mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de30df446d | ||
|
|
b5b45c8474 | ||
|
|
b98316a705 | ||
|
|
f2d9e0e8ea | ||
|
|
f5abaac8b7 | ||
|
|
0bb4f58222 | ||
|
|
4453afba89 | ||
|
|
96c8117135 | ||
|
|
1830ae2321 | ||
|
|
7af94a9d2a | ||
|
|
6d10c26c5d | ||
|
|
681f1a49a5 | ||
|
|
b750171593 | ||
|
|
02a019632b | ||
|
|
385d381cf1 | ||
|
|
48e8d76f21 | ||
|
|
d5336b2796 | ||
|
|
cb1b2bf5ca | ||
|
|
6c38cd360b | ||
|
|
4c2ca22cb2 | ||
|
|
cd177ff476 | ||
|
|
1ea3b4b3c5 | ||
|
|
8df3a9227f | ||
|
|
583695c228 | ||
|
|
455215290f | ||
|
|
5373345a3c | ||
|
|
e17b96d864 | ||
|
|
3ec4d274c4 | ||
|
|
611f8789da | ||
|
|
8e01d62150 | ||
|
|
f55662300a | ||
|
|
8de6ec27b8 | ||
|
|
2b8b626f69 | ||
|
|
d81fdb0f9c | ||
|
|
38406ee586 | ||
|
|
f2fdd6e6d3 | ||
|
|
ee3668006d | ||
|
|
7b4265470a | ||
|
|
9c9897706b | ||
|
|
9e8ad44cdf | ||
|
|
a6d82e0fc3 | ||
|
|
62ae3de488 | ||
|
|
dff094301a | ||
|
|
69aefc16f6 | ||
|
|
0a2ae30034 | ||
|
|
8b5be309fe | ||
|
|
e16eec8680 | ||
|
|
60f4606c9d | ||
|
|
c67fe04d3c | ||
|
|
9b4db98ed9 | ||
|
|
151c58d0ef |
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
README.md
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -34,4 +34,4 @@ body:
|
||||
id: screens
|
||||
attributes:
|
||||
label: Relevant screenshots (optional)
|
||||
description: Please upload any screenshots that may help us reproduce and/or understand the issue.
|
||||
description: Please upload any screenshots that may help us reproduce and/or understand the issue.
|
||||
|
||||
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -3,8 +3,14 @@ name: Go Build
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
@@ -4,6 +4,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main # Monitor the main branch
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
|
||||
permissions:
|
||||
contents: write # Ensure the workflow has write permissions
|
||||
@@ -38,7 +41,10 @@ jobs:
|
||||
minor=$(echo "$latest_tag" | cut -d. -f2)
|
||||
patch=$(echo "$latest_tag" | cut -d. -f3)
|
||||
new_patch=$((patch + 1))
|
||||
new_tag="v${major}.${minor}.${new_patch}"
|
||||
new_version="${major}.${minor}.${new_patch}"
|
||||
new_tag="v${new_version}"
|
||||
echo "New version is: $new_version"
|
||||
echo "new_version=$new_version" >> $GITHUB_ENV # Save the new version to environment file
|
||||
echo "New tag is: $new_tag"
|
||||
echo "new_tag=$new_tag" >> $GITHUB_ENV # Save the new tag to environment file
|
||||
|
||||
@@ -48,9 +54,14 @@ jobs:
|
||||
echo "" >> version.go
|
||||
echo "var version = \"${{ env.new_tag }}\"" >> version.go
|
||||
|
||||
- name: Update version.nix file
|
||||
run: |
|
||||
echo "\"${{ env.new_version }}\"" > pkgs/fabric/version.nix
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git add version.go
|
||||
git add pkgs/fabric/version.nix
|
||||
if ! git diff --staged --quiet; then
|
||||
git commit -m "Update version to ${{ env.new_tag }} and commit $commit_hash"
|
||||
else
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,7 @@
|
||||
# Nix
|
||||
.direnv
|
||||
result
|
||||
|
||||
# macOS local stores
|
||||
.DS_Store
|
||||
|
||||
@@ -161,4 +165,4 @@ cython_debug/
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
#.idea/
|
||||
|
||||
41
Dockerfile
Normal file
41
Dockerfile
Normal file
@@ -0,0 +1,41 @@
|
||||
# Use official golang image as builder
|
||||
FROM golang:1.22.5-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy go mod and sum files
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
# Download dependencies
|
||||
RUN go mod download
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o fabric
|
||||
|
||||
# Use scratch as final base image
|
||||
FROM alpine:latest
|
||||
|
||||
# Copy the binary from builder
|
||||
COPY --from=builder /app/fabric /fabric
|
||||
|
||||
# Copy patterns directory
|
||||
COPY patterns /patterns
|
||||
|
||||
# Ensure clean config directory and copy ENV file
|
||||
RUN rm -rf /root/.config/fabric && \
|
||||
mkdir -p /root/.config/fabric
|
||||
COPY ENV /root/.config/fabric/.env
|
||||
|
||||
# Add debug commands
|
||||
RUN ls -la /root/.config/fabric/
|
||||
|
||||
# Expose port 8080
|
||||
EXPOSE 8080
|
||||
|
||||
# Run the binary with debug output
|
||||
ENTRYPOINT ["/fabric"]
|
||||
CMD ["--serve"]
|
||||
9
ENV
Normal file
9
ENV
Normal file
@@ -0,0 +1,9 @@
|
||||
DEFAULT_VENDOR=OpenRouter
|
||||
DEFAULT_MODEL=openai/gpt-3.5-turbo-0125
|
||||
DEFAULT_MODEL_CONTEXT_LENGTH=128K
|
||||
PATTERNS_LOADER_GIT_REPO_URL=https://github.com/danielmiessler/fabric.git
|
||||
PATTERNS_LOADER_GIT_REPO_PATTERNS_FOLDER=patterns
|
||||
OPENROUTER_API_KEY=sk-or-v1-
|
||||
OPENROUTER_API_BASE_URL=https://openrouter.ai/api/v1
|
||||
YOUTUBE_API_KEY=AIzaS
|
||||
JINA_AI_API_KEY=jina_57
|
||||
@@ -197,7 +197,7 @@ Then [set your environmental variables](#environmental-variables) as shown above
|
||||
|
||||
The great thing about Go is that it's super easy to upgrade. Just run the same command you used to install it in the first place and you'll always get the latest version.
|
||||
```bash
|
||||
go install -ldflags "-X main.version=$(git describe --tags --always)" github.com/danielmiessler/fabric@latest
|
||||
go install github.com/danielmiessler/fabric@latest
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -217,6 +217,7 @@ Application Options:
|
||||
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
|
||||
-C, --context= Choose a context from the available contexts
|
||||
--session= Choose a session from the available sessions
|
||||
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
|
||||
-S, --setup Run setup for all reconfigurable parts of fabric
|
||||
-t, --temperature= Set temperature (default: 0.7)
|
||||
-T, --topp= Set top P (default: 0.9)
|
||||
@@ -358,7 +359,7 @@ This will create a PDF file named `output.pdf` in the current directory.
|
||||
To install `to_pdf`, install it the same way as you install Fabric, just with a different repo name.
|
||||
|
||||
```bash
|
||||
go install github.com/danielmiessler/fabric/to_pdf@latest
|
||||
go install github.com/danielmiessler/fabric/plugins/tools/to_pdf@latest
|
||||
```
|
||||
|
||||
Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on your system, as `to_pdf` requires `pdflatex` to be available in your system's PATH.
|
||||
|
||||
134
cli/cli.go
134
cli/cli.go
@@ -2,15 +2,18 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/youtube"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/core"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/converter"
|
||||
"github.com/danielmiessler/fabric/restapi"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Cli Controls the cli. It takes in the flags and runs the appropriate functions
|
||||
@@ -133,6 +136,8 @@ func Cli(version string) (err error) {
|
||||
|
||||
// if none of the above currentFlags are set, run the initiate chat function
|
||||
|
||||
var messageTools string
|
||||
|
||||
if currentFlags.YouTube != "" {
|
||||
if registry.YouTube.IsConfigured() == false {
|
||||
err = fmt.Errorf("YouTube is not configured, please run the setup procedure")
|
||||
@@ -140,41 +145,40 @@ func Cli(version string) (err error) {
|
||||
}
|
||||
|
||||
var videoId string
|
||||
if videoId, err = registry.YouTube.GetVideoId(currentFlags.YouTube); err != nil {
|
||||
var playlistId string
|
||||
if videoId, playlistId, err = registry.YouTube.GetVideoOrPlaylistId(currentFlags.YouTube); err != nil {
|
||||
return
|
||||
} else if (videoId == "" || currentFlags.YouTubePlaylist) && playlistId != "" {
|
||||
if currentFlags.Output != "" {
|
||||
err = registry.YouTube.FetchAndSavePlaylist(playlistId, currentFlags.Output)
|
||||
} else {
|
||||
var videos []*youtube.VideoMeta
|
||||
if videos, err = registry.YouTube.FetchPlaylistVideos(playlistId); err != nil {
|
||||
err = fmt.Errorf("error fetching playlist videos: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, video := range videos {
|
||||
var message string
|
||||
if message, err = processYoutubeVideo(currentFlags, registry, video.Id); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !currentFlags.IsChatRequest() {
|
||||
if err = WriteOutput(message, fmt.Sprintf("%v.md", video.TitleNormalized)); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
messageTools = AppendMessage(messageTools, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !currentFlags.YouTubeComments || currentFlags.YouTubeTranscript {
|
||||
var transcript string
|
||||
var language = "en"
|
||||
if currentFlags.Language != "" || registry.Language.DefaultLanguage.Value != "" {
|
||||
if currentFlags.Language != "" {
|
||||
language = currentFlags.Language
|
||||
} else {
|
||||
language = registry.Language.DefaultLanguage.Value
|
||||
}
|
||||
}
|
||||
if transcript, err = registry.YouTube.GrabTranscript(videoId, language); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
currentFlags.AppendMessage(transcript)
|
||||
}
|
||||
|
||||
if currentFlags.YouTubeComments {
|
||||
var comments []string
|
||||
if comments, err = registry.YouTube.GrabComments(videoId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
commentsString := strings.Join(comments, "\n")
|
||||
|
||||
currentFlags.AppendMessage(commentsString)
|
||||
}
|
||||
|
||||
messageTools, err = processYoutubeVideo(currentFlags, registry, videoId)
|
||||
if !currentFlags.IsChatRequest() {
|
||||
// if the pattern flag is not set, we wanted only to grab the transcript or comments
|
||||
fmt.Println(currentFlags.Message)
|
||||
err = currentFlags.WriteOutput(messageTools)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -186,8 +190,7 @@ func Cli(version string) (err error) {
|
||||
if website, err = registry.Jina.ScrapeURL(currentFlags.ScrapeURL); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
currentFlags.AppendMessage(website)
|
||||
messageTools = AppendMessage(messageTools, website)
|
||||
}
|
||||
|
||||
// Check if the scrape_question flag is set and call ScrapeQuestion
|
||||
@@ -197,23 +200,30 @@ func Cli(version string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
currentFlags.AppendMessage(website)
|
||||
messageTools = AppendMessage(messageTools, website)
|
||||
}
|
||||
|
||||
if !currentFlags.IsChatRequest() {
|
||||
// if the pattern flag is not set, we wanted only to grab the url or get the answer to the question
|
||||
fmt.Println(currentFlags.Message)
|
||||
err = currentFlags.WriteOutput(messageTools)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if messageTools != "" {
|
||||
currentFlags.AppendMessage(messageTools)
|
||||
}
|
||||
|
||||
var chatter *core.Chatter
|
||||
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.Stream, currentFlags.DryRun); err != nil {
|
||||
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.ModelContextLength, currentFlags.Stream, currentFlags.DryRun); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var session *fsdb.Session
|
||||
chatReq := currentFlags.BuildChatRequest(strings.Join(os.Args[1:], " "))
|
||||
var chatReq *common.ChatRequest
|
||||
if chatReq, err = currentFlags.BuildChatRequest(strings.Join(os.Args[1:], " ")); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if chatReq.Language == "" {
|
||||
chatReq.Language = registry.Language.DefaultLanguage.Value
|
||||
}
|
||||
@@ -246,3 +256,43 @@ func Cli(version string) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func processYoutubeVideo(
|
||||
flags *Flags, registry *core.PluginRegistry, videoId string) (message string, err error) {
|
||||
|
||||
if !flags.YouTubeComments || flags.YouTubeTranscript {
|
||||
var transcript string
|
||||
var language = "en"
|
||||
if flags.Language != "" || registry.Language.DefaultLanguage.Value != "" {
|
||||
if flags.Language != "" {
|
||||
language = flags.Language
|
||||
} else {
|
||||
language = registry.Language.DefaultLanguage.Value
|
||||
}
|
||||
}
|
||||
if transcript, err = registry.YouTube.GrabTranscript(videoId, language); err != nil {
|
||||
return
|
||||
}
|
||||
message = AppendMessage(message, transcript)
|
||||
}
|
||||
|
||||
if flags.YouTubeComments {
|
||||
var comments []string
|
||||
if comments, err = registry.YouTube.GrabComments(videoId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
commentsString := strings.Join(comments, "\n")
|
||||
|
||||
message = AppendMessage(message, commentsString)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func WriteOutput(message string, outputFile string) (err error) {
|
||||
fmt.Println(message)
|
||||
if outputFile != "" {
|
||||
err = CreateOutputFile(message, outputFile)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
125
cli/flags.go
125
cli/flags.go
@@ -6,10 +6,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Flags create flags struct. the users flags go into this, this will be passed to the chat struct in cli
|
||||
@@ -18,6 +21,7 @@ type Flags struct {
|
||||
PatternVariables map[string]string `short:"v" long:"variable" description:"Values for pattern variables, e.g. -v=#role:expert -v=#points:30"`
|
||||
Context string `short:"C" long:"context" description:"Choose a context from the available contexts" default:""`
|
||||
Session string `long:"session" description:"Choose a session from the available sessions"`
|
||||
Attachments []string `short:"a" long:"attachment" description:"Attachment path or URL (e.g. for OpenAI image recognition messages)"`
|
||||
Setup bool `short:"S" long:"setup" description:"Run setup for all reconfigurable parts of fabric"`
|
||||
Temperature float64 `short:"t" long:"temperature" description:"Set temperature" default:"0.7"`
|
||||
TopP float64 `short:"T" long:"topp" description:"Set top P" default:"0.9"`
|
||||
@@ -30,14 +34,16 @@ type Flags struct {
|
||||
ListAllContexts bool `short:"x" long:"listcontexts" description:"List all contexts"`
|
||||
ListAllSessions bool `short:"X" long:"listsessions" description:"List all sessions"`
|
||||
UpdatePatterns bool `short:"U" long:"updatepatterns" description:"Update patterns"`
|
||||
Message string `hidden:"true" description:"Message to send to chat"`
|
||||
Message string `hidden:"true" description:"Messages to send to chat"`
|
||||
Copy bool `short:"c" long:"copy" description:"Copy to clipboard"`
|
||||
Model string `short:"m" long:"model" description:"Choose model"`
|
||||
ModelContextLength int `long:"modelContextLength" description:"Model context length (only affects ollama)"`
|
||||
Output string `short:"o" long:"output" description:"Output to file" default:""`
|
||||
OutputSession bool `long:"output-session" description:"Output the entire session (also a temporary one) to the output file"`
|
||||
LatestPatterns string `short:"n" long:"latest" description:"Number of latest patterns to list" default:"0"`
|
||||
ChangeDefaultModel bool `short:"d" long:"changeDefaultModel" description:"Change default model"`
|
||||
YouTube string `short:"y" long:"youtube" description:"YouTube video \"URL\" to grab transcript, comments from it and send to chat"`
|
||||
YouTube string `short:"y" long:"youtube" description:"YouTube video or play list \"URL\" to grab transcript, comments from it and send to chat or print it put to the console and store it in the output file"`
|
||||
YouTubePlaylist bool `long:"playlist" description:"Prefer playlist over video if both ids are present in the URL"`
|
||||
YouTubeTranscript bool `long:"transcript" description:"Grab transcript from YouTube video and send to chat (it used per default)."`
|
||||
YouTubeComments bool `long:"comments" description:"Grab comments from YouTube video and send to chat"`
|
||||
Language string `short:"g" long:"language" description:"Specify the Language Code for the chat, e.g. -g=en -g=zh" default:""`
|
||||
@@ -67,16 +73,19 @@ func Init() (ret *Flags, err error) {
|
||||
}
|
||||
|
||||
info, _ := os.Stdin.Stat()
|
||||
hasStdin := (info.Mode() & os.ModeCharDevice) == 0
|
||||
pipedToStdin := (info.Mode() & os.ModeCharDevice) == 0
|
||||
|
||||
// takes input from stdin if it exists, otherwise takes input from args (the last argument)
|
||||
if hasStdin {
|
||||
if pipedToStdin {
|
||||
//fmt.Printf("piped: %v\n", args)
|
||||
if message, err = readStdin(); err != nil {
|
||||
return
|
||||
}
|
||||
} else if len(args) > 0 {
|
||||
//fmt.Printf("no piped: %v\n", args)
|
||||
message = args[len(args)-1]
|
||||
} else {
|
||||
//fmt.Printf("no data: %v\n", args)
|
||||
message = ""
|
||||
}
|
||||
ret.Message = message
|
||||
@@ -85,46 +94,95 @@ func Init() (ret *Flags, err error) {
|
||||
}
|
||||
|
||||
// readStdin reads from stdin and returns the input as a string or an error
|
||||
func readStdin() (string, error) {
|
||||
func readStdin() (ret string, err error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
var input string
|
||||
var sb strings.Builder
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
sb.WriteString(line)
|
||||
break
|
||||
}
|
||||
return "", fmt.Errorf("error reading from stdin: %w", err)
|
||||
return "", fmt.Errorf("error reading piped message from stdin: %w", err)
|
||||
}
|
||||
input += line
|
||||
sb.WriteString(line)
|
||||
}
|
||||
return input, nil
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
func (o *Flags) BuildChatOptions() (ret *common.ChatOptions) {
|
||||
ret = &common.ChatOptions{
|
||||
Temperature: o.Temperature,
|
||||
TopP: o.TopP,
|
||||
PresencePenalty: o.PresencePenalty,
|
||||
FrequencyPenalty: o.FrequencyPenalty,
|
||||
Raw: o.Raw,
|
||||
Seed: o.Seed,
|
||||
Temperature: o.Temperature,
|
||||
TopP: o.TopP,
|
||||
PresencePenalty: o.PresencePenalty,
|
||||
FrequencyPenalty: o.FrequencyPenalty,
|
||||
Raw: o.Raw,
|
||||
Seed: o.Seed,
|
||||
ModelContextLength: o.ModelContextLength,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest) {
|
||||
func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest, err error) {
|
||||
ret = &common.ChatRequest{
|
||||
ContextName: o.Context,
|
||||
SessionName: o.Session,
|
||||
PatternName: o.Pattern,
|
||||
PatternVariables: o.PatternVariables,
|
||||
Message: o.Message,
|
||||
Meta: Meta,
|
||||
}
|
||||
|
||||
var message *goopenai.ChatCompletionMessage
|
||||
if o.Attachments == nil || len(o.Attachments) == 0 {
|
||||
if o.Message != "" {
|
||||
message = &goopenai.ChatCompletionMessage{
|
||||
Role: goopenai.ChatMessageRoleUser,
|
||||
Content: strings.TrimSpace(o.Message),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message = &goopenai.ChatCompletionMessage{
|
||||
Role: goopenai.ChatMessageRoleUser,
|
||||
}
|
||||
|
||||
if o.Message != "" {
|
||||
message.MultiContent = append(message.MultiContent, goopenai.ChatMessagePart{
|
||||
Type: goopenai.ChatMessagePartTypeText,
|
||||
Text: strings.TrimSpace(o.Message),
|
||||
})
|
||||
}
|
||||
|
||||
for _, attachmentValue := range o.Attachments {
|
||||
var attachment *common.Attachment
|
||||
if attachment, err = common.NewAttachment(attachmentValue); err != nil {
|
||||
return
|
||||
}
|
||||
url := attachment.URL
|
||||
if url == nil {
|
||||
var base64Image string
|
||||
if base64Image, err = attachment.Base64Content(); err != nil {
|
||||
return
|
||||
}
|
||||
var mimeType string
|
||||
if mimeType, err = attachment.ResolveType(); err != nil {
|
||||
return
|
||||
}
|
||||
dataURL := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Image)
|
||||
url = &dataURL
|
||||
}
|
||||
message.MultiContent = append(message.MultiContent, goopenai.ChatMessagePart{
|
||||
Type: goopenai.ChatMessagePartTypeImageURL,
|
||||
ImageURL: &goopenai.ChatMessageImageURL{
|
||||
URL: *url,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
ret.Message = message
|
||||
|
||||
if o.Language != "" {
|
||||
langTag, err := language.Parse(o.Language)
|
||||
if err == nil {
|
||||
if langTag, langErr := language.Parse(o.Language); langErr == nil {
|
||||
ret.Language = langTag.String()
|
||||
}
|
||||
}
|
||||
@@ -132,15 +190,28 @@ func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest) {
|
||||
}
|
||||
|
||||
func (o *Flags) AppendMessage(message string) {
|
||||
if o.Message != "" {
|
||||
o.Message = o.Message + "\n" + message
|
||||
} else {
|
||||
o.Message = message
|
||||
}
|
||||
o.Message = AppendMessage(o.Message, message)
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Flags) IsChatRequest() (ret bool) {
|
||||
ret = o.Message != "" || o.Context != ""
|
||||
ret = o.Message != "" || len(o.Attachments) > 0 || o.Context != "" || o.Session != "" || o.Pattern != ""
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Flags) WriteOutput(message string) (err error) {
|
||||
fmt.Println(message)
|
||||
if o.Output != "" {
|
||||
err = CreateOutputFile(message, o.Output)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func AppendMessage(message string, newMessage string) (ret string) {
|
||||
if message != "" {
|
||||
ret = message + "\n" + newMessage
|
||||
} else {
|
||||
ret = newMessage
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -87,22 +87,3 @@ func TestBuildChatOptionsDefaultSeed(t *testing.T) {
|
||||
options := flags.BuildChatOptions()
|
||||
assert.Equal(t, expectedOptions, options)
|
||||
}
|
||||
|
||||
func TestBuildChatRequest(t *testing.T) {
|
||||
flags := &Flags{
|
||||
Context: "test-context",
|
||||
Session: "test-session",
|
||||
Pattern: "test-pattern",
|
||||
Message: "test-message",
|
||||
}
|
||||
|
||||
expectedRequest := &common.ChatRequest{
|
||||
ContextName: "test-context",
|
||||
SessionName: "test-session",
|
||||
PatternName: "test-pattern",
|
||||
Message: "test-message",
|
||||
Meta: "test",
|
||||
}
|
||||
request := flags.BuildChatRequest("test")
|
||||
assert.Equal(t, expectedRequest, request)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ func CreateOutputFile(message string, fileName string) (err error) {
|
||||
defer file.Close()
|
||||
if _, err = file.WriteString(message); err != nil {
|
||||
err = fmt.Errorf("error writing to file: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\n\n... written to %s\n", fileName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
170
common/attachment.go
Normal file
170
common/attachment.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Attachment struct {
|
||||
Type *string `json:"type,omitempty"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
URL *string `json:"url,omitempty"`
|
||||
Content []byte `json:"content,omitempty"`
|
||||
ID *string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (a *Attachment) GetId() (ret string, err error) {
|
||||
if a.ID == nil {
|
||||
var hash string
|
||||
if a.Content != nil {
|
||||
hash = fmt.Sprintf("%x", sha256.Sum256(a.Content))
|
||||
} else if a.Path != nil {
|
||||
var content []byte
|
||||
if content, err = ioutil.ReadFile(*a.Path); err != nil {
|
||||
return
|
||||
}
|
||||
hash = fmt.Sprintf("%x", sha256.Sum256(content))
|
||||
} else if a.URL != nil {
|
||||
data := map[string]string{"url": *a.URL}
|
||||
var jsonData []byte
|
||||
if jsonData, err = json.Marshal(data); err != nil {
|
||||
return
|
||||
}
|
||||
hash = fmt.Sprintf("%x", sha256.Sum256(jsonData))
|
||||
}
|
||||
a.ID = &hash
|
||||
}
|
||||
ret = *a.ID
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Attachment) ResolveType() (ret string, err error) {
|
||||
if a.Type != nil {
|
||||
ret = *a.Type
|
||||
return
|
||||
}
|
||||
if a.Path != nil {
|
||||
var mime *mimetype.MIME
|
||||
if mime, err = mimetype.DetectFile(*a.Path); err != nil {
|
||||
return
|
||||
}
|
||||
ret = mime.String()
|
||||
return
|
||||
}
|
||||
if a.URL != nil {
|
||||
var resp *http.Response
|
||||
if resp, err = http.Head(*a.URL); err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
ret = resp.Header.Get("Content-Type")
|
||||
return
|
||||
}
|
||||
if a.Content != nil {
|
||||
ret = mimetype.Detect(a.Content).String()
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("attachment has no type and no content to derive it from")
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Attachment) ContentBytes() (ret []byte, err error) {
|
||||
if a.Content != nil {
|
||||
ret = a.Content
|
||||
return
|
||||
}
|
||||
if a.Path != nil {
|
||||
if ret, err = ioutil.ReadFile(*a.Path); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if a.URL != nil {
|
||||
var resp *http.Response
|
||||
if resp, err = http.Get(*a.URL); err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if ret, err = ioutil.ReadAll(resp.Body); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("no content available")
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Attachment) Base64Content() (ret string, err error) {
|
||||
var content []byte
|
||||
if content, err = a.ContentBytes(); err != nil {
|
||||
return
|
||||
}
|
||||
ret = base64.StdEncoding.EncodeToString(content)
|
||||
return
|
||||
}
|
||||
|
||||
func NewAttachment(value string) (ret *Attachment, err error) {
|
||||
if isURL(value) {
|
||||
var mimeType string
|
||||
if mimeType, err = detectMimeTypeFromURL(value); err != nil {
|
||||
return
|
||||
}
|
||||
ret = &Attachment{
|
||||
Type: &mimeType,
|
||||
URL: &value,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var absPath string
|
||||
if absPath, err = filepath.Abs(value); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = os.Stat(absPath); os.IsNotExist(err) {
|
||||
err = fmt.Errorf("file %s does not exist", value)
|
||||
return
|
||||
}
|
||||
|
||||
var mimeType string
|
||||
if mimeType, err = detectMimeTypeFromFile(absPath); err != nil {
|
||||
return
|
||||
}
|
||||
ret = &Attachment{
|
||||
Type: &mimeType,
|
||||
Path: &absPath,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func detectMimeTypeFromURL(url string) (string, error) {
|
||||
resp, err := http.Head(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
mimeType := resp.Header.Get("Content-Type")
|
||||
if mimeType == "" {
|
||||
return "", fmt.Errorf("could not determine mimetype of URL")
|
||||
}
|
||||
return mimeType, nil
|
||||
}
|
||||
|
||||
func detectMimeTypeFromFile(path string) (string, error) {
|
||||
mime, err := mimetype.DetectFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return mime.String(), nil
|
||||
}
|
||||
|
||||
func isURL(value string) bool {
|
||||
return bytes.Contains([]byte(value), []byte("://"))
|
||||
}
|
||||
@@ -4,33 +4,29 @@ import goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
const ChatMessageRoleMeta = "meta"
|
||||
|
||||
type Message struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type ChatRequest struct {
|
||||
ContextName string
|
||||
SessionName string
|
||||
PatternName string
|
||||
PatternVariables map[string]string
|
||||
Message string
|
||||
Message *goopenai.ChatCompletionMessage
|
||||
Language string
|
||||
Meta string
|
||||
}
|
||||
|
||||
type ChatOptions struct {
|
||||
Model string
|
||||
Temperature float64
|
||||
TopP float64
|
||||
PresencePenalty float64
|
||||
FrequencyPenalty float64
|
||||
Raw bool
|
||||
Seed int
|
||||
Model string
|
||||
Temperature float64
|
||||
TopP float64
|
||||
PresencePenalty float64
|
||||
FrequencyPenalty float64
|
||||
Raw bool
|
||||
Seed int
|
||||
ModelContextLength int
|
||||
}
|
||||
|
||||
// NormalizeMessages remove empty messages and ensure messages order user-assist-user
|
||||
func NormalizeMessages(msgs []*Message, defaultUserMessage string) (ret []*Message) {
|
||||
func NormalizeMessages(msgs []*goopenai.ChatCompletionMessage, defaultUserMessage string) (ret []*goopenai.ChatCompletionMessage) {
|
||||
// Iterate over messages to enforce the odd position rule for user messages
|
||||
fullMessageIndex := 0
|
||||
for _, message := range msgs {
|
||||
@@ -41,7 +37,7 @@ func NormalizeMessages(msgs []*Message, defaultUserMessage string) (ret []*Messa
|
||||
|
||||
// Ensure, that each odd position shall be a user message
|
||||
if fullMessageIndex%2 == 0 && message.Role != goopenai.ChatMessageRoleUser {
|
||||
ret = append(ret, &Message{Role: goopenai.ChatMessageRoleUser, Content: defaultUserMessage})
|
||||
ret = append(ret, &goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleUser, Content: defaultUserMessage})
|
||||
fullMessageIndex++
|
||||
}
|
||||
ret = append(ret, message)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestNormalizeMessages(t *testing.T) {
|
||||
msgs := []*Message{
|
||||
msgs := []*goopenai.ChatCompletionMessage{
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
|
||||
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: ""},
|
||||
@@ -15,7 +15,7 @@ func TestNormalizeMessages(t *testing.T) {
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
|
||||
}
|
||||
|
||||
expected := []*Message{
|
||||
expected := []*goopenai.ChatCompletionMessage{
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
|
||||
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
|
||||
|
||||
@@ -3,11 +3,13 @@ package core
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const NoSessionPatternUserMessages = "no session, pattern or user messages provided"
|
||||
@@ -18,8 +20,9 @@ type Chatter struct {
|
||||
Stream bool
|
||||
DryRun bool
|
||||
|
||||
model string
|
||||
vendor ai.Vendor
|
||||
model string
|
||||
modelContextLength int
|
||||
vendor ai.Vendor
|
||||
}
|
||||
|
||||
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *fsdb.Session, err error) {
|
||||
@@ -31,6 +34,10 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
|
||||
opts.Model = o.model
|
||||
}
|
||||
|
||||
if opts.ModelContextLength == 0 {
|
||||
opts.ModelContextLength = o.modelContextLength
|
||||
}
|
||||
|
||||
message := ""
|
||||
|
||||
if o.Stream {
|
||||
@@ -57,7 +64,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
|
||||
return
|
||||
}
|
||||
|
||||
session.Append(&common.Message{Role: goopenai.ChatMessageRoleAssistant, Content: message})
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleAssistant, Content: message})
|
||||
|
||||
if session.Name != "" {
|
||||
err = o.db.Sessions.SaveSession(session)
|
||||
@@ -78,7 +85,7 @@ func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *
|
||||
}
|
||||
|
||||
if request.Meta != "" {
|
||||
session.Append(&common.Message{Role: common.ChatMessageRoleMeta, Content: request.Meta})
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: common.ChatMessageRoleMeta, Content: request.Meta})
|
||||
}
|
||||
|
||||
var contextContent string
|
||||
@@ -108,23 +115,27 @@ func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *
|
||||
if request.Language != "" {
|
||||
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, request.Language)
|
||||
}
|
||||
userMessage := strings.TrimSpace(request.Message)
|
||||
|
||||
if raw {
|
||||
// use the user role instead of the system role in raw mode
|
||||
message := systemMessage + userMessage
|
||||
if message != "" {
|
||||
session.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: message})
|
||||
if request.Message != nil {
|
||||
if systemMessage != "" {
|
||||
request.Message.Content = systemMessage + request.Message.Content
|
||||
}
|
||||
} else {
|
||||
if systemMessage != "" {
|
||||
request.Message = &goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if systemMessage != "" {
|
||||
session.Append(&common.Message{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
|
||||
}
|
||||
if userMessage != "" {
|
||||
session.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: userMessage})
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
|
||||
}
|
||||
}
|
||||
|
||||
if request.Message != nil {
|
||||
session.Append(request.Message)
|
||||
}
|
||||
|
||||
if session.IsEmpty() {
|
||||
session = nil
|
||||
err = fmt.Errorf(NoSessionPatternUserMessages)
|
||||
|
||||
@@ -3,15 +3,15 @@ package core
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/azure"
|
||||
"github.com/danielmiessler/fabric/plugins/tools"
|
||||
"github.com/samber/lo"
|
||||
"strconv"
|
||||
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/anthropic"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/azure"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/dryrun"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/gemini"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/groq"
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/danielmiessler/fabric/plugins/ai/openrouter"
|
||||
"github.com/danielmiessler/fabric/plugins/ai/siliconcloud"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/tools"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/jina"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/lang"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/youtube"
|
||||
@@ -164,7 +165,7 @@ func (o *PluginRegistry) Configure() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) GetChatter(model string, stream bool, dryRun bool) (ret *Chatter, err error) {
|
||||
func (o *PluginRegistry) GetChatter(model string, modelContextLength int, stream bool, dryRun bool) (ret *Chatter, err error) {
|
||||
ret = &Chatter{
|
||||
db: o.Db,
|
||||
Stream: stream,
|
||||
@@ -172,9 +173,20 @@ func (o *PluginRegistry) GetChatter(model string, stream bool, dryRun bool) (ret
|
||||
}
|
||||
|
||||
defaultModel := o.Defaults.Model.Value
|
||||
defaultModelContextLength, err := strconv.Atoi(o.Defaults.ModelContextLength.Value)
|
||||
defaultVendor := o.Defaults.Vendor.Value
|
||||
vendorManager := o.VendorManager
|
||||
|
||||
if err != nil {
|
||||
defaultModelContextLength = 0
|
||||
err = nil
|
||||
}
|
||||
|
||||
ret.modelContextLength = modelContextLength
|
||||
if ret.modelContextLength == 0 {
|
||||
ret.modelContextLength = defaultModelContextLength
|
||||
}
|
||||
|
||||
if dryRun {
|
||||
ret.vendor = dryrun.NewClient()
|
||||
ret.model = model
|
||||
|
||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
fabric-api:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./ENV:/root/.config/fabric/.env:ro
|
||||
environment:
|
||||
- GIN_MODE=release
|
||||
119
flake.lock
generated
Normal file
119
flake.lock
generated
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gomod2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729448365,
|
||||
"narHash": "sha256-oquZeWTYWTr5IxfwEzgsxjtD8SSFZYLdO9DaQb70vNU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "gomod2nix",
|
||||
"rev": "5d387097aa716f35dd99d848dc26d8d5b62a104c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "gomod2nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1729665710,
|
||||
"narHash": "sha256-AlcmCXJZPIlO5dmFzV3V2XF6x/OpNWUV8Y/FMPGd8Z4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2768c7d042a37de65bb1b5b3268fc987e534c49d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"gomod2nix": "gomod2nix",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems_2",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729613947,
|
||||
"narHash": "sha256-XGOvuIPW1XRfPgHtGYXd5MAmJzZtOuwlfKDgxX5KT3s=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "aac86347fb5063960eccb19493e0cadcdb4205ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
71
flake.nix
Normal file
71
flake.nix
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
description = "Fabric is an open-source framework for augmenting humans using AI. It provides a modular framework for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
systems.url = "github:nix-systems/default";
|
||||
|
||||
treefmt-nix = {
|
||||
url = "github:numtide/treefmt-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
gomod2nix = {
|
||||
url = "github:nix-community/gomod2nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
systems,
|
||||
treefmt-nix,
|
||||
gomod2nix,
|
||||
...
|
||||
}:
|
||||
let
|
||||
forAllSystems = nixpkgs.lib.genAttrs (import systems);
|
||||
|
||||
treefmtEval = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
treefmt-nix.lib.evalModule pkgs ./treefmt.nix
|
||||
);
|
||||
in
|
||||
{
|
||||
formatter = forAllSystems (system: treefmtEval.${system}.config.build.wrapper);
|
||||
|
||||
checks = forAllSystems (system: {
|
||||
formatting = treefmtEval.${system}.config.build.check self;
|
||||
});
|
||||
|
||||
devShells = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
goEnv = gomod2nix.legacyPackages.${system}.mkGoEnv { pwd = ./.; };
|
||||
in
|
||||
import ./shell.nix {
|
||||
inherit pkgs goEnv;
|
||||
inherit (gomod2nix.legacyPackages.${system}) gomod2nix;
|
||||
}
|
||||
);
|
||||
|
||||
packages = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
{
|
||||
default = self.packages.${system}.fabric;
|
||||
fabric = pkgs.callPackage ./pkgs/fabric {
|
||||
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
60
go.mod
60
go.mod
@@ -5,55 +5,55 @@ go 1.22.5
|
||||
require (
|
||||
github.com/anaskhan96/soup v1.2.5
|
||||
github.com/atotto/clipboard v0.1.4
|
||||
github.com/gabriel-vasile/mimetype v1.4.6
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825
|
||||
github.com/go-shiori/go-readability v0.0.0-20241012063810-92284fa8a71f
|
||||
github.com/google/generative-ai-go v0.18.0
|
||||
github.com/jessevdk/go-flags v1.6.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/liushuangls/go-anthropic/v2 v2.8.0
|
||||
github.com/ollama/ollama v0.3.11
|
||||
github.com/liushuangls/go-anthropic/v2 v2.9.0
|
||||
github.com/ollama/ollama v0.3.14
|
||||
github.com/otiai10/copy v1.14.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/sashabaranov/go-openai v1.30.0
|
||||
github.com/sashabaranov/go-openai v1.32.5
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/text v0.19.0
|
||||
google.golang.org/api v0.197.0
|
||||
google.golang.org/api v0.203.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.115.1 // indirect
|
||||
cloud.google.com/go v0.116.0 // indirect
|
||||
cloud.google.com/go/ai v0.8.2 // indirect
|
||||
cloud.google.com/go/auth v0.9.4 // indirect
|
||||
cloud.google.com/go/auth v0.9.9 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.1 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudflare/circl v1.4.0 // indirect
|
||||
github.com/bytedance/sonic v1.12.3 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||
github.com/cloudflare/circl v1.5.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.2 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
@@ -63,12 +63,12 @@ require (
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
@@ -77,22 +77,22 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
|
||||
go.opentelemetry.io/otel v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.30.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
||||
golang.org/x/arch v0.11.0 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.66.2 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
129
go.sum
129
go.sum
@@ -1,16 +1,16 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ=
|
||||
cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc=
|
||||
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
|
||||
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
|
||||
cloud.google.com/go/ai v0.8.2 h1:LEaQwqBv+k2ybrcdTtCTc9OPZXoEdcQaGrfvDYS6Bnk=
|
||||
cloud.google.com/go/ai v0.8.2/go.mod h1:Wb3EUUGWwB6yHBaUf/+oxUq/6XbCaU1yh0GrwUS8lr4=
|
||||
cloud.google.com/go/auth v0.9.4 h1:DxF7imbEbiFu9+zdKC6cKBko1e8XeJnipNqIbWZ+kDI=
|
||||
cloud.google.com/go/auth v0.9.4/go.mod h1:SHia8n6//Ya940F1rLimhJCjjx7KE17t0ctFEci3HkA=
|
||||
cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ=
|
||||
cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
|
||||
cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs=
|
||||
cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
||||
cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc=
|
||||
cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0=
|
||||
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
|
||||
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
||||
cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc=
|
||||
cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
@@ -32,22 +32,23 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
|
||||
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
|
||||
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
|
||||
github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
|
||||
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc=
|
||||
github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -61,8 +62,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
@@ -71,8 +72,8 @@ github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
||||
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
@@ -88,14 +89,14 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c h1:wpkoddUomPfHiOziHZixGO5ZBS73cKqVzZipfrLmO1w=
|
||||
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c/go.mod h1:oVDCh3qjJMLVUSILBRwrm+Bc6RNXGZYtoh9xdvf1ffM=
|
||||
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825 h1:CpSi7xiWqGaAqVn/2MsbRoDmPwXMvvQUu3hLjX1QrOM=
|
||||
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825/go.mod h1:YWa00ashoPZMAOElrSn4E1cJErhDVU6PWAll4Hxzn+w=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/go-shiori/go-readability v0.0.0-20241012063810-92284fa8a71f h1:cypj7SJh+47G9J3VCPdMzT3uWcXWAWDJA54ErTfOigI=
|
||||
github.com/go-shiori/go-readability v0.0.0-20241012063810-92284fa8a71f/go.mod h1:YWa00ashoPZMAOElrSn4E1cJErhDVU6PWAll4Hxzn+w=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -145,8 +146,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -157,8 +158,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/liushuangls/go-anthropic/v2 v2.8.0 h1:0zH2jDNycbrlszxnLrG+Gx8vVT0yJAPWU4s3ZTkWzgI=
|
||||
github.com/liushuangls/go-anthropic/v2 v2.8.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek=
|
||||
github.com/liushuangls/go-anthropic/v2 v2.9.0 h1:uGtXaypQf4D79hZdmajPciBcHvz5Z7tdU77DLJ4siI4=
|
||||
github.com/liushuangls/go-anthropic/v2 v2.9.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
@@ -167,16 +168,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/ollama/ollama v0.3.11 h1:Fs1B5WjXYUvr5bkMZZpUJfiqIAxrymujRidFABwMeV8=
|
||||
github.com/ollama/ollama v0.3.11/go.mod h1:YrWoNkFnPOYsnDvsf/Ztb1wxU9/IXrNsQHqcxbY2r94=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/ollama/ollama v0.3.14 h1:e94+Fb1PDqmD3O90g5cqUSkSxfNm9U3fHMIyaKQ8aSc=
|
||||
github.com/ollama/ollama v0.3.14/go.mod h1:YrWoNkFnPOYsnDvsf/Ztb1wxU9/IXrNsQHqcxbY2r94=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -189,8 +190,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/sashabaranov/go-openai v1.30.0 h1:fHv9urGxABfm885xGWsXFSk5cksa+8dJ4jGli/UQQcI=
|
||||
github.com/sashabaranov/go-openai v1.30.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.32.5 h1:/eNVa8KzlE7mJdKPZDj6886MUzZQjoVHyn0sLvIt5qA=
|
||||
github.com/sashabaranov/go-openai v1.32.5/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
@@ -200,7 +201,6 @@ github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -209,7 +209,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
@@ -221,19 +220,18 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
|
||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
|
||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
||||
golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
|
||||
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
@@ -243,6 +241,8 @@ golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -312,8 +312,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -324,24 +324,24 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ=
|
||||
google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw=
|
||||
google.golang.org/api v0.203.0 h1:SrEeuwU3S11Wlscsn+LA1kb/Y5xT8uggJSkIhD08NAU=
|
||||
google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
|
||||
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -351,8 +351,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
@@ -367,4 +367,3 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
||||
270
gomod2nix.toml
Normal file
270
gomod2nix.toml
Normal file
@@ -0,0 +1,270 @@
|
||||
schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."cloud.google.com/go"]
|
||||
version = "v0.116.0"
|
||||
hash = "sha256-e62GvNveg3bRi4O+eBARqgQ2sinobx+SVGR9WE7jKgs="
|
||||
[mod."cloud.google.com/go/ai"]
|
||||
version = "v0.8.2"
|
||||
hash = "sha256-UtCuHChDsXlACXdlVSNFo8F/X8vAkmPoJyng3/oEFe0="
|
||||
[mod."cloud.google.com/go/auth"]
|
||||
version = "v0.9.9"
|
||||
hash = "sha256-kUrulQhYPM6cFhInFqTX/Dj1GVi+Ev1Ry7T+hiTmb38="
|
||||
[mod."cloud.google.com/go/auth/oauth2adapt"]
|
||||
version = "v0.2.4"
|
||||
hash = "sha256-GRXPQMHEEgeKhdCOBjoDL7+UW3yBdSei5ULuZGBE4tw="
|
||||
[mod."cloud.google.com/go/compute/metadata"]
|
||||
version = "v0.5.2"
|
||||
hash = "sha256-EtBj20lhjM3SJVKCp70GHMnsItwJ9gOyJOW91wugojc="
|
||||
[mod."cloud.google.com/go/longrunning"]
|
||||
version = "v0.6.2"
|
||||
hash = "sha256-X78JL1/YtXA7upOcTuNezq5TxjQyFxQ6OINrS8zzdEU="
|
||||
[mod."dario.cat/mergo"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-wcG6+x0k6KzOSlaPA+1RFxa06/RIAePJTAjjuhLbImw="
|
||||
[mod."github.com/Microsoft/go-winio"]
|
||||
version = "v0.6.2"
|
||||
hash = "sha256-tVNWDUMILZbJvarcl/E7tpSnkn7urqgSHa2Eaka5vSU="
|
||||
[mod."github.com/ProtonMail/go-crypto"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-Gflazvyv+457FpUTtPafJ+SdolYSalpsU0tragTxNi8="
|
||||
[mod."github.com/anaskhan96/soup"]
|
||||
version = "v1.2.5"
|
||||
hash = "sha256-t8yCyK2y7x2qaI/3Yw16q3zVFqu+3acLcPgTr1MIKWg="
|
||||
[mod."github.com/andybalholm/cascadia"]
|
||||
version = "v1.3.2"
|
||||
hash = "sha256-Nc9SkqJO/ecincVcUBFITy24TMmMGj5o0Q8EgdNhrEk="
|
||||
[mod."github.com/araddon/dateparse"]
|
||||
version = "v0.0.0-20210429162001-6b43995a97de"
|
||||
hash = "sha256-UuX84naeRGMsFOgIgRoBHG5sNy1CzBkWPKmd6VbLwFw="
|
||||
[mod."github.com/atotto/clipboard"]
|
||||
version = "v0.1.4"
|
||||
hash = "sha256-ZZ7U5X0gWOu8zcjZcWbcpzGOGdycwq0TjTFh/eZHjXk="
|
||||
[mod."github.com/bytedance/sonic"]
|
||||
version = "v1.12.3"
|
||||
hash = "sha256-cZicMhM/2D7HefuJ0xe7AJKh9du2O38HWs+3RNCpbZM="
|
||||
[mod."github.com/bytedance/sonic/loader"]
|
||||
version = "v0.2.1"
|
||||
hash = "sha256-+gPRZtBOJbAnXp/jdMlPmesc62JGH8akQ1UK9VRI7E4="
|
||||
[mod."github.com/cloudflare/circl"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-j7T4cfbfmhlbaO+kNKveTnk95JbkEOX0IVw8D9bGTkQ="
|
||||
[mod."github.com/cloudwego/base64x"]
|
||||
version = "v0.1.4"
|
||||
hash = "sha256-umCZR3iNmHFm+BC76kfpdcRG+pTQd6Jcu/c2kQDnyfw="
|
||||
[mod."github.com/cloudwego/iasm"]
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-TzIP2N3HOesXrKACsRr/ShcoqttwPGZPckIepsTyHOA="
|
||||
[mod."github.com/cyphar/filepath-securejoin"]
|
||||
version = "v0.3.4"
|
||||
hash = "sha256-I9dV5gtKk3hH39taAWxvvJEXMi4YoHSxeESVyjpl1MU="
|
||||
[mod."github.com/davecgh/go-spew"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
|
||||
[mod."github.com/emirpasic/gods"]
|
||||
version = "v1.18.1"
|
||||
hash = "sha256-hGDKddjLj+5dn2woHtXKUdd49/3xdsqnhx7VEdCu1m4="
|
||||
[mod."github.com/felixge/httpsnoop"]
|
||||
version = "v1.0.4"
|
||||
hash = "sha256-c1JKoRSndwwOyOxq9ddCe+8qn7mG9uRq2o/822x5O/c="
|
||||
[mod."github.com/gabriel-vasile/mimetype"]
|
||||
version = "v1.4.6"
|
||||
hash = "sha256-W/uPcE22Fduw1XmX8Ujf1S9SYVOcEoE1wzK4I0/vapw="
|
||||
[mod."github.com/gin-contrib/sse"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-zYbMTao+1F+385Lvsba9roLmmt9eYqr57sUWo0LCVhw="
|
||||
[mod."github.com/gin-gonic/gin"]
|
||||
version = "v1.10.0"
|
||||
hash = "sha256-esJasHrJtuTBwGPGAoc/XSb428J8va+tPGcZ0gTfsgc="
|
||||
[mod."github.com/go-git/gcfg"]
|
||||
version = "v1.5.1-0.20230307220236-3a3c6141e376"
|
||||
hash = "sha256-f4k0gSYuo0/q3WOoTxl2eFaj7WZpdz29ih6CKc8Ude8="
|
||||
[mod."github.com/go-git/go-billy/v5"]
|
||||
version = "v5.6.0"
|
||||
hash = "sha256-Hw+odNozpiixXqmsbahihdV+TBxpusm6/hDLngf7kUg="
|
||||
[mod."github.com/go-git/go-git/v5"]
|
||||
version = "v5.12.0"
|
||||
hash = "sha256-mD8EWOQ25FtKBWVSQhQ8V1Rr0tC/ySFZQ9GMDLRqwQU="
|
||||
[mod."github.com/go-logr/logr"]
|
||||
version = "v1.4.2"
|
||||
hash = "sha256-/W6qGilFlZNTb9Uq48xGZ4IbsVeSwJiAMLw4wiNYHLI="
|
||||
[mod."github.com/go-logr/stdr"]
|
||||
version = "v1.2.2"
|
||||
hash = "sha256-rRweAP7XIb4egtT1f2gkz4sYOu7LDHmcJ5iNsJUd0sE="
|
||||
[mod."github.com/go-playground/locales"]
|
||||
version = "v0.14.1"
|
||||
hash = "sha256-BMJGAexq96waZn60DJXZfByRHb8zA/JP/i6f/YrW9oQ="
|
||||
[mod."github.com/go-playground/universal-translator"]
|
||||
version = "v0.18.1"
|
||||
hash = "sha256-2/B2qP51zfiY+k8G0w0D03KXUc7XpWj6wKY7NjNP/9E="
|
||||
[mod."github.com/go-playground/validator/v10"]
|
||||
version = "v10.22.1"
|
||||
hash = "sha256-EsgeltH0ow6saxLvTFVtIyHVqWI3Fiu1AE2Qmnsmowg="
|
||||
[mod."github.com/go-shiori/dom"]
|
||||
version = "v0.0.0-20230515143342-73569d674e1c"
|
||||
hash = "sha256-4lm9KZfR2XnfZU9KTG+4jqLYZqbfL74AMO4y3dKpIbg="
|
||||
[mod."github.com/go-shiori/go-readability"]
|
||||
version = "v0.0.0-20241012063810-92284fa8a71f"
|
||||
hash = "sha256-NgciyWylVSjzkt5xWF1Xk1Xbxgq3PsHW5PZ8oifjZVY="
|
||||
[mod."github.com/goccy/go-json"]
|
||||
version = "v0.10.3"
|
||||
hash = "sha256-ZOzfwCXh+qp+hp+UnC0t422hUV0Cq5KANXkx8hcLp7s="
|
||||
[mod."github.com/gogs/chardet"]
|
||||
version = "v0.0.0-20211120154057-b7413eaefb8f"
|
||||
hash = "sha256-4MeqBJsh4U+ZEbfdDwdciTYMlQWkCil2KJbUxHjBSIo="
|
||||
[mod."github.com/golang/groupcache"]
|
||||
version = "v0.0.0-20210331224755-41bb18bfe9da"
|
||||
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
|
||||
[mod."github.com/google/generative-ai-go"]
|
||||
version = "v0.18.0"
|
||||
hash = "sha256-Ye+1rV3gzb2FG9ATq8cihlUiCynRv0eejMwsSfxOXcM="
|
||||
[mod."github.com/google/s2a-go"]
|
||||
version = "v0.1.8"
|
||||
hash = "sha256-H4jy3iElh82CTujW3UpaSvsdfN7fZHBLJ4Z4M7kiMSk="
|
||||
[mod."github.com/google/uuid"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
|
||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||
version = "v0.3.4"
|
||||
hash = "sha256-RVHWa0I68CTegjlXnM/GlishoZhmmwG4z+9KBucAJ1A="
|
||||
[mod."github.com/googleapis/gax-go/v2"]
|
||||
version = "v2.13.0"
|
||||
hash = "sha256-p1SEjRjI/SkWSBWjeptQ5M/Tgrcj8IiH/beXBYqRVko="
|
||||
[mod."github.com/jbenet/go-context"]
|
||||
version = "v0.0.0-20150711004518-d14ea06fba99"
|
||||
hash = "sha256-VANNCWNNpARH/ILQV9sCQsBWgyL2iFT+4AHZREpxIWE="
|
||||
[mod."github.com/jessevdk/go-flags"]
|
||||
version = "v1.6.1"
|
||||
hash = "sha256-Q5WFTgRxYio0+ay3sbQeBPKeJAFvOdiDVkaTVn3hoTA="
|
||||
[mod."github.com/joho/godotenv"]
|
||||
version = "v1.5.1"
|
||||
hash = "sha256-kA0osKfsc6Kp+nuGTRJyXZZlJt1D/kuEazKMWYCWcQ8="
|
||||
[mod."github.com/json-iterator/go"]
|
||||
version = "v1.1.12"
|
||||
hash = "sha256-To8A0h+lbfZ/6zM+2PpRpY3+L6725OPC66lffq6fUoM="
|
||||
[mod."github.com/kevinburke/ssh_config"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-Ta7ZOmyX8gG5tzWbY2oES70EJPfI90U7CIJS9EAce0s="
|
||||
[mod."github.com/klauspost/cpuid/v2"]
|
||||
version = "v2.2.8"
|
||||
hash = "sha256-/E58BnABQYxO+cmiue7OQqRLWkd/Lh8grX8DjTU4tk8="
|
||||
[mod."github.com/leodido/go-urn"]
|
||||
version = "v1.4.0"
|
||||
hash = "sha256-Q6kplWkY37Tzy6GOme3Wut40jFK4Izun+ij/BJvcEu0="
|
||||
[mod."github.com/liushuangls/go-anthropic/v2"]
|
||||
version = "v2.9.0"
|
||||
hash = "sha256-1bvwuPT5SaYrzKYiXpz0fjDgu3994Hs5MPXZUFPhCLI="
|
||||
[mod."github.com/mattn/go-isatty"]
|
||||
version = "v0.0.20"
|
||||
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
|
||||
[mod."github.com/modern-go/concurrent"]
|
||||
version = "v0.0.0-20180306012644-bacd9c7ef1dd"
|
||||
hash = "sha256-OTySieAgPWR4oJnlohaFTeK1tRaVp/b0d1rYY8xKMzo="
|
||||
[mod."github.com/modern-go/reflect2"]
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-+W9EIW7okXIXjWEgOaMh58eLvBZ7OshW2EhaIpNLSBU="
|
||||
[mod."github.com/ollama/ollama"]
|
||||
version = "v0.3.14"
|
||||
hash = "sha256-R+jWZzGokwWimPePIcUoZz6tDG2qHFeClgxhT7SEoqw="
|
||||
[mod."github.com/otiai10/copy"]
|
||||
version = "v1.14.0"
|
||||
hash = "sha256-xsaL1ddkPS544y0Jv7u/INUALBYmYq29ddWvysLXk4A="
|
||||
[mod."github.com/pelletier/go-toml/v2"]
|
||||
version = "v2.2.3"
|
||||
hash = "sha256-fE++SVgnCGdnFZoROHWuYjIR7ENl7k9KKxQrRTquv/o="
|
||||
[mod."github.com/pjbgf/sha1cd"]
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-kX9BdLh2dxtGNaDvc24NORO+C0AZ7JzbrXrtecCdB7w="
|
||||
[mod."github.com/pkg/errors"]
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw="
|
||||
[mod."github.com/pmezard/go-difflib"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
|
||||
[mod."github.com/samber/lo"]
|
||||
version = "v1.47.0"
|
||||
hash = "sha256-jMXexVTlPdZ40STRpBLv7b+BIRqdxxra12Pl2Mj7Nz8="
|
||||
[mod."github.com/sashabaranov/go-openai"]
|
||||
version = "v1.32.5"
|
||||
hash = "sha256-T56gcES0qMZCSL3uFi+G9vmfTk00QlMWONsMS+cxwR0="
|
||||
[mod."github.com/sergi/go-diff"]
|
||||
version = "v1.3.2-0.20230802210424-5b0b94c5c0d3"
|
||||
hash = "sha256-UcLU83CPMbSoKI8RLvLJ7nvGaE2xRSL1RjoHCVkMzUM="
|
||||
[mod."github.com/skeema/knownhosts"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-piR5IdfqxK9nxyErJ+IRDLnkaeNQwX93ztTFZyPm5MQ="
|
||||
[mod."github.com/stretchr/testify"]
|
||||
version = "v1.9.0"
|
||||
hash = "sha256-uUp/On+1nK+lARkTVtb5RxlW15zxtw2kaAFuIASA+J0="
|
||||
[mod."github.com/twitchyliquid64/golang-asm"]
|
||||
version = "v0.15.1"
|
||||
hash = "sha256-HLk6oUe7EoITrNvP0y8D6BtIgIcmDZYtb/xl/dufIoY="
|
||||
[mod."github.com/ugorji/go/codec"]
|
||||
version = "v1.2.12"
|
||||
hash = "sha256-sp1LJ93UK7mFwgZqG8jxCgTCPgKR74HNU6XxX0Jfjm0="
|
||||
[mod."github.com/xanzy/ssh-agent"]
|
||||
version = "v0.3.3"
|
||||
hash = "sha256-l3pGB6IdzcPA/HLk93sSN6NM2pKPy+bVOoacR5RC2+c="
|
||||
[mod."go.opencensus.io"]
|
||||
version = "v0.24.0"
|
||||
hash = "sha256-4H+mGZgG2c9I1y0m8avF4qmt8LUKxxVsTqR8mKgP4yo="
|
||||
[mod."go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"]
|
||||
version = "v0.56.0"
|
||||
hash = "sha256-nrdJ7CgH3yKhNkMpvhP2BY4+VL/maR5mrjJCO6Dke2s="
|
||||
[mod."go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"]
|
||||
version = "v0.56.0"
|
||||
hash = "sha256-Nw9uF/TUoFnH0488VNHVndgoSX+lxZy1Y93Wryl7qP4="
|
||||
[mod."go.opentelemetry.io/otel"]
|
||||
version = "v1.31.0"
|
||||
hash = "sha256-NQBHyMSRn9vaxSrNHYwv0oX1aJuEpyks/gpYEWHlx6k="
|
||||
[mod."go.opentelemetry.io/otel/metric"]
|
||||
version = "v1.31.0"
|
||||
hash = "sha256-2s5IN8IwPBitqnjIEraOfg8fWd3nIy8jWoKTXa+uUs4="
|
||||
[mod."go.opentelemetry.io/otel/trace"]
|
||||
version = "v1.31.0"
|
||||
hash = "sha256-iVDe3qNzmX1+MQTAoaeIbhnIbu/hnx4OsUIPlxuX1gY="
|
||||
[mod."golang.org/x/arch"]
|
||||
version = "v0.11.0"
|
||||
hash = "sha256-gl4bqDA/Qv6hhqxROIHTWnNGkidMMN0frp1RqcfNXlY="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.28.0"
|
||||
hash = "sha256-AYjr0BcWQMwWY1u8c2hzUprtqHUmAH7RNSxHz2hhnZs="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.30.0"
|
||||
hash = "sha256-i1f6wJHfFq0nKtbuY7twZ7uPyUbRYHVjd3uy0SS06mU="
|
||||
[mod."golang.org/x/oauth2"]
|
||||
version = "v0.23.0"
|
||||
hash = "sha256-K1X4ROG88PprttNjZCikDlZw8YYiQIQRdtbZBH3GJgM="
|
||||
[mod."golang.org/x/sync"]
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-usvF0z7gq1vsX58p4orX+8WHlv52pdXgaueXlwj2Wss="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.26.0"
|
||||
hash = "sha256-YjklsWNhx4g4TaWRWfFe1TMFKujbqiaNvZ38bfI35fM="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.19.0"
|
||||
hash = "sha256-C92pSYLLUQ2NKKcc60wpoSJ5UWAfnWkmd997C13fXdU="
|
||||
[mod."golang.org/x/time"]
|
||||
version = "v0.7.0"
|
||||
hash = "sha256-o1ol/hTpfrc06KUXSepAgm4QUuWmH1S+vqg6kmFad64="
|
||||
[mod."google.golang.org/api"]
|
||||
version = "v0.203.0"
|
||||
hash = "sha256-UlCfDi4LbcBvXVO5gLRWP6/fpfWWHoolRkxzYWGnNqg="
|
||||
[mod."google.golang.org/genproto/googleapis/api"]
|
||||
version = "v0.0.0-20241021214115-324edc3d5d38"
|
||||
hash = "sha256-ASsqfJU1DA57PLRoitSkdlS/p10EEuzl0YuZTdbmMCw="
|
||||
[mod."google.golang.org/genproto/googleapis/rpc"]
|
||||
version = "v0.0.0-20241021214115-324edc3d5d38"
|
||||
hash = "sha256-Fk+cG5bRI3BvnqhWzvMzbU36cC7PM+o2oAOJmvVx9M0="
|
||||
[mod."google.golang.org/grpc"]
|
||||
version = "v1.67.1"
|
||||
hash = "sha256-VqfKp80c2B1MK4m1WtHW4r7ykqdChJbqaMn+gMEYmYc="
|
||||
[mod."google.golang.org/protobuf"]
|
||||
version = "v1.35.1"
|
||||
hash = "sha256-4NtUQoBvlPGFGjo7c+E1EBS/sb8oy50MGy45KGWPpWo="
|
||||
[mod."gopkg.in/warnings.v0"]
|
||||
version = "v0.1.2"
|
||||
hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
|
||||
[mod."gopkg.in/yaml.v3"]
|
||||
version = "v3.0.1"
|
||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||
22
patterns/analyze_proposition/system.md
Normal file
22
patterns/analyze_proposition/system.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# IDENTITY and PURPOSE
|
||||
You are an AI assistant whose primary responsibility is to analyze a federal, state, or local ballot proposition. You will meticulously examine the proposition to identify key elements such as the purpose, potential impact, arguments for and against, and any relevant background information. Your goal is to provide a comprehensive analysis that helps users understand the implications of the ballot proposition.
|
||||
|
||||
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
|
||||
|
||||
# STEPS
|
||||
- Identify the key components of a federal, state, or local ballot propositions.
|
||||
- Develop a framework for analyzing the purpose of the proposition.
|
||||
- Assess the potential impact of the proposition if passed.
|
||||
- Compile arguments for and against the proposition.
|
||||
- Gather relevant background information and context.
|
||||
- Organize the analysis in a clear and structured format.
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
- Only output Markdown.
|
||||
- All sections should be Heading level 1.
|
||||
- Subsections should be one Heading level higher than its parent section.
|
||||
- All bullets should have their own paragraph.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
# INPUT
|
||||
INPUT:
|
||||
0
patterns/analyze_proposition/user.md
Normal file
0
patterns/analyze_proposition/user.md
Normal file
45
patterns/create_user_story/system.md
Normal file
45
patterns/create_user_story/system.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# IDENTITY and PURPOSE
|
||||
|
||||
You are an expert on writing concise, clear, and illuminating technical user stories for new features in complex software programs
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
Write the users stories in a fashion recognised by other software stakeholders, including product, development, operations and quality assurance
|
||||
|
||||
EXAMPLE USER STORY
|
||||
|
||||
Description
|
||||
As a Highlight developer
|
||||
I want to migrate email templates over to Mustache
|
||||
So that future upgrades to the messenger service can be made easier
|
||||
|
||||
Acceptance Criteria
|
||||
- Migrate the existing alerting email templates from the instance specific databases over to the messenger templates blob storage.
|
||||
- Rename each template to a GUID and store in it's own folder within the blob storage
|
||||
- Store Subject and Body as separate blobs
|
||||
|
||||
- Create an upgrade script to change the value of the Alerting.Email.Template local parameter in all systems to the new template names.
|
||||
- Change the template retrieval and saving for user editing to contact the blob storage rather than the database
|
||||
- Remove the database tables and code that handles the SQL based templates
|
||||
- Highlight sends the template name and the details of the body to the Email queue in Service bus
|
||||
- this is handled by the generic Email Client (if created already)
|
||||
- This email type will be added to the list of email types that are sent to the messenger service (switch to be removed once all email templates are completed)
|
||||
|
||||
- Include domain details as part of payload sent to the messenger service
|
||||
|
||||
Note: ensure that Ops know when this work is being done so they are aware of any changes to existing templates
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
- Write the user story according to the structure above.
|
||||
- That means the user story should be written in a simple, bulleted style, not in a grandiose, conversational or academic style.
|
||||
|
||||
# OUTPUT FORMAT
|
||||
|
||||
- Output a full, user story about the content provided using the instructions above.
|
||||
- The structure should be: Description, Acceptance criteria
|
||||
- Write in a simple, plain, and clear style, not in a grandiose, conversational or academic style.
|
||||
- Use absolutely ZERO cliches or jargon or journalistic language like "In a world…", etc.
|
||||
- Do not use cliches or jargon.
|
||||
- Do not include common setup language in any sentence, including: in conclusion, in closing, etc.
|
||||
- Do not output warnings or notes—just the output requested.
|
||||
56
patterns/md_callout/system.md
Normal file
56
patterns/md_callout/system.md
Normal file
@@ -0,0 +1,56 @@
|
||||
IDENTITY and GOAL:
|
||||
|
||||
You are an ultra-wise and brilliant classifier and judge of content. You create a markdown callout based on the provided text.
|
||||
|
||||
Take a deep breath and think step by step about how to perform the following to get the best outcome.
|
||||
|
||||
STEPS:
|
||||
|
||||
1. You determine which callout type is going to best identify the content you are working with.
|
||||
|
||||
CALLOUT OPTIONS TO SELECT FROM (Select one that applies best):
|
||||
|
||||
> [!NOTE]
|
||||
> This is a note callout for general information.
|
||||
|
||||
> [!TIP]
|
||||
> Here's a helpful tip for users.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This information is crucial for success.
|
||||
|
||||
> [!WARNING]
|
||||
> Be cautious! This action has potential risks.
|
||||
|
||||
> [!CAUTION]
|
||||
> This action may have negative consequences.
|
||||
|
||||
END OF CALLOUT OPTIONS
|
||||
|
||||
2. Take the text I gave you and place it in the appropriate callout format.
|
||||
|
||||
OUTPUT:
|
||||
|
||||
The output should look like the following:
|
||||
|
||||
```md
|
||||
> [!CHOSEN CALLOUT]
|
||||
> The text I gave you goes here.
|
||||
```
|
||||
|
||||
OUTPUT FORMAT:
|
||||
|
||||
```md
|
||||
> [!CHOSEN CALLOUT]
|
||||
> The text I gave you goes here.
|
||||
```
|
||||
|
||||
OUTPUT INSTRUCTIONS
|
||||
|
||||
- ONLY generate the chosen callout
|
||||
|
||||
- ONLY OUTPUT THE MARKDOWN CALLOUT ABOVE.
|
||||
|
||||
- Do not output the ```md container. Just the marodkwn itself.
|
||||
|
||||
INPUT:
|
||||
25
pkgs/fabric/default.nix
Normal file
25
pkgs/fabric/default.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
lib,
|
||||
buildGoApplication,
|
||||
}:
|
||||
|
||||
buildGoApplication {
|
||||
pname = "fabric-ai";
|
||||
version = import ./version.nix;
|
||||
src = ../../.;
|
||||
pwd = ../../.;
|
||||
modules = ../../gomod2nix.toml;
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Fabric is an open-source framework for augmenting humans using AI. It provides a modular framework for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere";
|
||||
homepage = "https://github.com/danielmiessler/fabric";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.all;
|
||||
mainProgram = "fabric";
|
||||
};
|
||||
}
|
||||
1
pkgs/fabric/version.nix
Normal file
1
pkgs/fabric/version.nix
Normal file
@@ -0,0 +1 @@
|
||||
"1.4.93"
|
||||
@@ -66,7 +66,7 @@ func (an *Client) ListModels() (ret []string, err error) {
|
||||
}
|
||||
|
||||
func (an *Client) SendStream(
|
||||
msgs []*common.Message, opts *common.ChatOptions, channel chan string,
|
||||
msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string,
|
||||
) (err error) {
|
||||
ctx := context.Background()
|
||||
req := an.buildMessagesRequest(msgs, opts)
|
||||
@@ -91,7 +91,7 @@ func (an *Client) SendStream(
|
||||
return
|
||||
}
|
||||
|
||||
func (an *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.ChatOptions) (ret string, err error) {
|
||||
func (an *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
||||
req := an.buildMessagesRequest(msgs, opts)
|
||||
req.Stream = false
|
||||
|
||||
@@ -109,7 +109,7 @@ func (an *Client) Send(ctx context.Context, msgs []*common.Message, opts *common
|
||||
return
|
||||
}
|
||||
|
||||
func (an *Client) buildMessagesRequest(msgs []*common.Message, opts *common.ChatOptions) (ret anthropic.MessagesRequest) {
|
||||
func (an *Client) buildMessagesRequest(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret anthropic.MessagesRequest) {
|
||||
temperature := float32(opts.Temperature)
|
||||
topP := float32(opts.TopP)
|
||||
|
||||
@@ -125,7 +125,7 @@ func (an *Client) buildMessagesRequest(msgs []*common.Message, opts *common.Chat
|
||||
return
|
||||
}
|
||||
|
||||
func (an *Client) toMessages(msgs []*common.Message) (ret []anthropic.Message) {
|
||||
func (an *Client) toMessages(msgs []*goopenai.ChatCompletionMessage) (ret []anthropic.Message) {
|
||||
// we could call the method before calling the specific vendor
|
||||
normalizedMessages := common.NormalizeMessages(msgs, an.defaultRequiredUserMessage)
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
@@ -22,7 +23,7 @@ func (c *Client) ListModels() ([]string, error) {
|
||||
return []string{"dry-run-model"}, nil
|
||||
}
|
||||
|
||||
func (c *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, channel chan string) error {
|
||||
func (c *Client) SendStream(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string) error {
|
||||
output := "Dry run: Would send the following request:\n\n"
|
||||
|
||||
for _, msg := range msgs {
|
||||
@@ -44,13 +45,16 @@ func (c *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, ch
|
||||
output += fmt.Sprintf("TopP: %f\n", opts.TopP)
|
||||
output += fmt.Sprintf("PresencePenalty: %f\n", opts.PresencePenalty)
|
||||
output += fmt.Sprintf("FrequencyPenalty: %f\n", opts.FrequencyPenalty)
|
||||
if opts.ModelContextLength != 0 {
|
||||
output += fmt.Sprintf("ModelContextLength: %d\n", opts.ModelContextLength)
|
||||
}
|
||||
|
||||
channel <- output
|
||||
close(channel)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Send(_ context.Context, msgs []*common.Message, opts *common.ChatOptions) (string, error) {
|
||||
func (c *Client) Send(_ context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (string, error) {
|
||||
fmt.Println("Dry run: Would send the following request:")
|
||||
|
||||
for _, msg := range msgs {
|
||||
@@ -72,6 +76,9 @@ func (c *Client) Send(_ context.Context, msgs []*common.Message, opts *common.Ch
|
||||
fmt.Printf("TopP: %f\n", opts.TopP)
|
||||
fmt.Printf("PresencePenalty: %f\n", opts.PresencePenalty)
|
||||
fmt.Printf("FrequencyPenalty: %f\n", opts.FrequencyPenalty)
|
||||
if opts.ModelContextLength != 0 {
|
||||
fmt.Printf("ModelContextLength: %d\n", opts.ModelContextLength)
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
@@ -58,7 +59,7 @@ func (o *Client) ListModels() (ret []string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.ChatOptions) (ret string, err error) {
|
||||
func (o *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
||||
systemInstruction, messages := toMessages(msgs)
|
||||
|
||||
var client *genai.Client
|
||||
@@ -89,7 +90,7 @@ func (o *Client) buildModelNameFull(modelName string) string {
|
||||
return fmt.Sprintf("%v%v", modelsNamePrefix, modelName)
|
||||
}
|
||||
|
||||
func (o *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, channel chan string) (err error) {
|
||||
func (o *Client) SendStream(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string) (err error) {
|
||||
ctx := context.Background()
|
||||
var client *genai.Client
|
||||
if client, err = genai.NewClient(ctx, option.WithAPIKey(o.ApiKey.Value)); err != nil {
|
||||
@@ -141,7 +142,7 @@ func (o *Client) extractText(response *genai.GenerateContentResponse) (ret strin
|
||||
return
|
||||
}
|
||||
|
||||
func toMessages(msgs []*common.Message) (systemInstruction *genai.Content, messages []genai.Part) {
|
||||
func toMessages(msgs []*goopenai.ChatCompletionMessage) (systemInstruction *genai.Content, messages []genai.Part) {
|
||||
if len(msgs) >= 2 {
|
||||
systemInstruction = &genai.Content{
|
||||
Parts: []genai.Part{
|
||||
|
||||
@@ -3,15 +3,16 @@ package ollama
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/samber/lo"
|
||||
|
||||
ollamaapi "github.com/ollama/ollama/api"
|
||||
"github.com/samber/lo"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
)
|
||||
|
||||
func NewClient() (ret *Client) {
|
||||
@@ -62,7 +63,7 @@ func (o *Client) ListModels() (ret []string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, channel chan string) (err error) {
|
||||
func (o *Client) SendStream(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string) (err error) {
|
||||
req := o.createChatRequest(msgs, opts)
|
||||
|
||||
respFunc := func(resp ollamaapi.ChatResponse) (streamErr error) {
|
||||
@@ -80,7 +81,7 @@ func (o *Client) SendStream(msgs []*common.Message, opts *common.ChatOptions, ch
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.ChatOptions) (ret string, err error) {
|
||||
func (o *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
||||
bf := false
|
||||
|
||||
req := o.createChatRequest(msgs, opts)
|
||||
@@ -97,8 +98,8 @@ func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Client) createChatRequest(msgs []*common.Message, opts *common.ChatOptions) (ret ollamaapi.ChatRequest) {
|
||||
messages := lo.Map(msgs, func(message *common.Message, _ int) (ret ollamaapi.Message) {
|
||||
func (o *Client) createChatRequest(msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret ollamaapi.ChatRequest) {
|
||||
messages := lo.Map(msgs, func(message *goopenai.ChatCompletionMessage, _ int) (ret ollamaapi.Message) {
|
||||
return ollamaapi.Message{Role: message.Role, Content: message.Content}
|
||||
})
|
||||
|
||||
@@ -109,6 +110,10 @@ func (o *Client) createChatRequest(msgs []*common.Message, opts *common.ChatOpti
|
||||
"top_p": opts.TopP,
|
||||
}
|
||||
|
||||
if opts.ModelContextLength != 0 {
|
||||
options["num_ctx"] = opts.ModelContextLength
|
||||
}
|
||||
|
||||
ret = ollamaapi.ChatRequest{
|
||||
Model: opts.Model,
|
||||
Messages: messages,
|
||||
|
||||
@@ -68,7 +68,7 @@ func (o *Client) ListModels() (ret []string, err error) {
|
||||
}
|
||||
|
||||
func (o *Client) SendStream(
|
||||
msgs []*common.Message, opts *common.ChatOptions, channel chan string,
|
||||
msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions, channel chan string,
|
||||
) (err error) {
|
||||
req := o.buildChatCompletionRequest(msgs, opts)
|
||||
req.Stream = true
|
||||
@@ -104,7 +104,7 @@ func (o *Client) SendStream(
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.ChatOptions) (ret string, err error) {
|
||||
func (o *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions) (ret string, err error) {
|
||||
req := o.buildChatCompletionRequest(msgs, opts)
|
||||
|
||||
var resp goopenai.ChatCompletionResponse
|
||||
@@ -119,10 +119,10 @@ func (o *Client) Send(ctx context.Context, msgs []*common.Message, opts *common.
|
||||
}
|
||||
|
||||
func (o *Client) buildChatCompletionRequest(
|
||||
msgs []*common.Message, opts *common.ChatOptions,
|
||||
msgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions,
|
||||
) (ret goopenai.ChatCompletionRequest) {
|
||||
messages := lo.Map(msgs, func(message *common.Message, _ int) goopenai.ChatCompletionMessage {
|
||||
return goopenai.ChatCompletionMessage{Role: message.Role, Content: message.Content}
|
||||
messages := lo.Map(msgs, func(message *goopenai.ChatCompletionMessage, _ int) goopenai.ChatCompletionMessage {
|
||||
return *message
|
||||
})
|
||||
|
||||
if opts.Raw {
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
|
||||
func TestBuildChatCompletionRequestPinSeed(t *testing.T) {
|
||||
|
||||
var msgs []*common.Message
|
||||
var msgs []*goopenai.ChatCompletionMessage
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
msgs = append(msgs, &common.Message{
|
||||
msgs = append(msgs, &goopenai.ChatCompletionMessage{
|
||||
Role: "User",
|
||||
Content: "My msg",
|
||||
})
|
||||
@@ -57,10 +57,10 @@ func TestBuildChatCompletionRequestPinSeed(t *testing.T) {
|
||||
|
||||
func TestBuildChatCompletionRequestNilSeed(t *testing.T) {
|
||||
|
||||
var msgs []*common.Message
|
||||
var msgs []*goopenai.ChatCompletionMessage
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
msgs = append(msgs, &common.Message{
|
||||
msgs = append(msgs, &goopenai.ChatCompletionMessage{
|
||||
Role: "User",
|
||||
Content: "My msg",
|
||||
})
|
||||
|
||||
@@ -3,6 +3,7 @@ package ai
|
||||
import (
|
||||
"context"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
)
|
||||
@@ -10,6 +11,6 @@ import (
|
||||
type Vendor interface {
|
||||
plugins.Plugin
|
||||
ListModels() ([]string, error)
|
||||
SendStream([]*common.Message, *common.ChatOptions, chan string) error
|
||||
Send(context.Context, []*common.Message, *common.ChatOptions) (string, error)
|
||||
SendStream([]*goopenai.ChatCompletionMessage, *common.ChatOptions, chan string) error
|
||||
Send(context.Context, []*goopenai.ChatCompletionMessage, *common.ChatOptions) (string, error)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package fsdb
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
type SessionsEntity struct {
|
||||
@@ -36,16 +37,16 @@ func (o *SessionsEntity) SaveSession(session *Session) (err error) {
|
||||
|
||||
type Session struct {
|
||||
Name string
|
||||
Messages []*common.Message
|
||||
Messages []*goopenai.ChatCompletionMessage
|
||||
|
||||
vendorMessages []*common.Message
|
||||
vendorMessages []*goopenai.ChatCompletionMessage
|
||||
}
|
||||
|
||||
func (o *Session) IsEmpty() bool {
|
||||
return len(o.Messages) == 0
|
||||
}
|
||||
|
||||
func (o *Session) Append(messages ...*common.Message) {
|
||||
func (o *Session) Append(messages ...*goopenai.ChatCompletionMessage) {
|
||||
if o.vendorMessages != nil {
|
||||
for _, message := range messages {
|
||||
o.Messages = append(o.Messages, message)
|
||||
@@ -56,9 +57,9 @@ func (o *Session) Append(messages ...*common.Message) {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Session) GetVendorMessages() (ret []*common.Message) {
|
||||
func (o *Session) GetVendorMessages() (ret []*goopenai.ChatCompletionMessage) {
|
||||
if o.vendorMessages == nil {
|
||||
o.vendorMessages = []*common.Message{}
|
||||
o.vendorMessages = []*goopenai.ChatCompletionMessage{}
|
||||
for _, message := range o.Messages {
|
||||
o.appendVendorMessage(message)
|
||||
}
|
||||
@@ -67,13 +68,13 @@ func (o *Session) GetVendorMessages() (ret []*common.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Session) appendVendorMessage(message *common.Message) {
|
||||
func (o *Session) appendVendorMessage(message *goopenai.ChatCompletionMessage) {
|
||||
if message.Role != common.ChatMessageRoleMeta {
|
||||
o.vendorMessages = append(o.vendorMessages, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Session) GetLastMessage() (ret *common.Message) {
|
||||
func (o *Session) GetLastMessage() (ret *goopenai.ChatCompletionMessage) {
|
||||
if len(o.Messages) > 0 {
|
||||
ret = o.Messages[len(o.Messages)-1]
|
||||
}
|
||||
@@ -82,7 +83,16 @@ func (o *Session) GetLastMessage() (ret *common.Message) {
|
||||
|
||||
func (o *Session) String() (ret string) {
|
||||
for _, message := range o.Messages {
|
||||
ret += fmt.Sprintf("\n--- \n[%v]\n\n%v", message.Role, message.Content)
|
||||
ret += fmt.Sprintf("\n--- \n[%v]\n%v", message.Role, message.Content)
|
||||
if message.MultiContent != nil {
|
||||
for _, part := range message.MultiContent {
|
||||
if part.Type == goopenai.ChatMessagePartTypeImageURL {
|
||||
ret += fmt.Sprintf("\n%v: %v", part.Type, *part.ImageURL)
|
||||
} else if part.Type == goopenai.ChatMessagePartTypeText {
|
||||
ret += fmt.Sprintf("\n%v: %v", part.Type, part.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package fsdb
|
||||
|
||||
import (
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
"testing"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
)
|
||||
|
||||
func TestSessions_GetOrCreateSession(t *testing.T) {
|
||||
@@ -27,7 +26,7 @@ func TestSessions_SaveSession(t *testing.T) {
|
||||
StorageEntity: &StorageEntity{Dir: dir, FileExtension: ".json"},
|
||||
}
|
||||
sessionName := "testSession"
|
||||
session := &Session{Name: sessionName, Messages: []*common.Message{{Content: "message1"}}}
|
||||
session := &Session{Name: sessionName, Messages: []*goopenai.ChatCompletionMessage{{Content: "message1"}}}
|
||||
err := sessions.SaveSession(session)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to save session: %v", err)
|
||||
|
||||
@@ -4,9 +4,10 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NeeDefaults(getVendorsModels func() (*ai.VendorsModels, error)) (ret *Defaults) {
|
||||
@@ -21,18 +22,23 @@ func NeeDefaults(getVendorsModels func() (*ai.VendorsModels, error)) (ret *Defau
|
||||
}
|
||||
|
||||
ret.Vendor = ret.AddSetting("Vendor", true)
|
||||
|
||||
ret.Model = ret.AddSetupQuestionCustom("Model", true,
|
||||
"Enter the index the name of your default model")
|
||||
|
||||
ret.ModelContextLength = ret.AddSetupQuestionCustom("Model Context Length", false,
|
||||
"Enter model context length")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type Defaults struct {
|
||||
*plugins.PluginBase
|
||||
|
||||
Vendor *plugins.Setting
|
||||
Model *plugins.SetupQuestion
|
||||
GetVendorsModels func() (*ai.VendorsModels, error)
|
||||
Vendor *plugins.Setting
|
||||
Model *plugins.SetupQuestion
|
||||
ModelContextLength *plugins.SetupQuestion
|
||||
GetVendorsModels func() (*ai.VendorsModels, error)
|
||||
}
|
||||
|
||||
func (o *Defaults) Setup() (err error) {
|
||||
|
||||
@@ -2,14 +2,17 @@ package youtube
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anaskhan96/soup"
|
||||
"github.com/danielmiessler/fabric/plugins"
|
||||
@@ -37,38 +40,56 @@ type YouTube struct {
|
||||
*plugins.PluginBase
|
||||
ApiKey *plugins.SetupQuestion
|
||||
|
||||
service *youtube.Service
|
||||
normalizeRegex *regexp.Regexp
|
||||
service *youtube.Service
|
||||
}
|
||||
|
||||
func (o *YouTube) initService() (err error) {
|
||||
if o.service == nil {
|
||||
o.normalizeRegex = regexp.MustCompile(`[^a-zA-Z0-9]+`)
|
||||
ctx := context.Background()
|
||||
o.service, err = youtube.NewService(ctx, option.WithAPIKey(o.ApiKey.Value))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *YouTube) GetVideoId(url string) (ret string, err error) {
|
||||
func (o *YouTube) GetVideoOrPlaylistId(url string) (videoId string, playlistId string, err error) {
|
||||
if err = o.initService(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pattern := `(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})`
|
||||
re := regexp.MustCompile(pattern)
|
||||
match := re.FindStringSubmatch(url)
|
||||
if len(match) > 1 {
|
||||
ret = match[1]
|
||||
} else {
|
||||
err = fmt.Errorf("invalid YouTube URL, can't get video ID")
|
||||
// Video ID pattern
|
||||
videoPattern := `(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]*)`
|
||||
videoRe := regexp.MustCompile(videoPattern)
|
||||
videoMatch := videoRe.FindStringSubmatch(url)
|
||||
if len(videoMatch) > 1 {
|
||||
videoId = videoMatch[1]
|
||||
}
|
||||
|
||||
// Playlist ID pattern
|
||||
playlistPattern := `[?&]list=([a-zA-Z0-9_-]+)`
|
||||
playlistRe := regexp.MustCompile(playlistPattern)
|
||||
playlistMatch := playlistRe.FindStringSubmatch(url)
|
||||
if len(playlistMatch) > 1 {
|
||||
playlistId = playlistMatch[1]
|
||||
}
|
||||
|
||||
if videoId == "" && playlistId == "" {
|
||||
err = fmt.Errorf("invalid YouTube URL, can't get video or playlist ID: '%s'", url)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *YouTube) GrabTranscriptForUrl(url string, language string) (ret string, err error) {
|
||||
var videoId string
|
||||
if videoId, err = o.GetVideoId(url); err != nil {
|
||||
var playlistId string
|
||||
if videoId, playlistId, err = o.GetVideoOrPlaylistId(url); err != nil {
|
||||
return
|
||||
} else if videoId == "" && playlistId != "" {
|
||||
err = fmt.Errorf("URL is a playlist, not a video")
|
||||
return
|
||||
}
|
||||
|
||||
return o.GrabTranscript(videoId, language)
|
||||
}
|
||||
|
||||
@@ -85,7 +106,7 @@ func (o *YouTube) GrabTranscript(videoId string, language string) (ret string, e
|
||||
textTags := doc.FindAll("text")
|
||||
var textBuilder strings.Builder
|
||||
for _, textTag := range textTags {
|
||||
textBuilder.WriteString(textTag.Text())
|
||||
textBuilder.WriteString(strings.ReplaceAll(textTag.Text(), "'", "'"))
|
||||
textBuilder.WriteString(" ")
|
||||
ret = textBuilder.String()
|
||||
}
|
||||
@@ -172,7 +193,11 @@ func (o *YouTube) GrabDurationForUrl(url string) (ret int, err error) {
|
||||
}
|
||||
|
||||
var videoId string
|
||||
if videoId, err = o.GetVideoId(url); err != nil {
|
||||
var playlistId string
|
||||
if videoId, playlistId, err = o.GetVideoOrPlaylistId(url); err != nil {
|
||||
return
|
||||
} else if videoId == "" && playlistId != "" {
|
||||
err = fmt.Errorf("URL is a playlist, not a video")
|
||||
return
|
||||
}
|
||||
return o.GrabDuration(videoId)
|
||||
@@ -203,7 +228,11 @@ func (o *YouTube) GrabDuration(videoId string) (ret int, err error) {
|
||||
|
||||
func (o *YouTube) Grab(url string, options *Options) (ret *VideoInfo, err error) {
|
||||
var videoId string
|
||||
if videoId, err = o.GetVideoId(url); err != nil {
|
||||
var playlistId string
|
||||
if videoId, playlistId, err = o.GetVideoOrPlaylistId(url); err != nil {
|
||||
return
|
||||
} else if videoId == "" && playlistId != "" {
|
||||
err = fmt.Errorf("URL is a playlist, not a video")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -232,6 +261,109 @@ func (o *YouTube) Grab(url string, options *Options) (ret *VideoInfo, err error)
|
||||
return
|
||||
}
|
||||
|
||||
// FetchPlaylistVideos fetches all videos from a YouTube playlist.
|
||||
func (o *YouTube) FetchPlaylistVideos(playlistID string) (ret []*VideoMeta, err error) {
|
||||
if err = o.initService(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
nextPageToken := ""
|
||||
for {
|
||||
call := o.service.PlaylistItems.List([]string{"snippet"}).PlaylistId(playlistID).MaxResults(50)
|
||||
if nextPageToken != "" {
|
||||
call = call.PageToken(nextPageToken)
|
||||
}
|
||||
|
||||
var response *youtube.PlaylistItemListResponse
|
||||
if response, err = call.Do(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range response.Items {
|
||||
videoID := item.Snippet.ResourceId.VideoId
|
||||
title := item.Snippet.Title
|
||||
ret = append(ret, &VideoMeta{videoID, title, o.normalizeFileName(title)})
|
||||
}
|
||||
|
||||
nextPageToken = response.NextPageToken
|
||||
if nextPageToken == "" {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second) // Pause to respect API rate limit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SaveVideosToCSV saves the list of videos to a CSV file.
|
||||
func (o *YouTube) SaveVideosToCSV(filename string, videos []*VideoMeta) (err error) {
|
||||
var file *os.File
|
||||
if file, err = os.Create(filename); err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
writer := csv.NewWriter(file)
|
||||
defer writer.Flush()
|
||||
|
||||
// Write headers
|
||||
if err = writer.Write([]string{"VideoID", "Title"}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Write video data
|
||||
for _, record := range videos {
|
||||
if err = writer.Write([]string{record.Id, record.Title}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FetchAndSavePlaylist fetches all videos in a playlist and saves them to a CSV file.
|
||||
func (o *YouTube) FetchAndSavePlaylist(playlistID, filename string) (err error) {
|
||||
var videos []*VideoMeta
|
||||
if videos, err = o.FetchPlaylistVideos(playlistID); err != nil {
|
||||
err = fmt.Errorf("error fetching playlist videos: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = o.SaveVideosToCSV(filename, videos); err != nil {
|
||||
err = fmt.Errorf("error saving videos to CSV: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Playlist saved to", filename)
|
||||
return
|
||||
}
|
||||
|
||||
func (o *YouTube) FetchAndPrintPlaylist(playlistID string) (err error) {
|
||||
var videos []*VideoMeta
|
||||
if videos, err = o.FetchPlaylistVideos(playlistID); err != nil {
|
||||
err = fmt.Errorf("error fetching playlist videos: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Playlist: %s\n", playlistID)
|
||||
fmt.Printf("VideoId: Title\n")
|
||||
for _, video := range videos {
|
||||
fmt.Printf("%s: %s\n", video.Id, video.Title)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *YouTube) normalizeFileName(name string) string {
|
||||
return o.normalizeRegex.ReplaceAllString(name, "_")
|
||||
|
||||
}
|
||||
|
||||
type VideoMeta struct {
|
||||
Id string
|
||||
Title string
|
||||
TitleNormalized string
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
Duration bool
|
||||
Transcript bool
|
||||
|
||||
30
shell.nix
Normal file
30
shell.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
pkgs,
|
||||
gomod2nix,
|
||||
goEnv,
|
||||
}:
|
||||
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
pkgs.go
|
||||
pkgs.gopls
|
||||
pkgs.gotools
|
||||
pkgs.go-tools
|
||||
pkgs.goimports-reviser
|
||||
gomod2nix
|
||||
goEnv
|
||||
|
||||
(pkgs.writeShellScriptBin "update" ''
|
||||
go get -u
|
||||
go mod tidy
|
||||
gomod2nix generate
|
||||
'')
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
echo -e "\033[0;32;4mHeper commands:\033[0m"
|
||||
echo "'update' instead of 'go get -u && go mod tidy'"
|
||||
'';
|
||||
};
|
||||
}
|
||||
11
treefmt.nix
Normal file
11
treefmt.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
projectRootFile = "flake.nix";
|
||||
|
||||
programs = {
|
||||
deadnix.enable = true;
|
||||
statix.enable = true;
|
||||
nixfmt.enable = true;
|
||||
|
||||
gofmt.enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.77"
|
||||
var version = "v1.4.93"
|
||||
|
||||
Reference in New Issue
Block a user