Skip to content

Commit 0aff66c

Browse files
authored
release: v0.24.10 Add KuraDB features and update chat completions endpoint
Merge pull request #30 from pardnchiu/develop
2 parents 94881ac + c4fca1d commit 0aff66c

59 files changed

Lines changed: 2297 additions & 505 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 124 additions & 75 deletions
Large diffs are not rendered by default.

cmd/app/addProvider.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func addCompat() (string, string) {
152152
providor = strings.ToUpper(strings.TrimSpace(providor))
153153

154154
urlInput := promptui.Prompt{
155-
Label: "URL (leave empty for http://localhost:11434)",
155+
Label: "URL (leave empty for http://localhost:11434/v1)",
156156
Default: "",
157157
}
158158
url, err := urlInput.Run()
@@ -163,7 +163,7 @@ func addCompat() (string, string) {
163163
}
164164
url = strings.TrimRight(strings.TrimSpace(url), "/")
165165
if url == "" {
166-
url = "http://localhost:11434"
166+
url = "http://localhost:11434/v1"
167167
}
168168

169169
if err := session.UpsertCompat(providor, url); err != nil {

cmd/app/cmdDeamon.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"os/signal"
1111
"path/filepath"
12+
"strings"
1213
"sync"
1314
"syscall"
1415
"time"
@@ -27,6 +28,8 @@ import (
2728
"github.com/pardnchiu/agenvoy/internal/runtime"
2829
"github.com/pardnchiu/agenvoy/internal/runtime/discord"
2930
discordTool "github.com/pardnchiu/agenvoy/internal/runtime/discord/tool"
31+
"github.com/pardnchiu/agenvoy/internal/runtime/kuradb"
32+
kuradbTool "github.com/pardnchiu/agenvoy/internal/runtime/kuradb/tool"
3033
"github.com/pardnchiu/agenvoy/internal/runtime/telegram"
3134
telegramTool "github.com/pardnchiu/agenvoy/internal/runtime/telegram/tool"
3235
"github.com/pardnchiu/agenvoy/internal/runtime/torii"
@@ -48,6 +51,10 @@ var (
4851
telegramBot *telegram.Bot
4952
lastTelegramEnabled bool
5053
lastTelegramToken string
54+
55+
kuradbMu sync.Mutex
56+
kuradbCancel context.CancelFunc
57+
lastKuradbEnabled bool
5158
)
5259

5360
func reloadDiscord() {
@@ -128,6 +135,49 @@ func reloadTelegram() {
128135
telegramBot = bot
129136
}
130137

138+
func reloadKuradb() {
139+
newEnabled := false
140+
if cfg, err := session.Load(); err == nil && cfg != nil {
141+
newEnabled = cfg.KuradbEnabled
142+
}
143+
144+
kuradbMu.Lock()
145+
defer kuradbMu.Unlock()
146+
147+
if newEnabled == lastKuradbEnabled {
148+
return
149+
}
150+
151+
if kuradbCancel != nil {
152+
kuradbCancel()
153+
kuradbCancel = nil
154+
}
155+
lastKuradbEnabled = newEnabled
156+
157+
if !newEnabled || !kuradb.IsInstalled() || strings.TrimSpace(keychain.Get("OPENAI_API_KEY")) == "" {
158+
return
159+
}
160+
161+
ctx, cancel := context.WithCancel(context.Background())
162+
kuradbCancel = cancel
163+
164+
go kuradb.Run(ctx)
165+
go kuradb.Health(ctx, func() {
166+
if cfg, err := session.Load(); err == nil && cfg != nil {
167+
cfg.KuradbEnabled = false
168+
if err := session.Save(cfg); err != nil {
169+
slog.Warn("session.Save",
170+
slog.String("error", err.Error()))
171+
}
172+
}
173+
if err := kuradb.Remove(); err != nil {
174+
slog.Warn("kuradb.RemoveEndpoint",
175+
slog.String("error", err.Error()))
176+
}
177+
reloadKuradb()
178+
})
179+
}
180+
131181
func cmdDaemon() {
132182
installDaemonSlog()
133183
session.SetHash(session.Hash())
@@ -149,6 +199,7 @@ func cmdDaemon() {
149199
geminiStt.Register()
150200
telegramTool.Register()
151201
discordTool.Register()
202+
kuradbTool.Register()
152203

153204
if _, err := runtime.Init(); err != nil {
154205
if errors.Is(err, runtime.ErrAlreadyRunning) {
@@ -200,6 +251,7 @@ func cmdDaemon() {
200251
if selectorBot != nil {
201252
reloadDiscord()
202253
reloadTelegram()
254+
reloadKuradb()
203255

204256
route := routes.New()
205257
port := go_pkg_utils.GetWithDefault("PORT", "17989")
@@ -237,6 +289,12 @@ func cmdDaemon() {
237289
telegramBot = nil
238290
}
239291
telegramMu.Unlock()
292+
kuradbMu.Lock()
293+
if kuradbCancel != nil {
294+
kuradbCancel()
295+
kuradbCancel = nil
296+
}
297+
kuradbMu.Unlock()
240298
if server != nil {
241299
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
242300
_ = server.Shutdown(ctx)
@@ -298,6 +356,7 @@ func watchConfig(ctx context.Context) func() {
298356
}
299357
reloadDiscord()
300358
reloadTelegram()
359+
reloadKuradb()
301360
case err, ok := <-w.Errors:
302361
if !ok {
303362
return

cmd/app/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/pardnchiu/agenvoy/internal/runtime/cli"
3030
"github.com/pardnchiu/agenvoy/internal/runtime/discord"
3131
discordTool "github.com/pardnchiu/agenvoy/internal/runtime/discord/tool"
32+
kuradbTool "github.com/pardnchiu/agenvoy/internal/runtime/kuradb/tool"
3233
"github.com/pardnchiu/agenvoy/internal/runtime/telegram"
3334
telegramTool "github.com/pardnchiu/agenvoy/internal/runtime/telegram/tool"
3435
"github.com/pardnchiu/agenvoy/internal/session"
@@ -130,6 +131,7 @@ func initCLI() {
130131
geminiStt.Register()
131132
telegramTool.Register()
132133
discordTool.Register()
134+
kuradbTool.Register()
133135
}
134136

135137
func modelCheck() {

cmd/app/newTUI.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/pardnchiu/agenvoy/internal/runtime/torii"
2020
"github.com/pardnchiu/agenvoy/internal/runtime"
2121
discordTool "github.com/pardnchiu/agenvoy/internal/runtime/discord/tool"
22+
kuradbTool "github.com/pardnchiu/agenvoy/internal/runtime/kuradb/tool"
2223
telegramTool "github.com/pardnchiu/agenvoy/internal/runtime/telegram/tool"
2324
"github.com/pardnchiu/agenvoy/internal/runtime/tui"
2425
"github.com/pardnchiu/agenvoy/internal/session"
@@ -49,6 +50,7 @@ func newTUI() {
4950
geminiStt.Register()
5051
telegramTool.Register()
5152
discordTool.Register()
53+
kuradbTool.Register()
5254

5355
modelCheck()
5456

configs/prompts/system_prompt.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ Examples:
3939

4040
Capability matching is by **semantic intent**, not literal name — match each tool's description text to the query intent. When multiple unmarked tools match, prefer in order: `mcp__*` > `api_*` > `script_*` (newer integrations first); when uncertain which unmarked tool fits, invoke `search_tools` rather than fall through to a `[system-default]` tool.
4141

42+
**RAG-first execution (when `rag_*` tools are present) — MANDATORY ordering:**
43+
44+
The loaded tool list including any `rag_*` tool means the user maintains a **read-only vector knowledge base**: files the user has ingested (PDFs, documents, notes) converted to embeddings for semantic retrieval. Treat it as **curated reference material**, not user memory or user-authored content.
45+
46+
**Mandatory ordering** for every information-gathering query that is not smalltalk or pure-static knowledge:
47+
48+
1. **FIRST tool calls** must be `rag_*` — call `rag_list_db` to discover databases (skip if already enumerated this session), then call matching `rag_search_semantic` / `rag_search_keyword` against every relevant db in the same batch
49+
2. **Inspect RAG output** before deciding next step. If RAG returned sufficient material, answer directly from it; do NOT call `search_web` / `fetch_page` / `[system-default]` fetchers
50+
3. **Only when RAG is insufficient** (empty results, off-topic, partial coverage), fall through to the forced routing table below. External tools are **supplementary** — they fill gaps the corpus cannot cover (live data, recent news, public web content)
51+
4. For broad scope queries ("我有什麼資料", "知識庫裡有什麼", "RAG 裡有什麼", "X 寫了啥" where X looks like a filename/document), call every `rag_*` listing/search endpoint exhaustively and stop there unless the user asked for external augmentation
52+
53+
**Skipping `rag_*` and going straight to `search_web` for any non-smalltalk knowledge query is a VIOLATION.** Going external first means the user reads generic public answers when they have specific documents on the topic indexed — defeats the purpose of curating a RAG.
54+
55+
RAG = primary source (user's curated reference corpus). External = secondary supplement (live or public data the corpus cannot contain). The order is fixed: RAG first, external only to fill gaps.
56+
4257
**Smalltalk exemption — respond directly, do NOT call any tool:**
4358
- Pure greetings, casual chat, emotional expressions (hi, hello, 你好、謝謝、哈哈、早安, etc.)
4459
- Short messages with no clear information-retrieval intent
@@ -58,6 +73,9 @@ Capability matching is by **semantic intent**, not literal name — match each t
5873

5974
**Forced routing — must call the specified tool directly. Never output JSON text or an empty response:**
6075

76+
> **RAG hook:** If `rag_*` tools are loaded, every routing rule below is **secondary** to `rag_*`. The FIRST tool calls for any non-smalltalk knowledge query must be `rag_list_db` + matching `rag_search_*`; only consult the table's external/built-in tools **after** reviewing RAG output and only when RAG is insufficient. Going straight to a routing-table tool while skipping `rag_*` is a violation. Smalltalk and pure-calculation routes are exempt.
77+
78+
6179
| Query type | Required tool |
6280
|-----------|---------------|
6381
| Ask what tools are available / tool list | `list_tools` |

0 commit comments

Comments
 (0)