mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-10 23:08:06 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
278d488dbf | ||
|
|
d590c0dd15 | ||
|
|
c936f8e77b | ||
|
|
7dacc07f03 | ||
|
|
4e6a2736ad | ||
|
|
14c95d7bc1 | ||
|
|
2e7b664e1e | ||
|
|
729d092754 |
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,5 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.326 (2025-11-16)
|
||||
|
||||
### PR [#1830](https://github.com/danielmiessler/Fabric/pull/1830) by [ksylvan](https://github.com/ksylvan): Ensure final newline in model generated outputs
|
||||
|
||||
- Feat: ensure newline in `CreateOutputFile` and improve tests
|
||||
- Add newline to `CreateOutputFile` if missing
|
||||
- Use `t.Cleanup` for file removal in tests
|
||||
- Add test for message with trailing newline
|
||||
- Introduce `printedStream` flag in `Chatter.Send`
|
||||
|
||||
### Direct commits
|
||||
|
||||
- Chore: update README with recent features and extensions
|
||||
|
||||
- Add v1.4.322 release with concept maps
|
||||
|
||||
- Introduce WELLNESS category with psychological analysis
|
||||
- Upgrade to Claude Sonnet 4.5
|
||||
|
||||
- Add Portuguese language variants with BCP 47 support
|
||||
- Migrate to `openai-go/azure` SDK for Azure
|
||||
|
||||
- Add Extensions section to README navigation
|
||||
|
||||
## v1.4.325 (2025-11-15)
|
||||
|
||||
### PR [#1828](https://github.com/danielmiessler/Fabric/pull/1828) by [ksylvan](https://github.com/ksylvan): Fix empty string detection in chatter and AI clients
|
||||
|
||||
- Chore: improve message handling by trimming whitespace in content checks
|
||||
- Remove default space in `BuildSession` message content
|
||||
- Trim whitespace in `anthropic` message content check
|
||||
- Trim whitespace in `gemini` message content check
|
||||
|
||||
## v1.4.324 (2025-11-14)
|
||||
|
||||
### PR [#1827](https://github.com/danielmiessler/Fabric/pull/1827) by [ksylvan](https://github.com/ksylvan): Make YouTube API key optional in setup
|
||||
|
||||
@@ -73,6 +73,9 @@ Below are the **new features and capabilities** we've added (newest first):
|
||||
|
||||
### Recent Major Features
|
||||
|
||||
- [v1.4.322](https://github.com/danielmiessler/fabric/releases/tag/v1.4.322) (Nov 5, 2025) — **Interactive HTML Concept Maps and Claude Sonnet 4.5**: Adds `create_conceptmap` pattern for visual knowledge representation using Vis.js, introduces WELLNESS category with psychological analysis patterns, and upgrades to Claude Sonnet 4.5
|
||||
- [v1.4.317](https://github.com/danielmiessler/fabric/releases/tag/v1.4.317) (Sep 21, 2025) — **Portuguese Language Variants**: Adds BCP 47 locale normalization with support for Brazilian Portuguese (pt-BR) and European Portuguese (pt-PT) with intelligent fallback chains
|
||||
- [v1.4.314](https://github.com/danielmiessler/fabric/releases/tag/v1.4.314) (Sep 17, 2025) — **Azure OpenAI Migration**: Migrates to official `openai-go/azure` SDK with improved authentication and default API version support
|
||||
- [v1.4.311](https://github.com/danielmiessler/fabric/releases/tag/v1.4.311) (Sep 13, 2025) — **More internationalization support**: Adds de (German), fa (Persian / Farsi), fr (French), it (Italian),
|
||||
ja (Japanese), pt (Portuguese), zh (Chinese)
|
||||
- [v1.4.309](https://github.com/danielmiessler/fabric/releases/tag/v1.4.309) (Sep 9, 2025) — **Comprehensive internationalization support**: Includes English and Spanish locale files.
|
||||
@@ -161,6 +164,7 @@ Keep in mind that many of these were recorded when Fabric was Python-based, so r
|
||||
- [Fish Completion](#fish-completion)
|
||||
- [Usage](#usage)
|
||||
- [Debug Levels](#debug-levels)
|
||||
- [Extensions](#extensions)
|
||||
- [Our approach to prompting](#our-approach-to-prompting)
|
||||
- [Examples](#examples)
|
||||
- [Just use the Patterns](#just-use-the-patterns)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.324"
|
||||
var version = "v1.4.326"
|
||||
|
||||
Binary file not shown.
@@ -29,6 +29,9 @@ func CreateOutputFile(message string, fileName string) (err error) {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
if !strings.HasSuffix(message, "\n") {
|
||||
message += "\n"
|
||||
}
|
||||
if _, err = file.WriteString(message); err != nil {
|
||||
err = fmt.Errorf("%s", fmt.Sprintf(i18n.T("error_writing_to_file"), err))
|
||||
} else {
|
||||
|
||||
@@ -24,5 +24,34 @@ func TestCreateOutputFile(t *testing.T) {
|
||||
t.Fatalf("CreateOutputFile() error = %v", err)
|
||||
}
|
||||
|
||||
defer os.Remove(fileName)
|
||||
t.Cleanup(func() { os.Remove(fileName) })
|
||||
|
||||
data, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
expected := message + "\n"
|
||||
if string(data) != expected {
|
||||
t.Fatalf("expected file contents %q, got %q", expected, data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOutputFileMessageWithTrailingNewline(t *testing.T) {
|
||||
fileName := "test_output_with_newline.txt"
|
||||
message := "test message with newline\n"
|
||||
|
||||
if err := CreateOutputFile(message, fileName); err != nil {
|
||||
t.Fatalf("CreateOutputFile() error = %v", err)
|
||||
}
|
||||
t.Cleanup(func() { os.Remove(fileName) })
|
||||
|
||||
data, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
if string(data) != message {
|
||||
t.Fatalf("expected file contents %q, got %q", message, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
|
||||
responseChan := make(chan string)
|
||||
errChan := make(chan error, 1)
|
||||
done := make(chan struct{})
|
||||
printedStream := false
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
@@ -81,9 +82,14 @@ func (o *Chatter) Send(request *domain.ChatRequest, opts *domain.ChatOptions) (s
|
||||
message += response
|
||||
if !opts.SuppressThink {
|
||||
fmt.Print(response)
|
||||
printedStream = true
|
||||
}
|
||||
}
|
||||
|
||||
if printedStream && !opts.SuppressThink && !strings.HasSuffix(message, "\n") {
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Wait for goroutine to finish
|
||||
<-done
|
||||
|
||||
@@ -175,7 +181,7 @@ func (o *Chatter) BuildSession(request *domain.ChatRequest, raw bool) (session *
|
||||
if request.Message == nil {
|
||||
request.Message = &chat.ChatCompletionMessage{
|
||||
Role: chat.ChatMessageRoleUser,
|
||||
Content: " ",
|
||||
Content: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ func (an *Client) toMessages(msgs []*chat.ChatCompletionMessage) (ret []anthropi
|
||||
lastRoleWasUser := false
|
||||
|
||||
for _, msg := range msgs {
|
||||
if msg.Content == "" {
|
||||
if strings.TrimSpace(msg.Content) == "" {
|
||||
continue // Skip empty messages
|
||||
}
|
||||
|
||||
|
||||
@@ -456,7 +456,7 @@ func (o *Client) convertMessages(msgs []*chat.ChatCompletionMessage) []*genai.Co
|
||||
content.Role = "user"
|
||||
}
|
||||
|
||||
if msg.Content != "" {
|
||||
if strings.TrimSpace(msg.Content) != "" {
|
||||
content.Parts = append(content.Parts, &genai.Part{Text: msg.Content})
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"1.4.324"
|
||||
"1.4.326"
|
||||
|
||||
Reference in New Issue
Block a user