fix: deepen opens the linked note, task list columns in "Alle Aufgaben", Whisper repeats, date field
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m33s

- The deepen buttons of task rows and Kanban cards open an already linked note (accent colour)
  instead of creating another one; the server refuses a second note for a linked task as well.
- "Alle Aufgaben" uses each task's own list columns for the status selector, dot and detail.
- Whisper: send vad_filter (STT_VAD_FILTER, default on) and drop a verbatim repeated tail of
  sentences or words from the transcript.
- Task detail: narrower time field, wider date field in the desktop sidebar.

v0.37.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-11-01 13:28:52 +01:00
1 parent c56bd4d943
commit 6f2eb08489
13 files changed
+131 -18

No files matched your search

+60 -1
View File
@@ -12,6 +12,7 @@ import (
"net/http"
"net/textproto"
"path"
"regexp"
"strings"
"sync"
"time"
@@ -173,6 +174,9 @@ func (s *Server) transcribe(ctx context.Context, audio []byte, filename, content
_ = mw.WriteField("language", lang)
}
_ = mw.WriteField("response_format", "json")
if s.cfg.Speech.VADFilter {
_ = mw.WriteField("vad_filter", "true")
}
if err := mw.Close(); err != nil {
return "", err
}
@@ -192,7 +196,62 @@ func (s *Server) transcribe(ctx context.Context, audio []byte, filename, content
if err := json.Unmarshal(raw, &out); err != nil {
return "", fmt.Errorf("unerwartete Antwort: %s", strings.TrimSpace(string(raw)))
}
return strings.TrimSpace(out.Text), nil
return dropRepeatedTail(strings.TrimSpace(out.Text)), nil
}
var sentenceRe = regexp.MustCompile(`[^.!?…]+[.!?…]*`)
func normalizeSpeech(s string) string {
return strings.Trim(strings.ToLower(strings.Join(strings.Fields(s), " ")), " .,!?…;:-–")
}
// dropRepeatedTail removes what Whisper sometimes makes up at the end of longer recordings: sentences
// it already wrote, repeated once more, or the last words echoed right after themselves.
func dropRepeatedTail(text string) string {
for {
trimmed := dropOnce(text)
if trimmed == text {
return text
}
text = trimmed
}
}
func dropOnce(text string) string {
// Sentence level: the last k sentences occur in the same order earlier on
sentences := sentenceRe.FindAllStringIndex(text, -1)
norm := make([]string, len(sentences))
for i, loc := range sentences {
norm[i] = normalizeSpeech(text[loc[0]:loc[1]])
}
for k := len(norm) / 2; k >= 1; k-- {
tail := norm[len(norm)-k:]
if len(strings.Join(tail, " ")) < 15 {
continue
}
for start := 0; start+k <= len(norm)-k; start++ {
same := true
for j := 0; j < k; j++ {
if norm[start+j] != tail[j] || tail[j] == "" {
same = false
break
}
}
if same {
return strings.TrimSpace(text[:sentences[len(norm)-k][0]])
}
}
}
// Word level: the last n words (at least 6) directly repeat the n words before them
words := strings.Fields(text)
for n := len(words) / 2; n >= 6; n-- {
a := normalizeSpeech(strings.Join(words[len(words)-2*n:len(words)-n], " "))
b := normalizeSpeech(strings.Join(words[len(words)-n:], " "))
if a == b {
return strings.Join(words[:len(words)-n], " ")
}
}
return text
}
// checkVoice asks the Whisper server whether it is up and has the model.