Enable kaya-board tools on Tasks mention replies.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Match Telegram chat tool surface (journal, tasks, steam/discord/node) so diary requests hit write_journal instead of a board-only comment. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
856e5a3cab
commit
3a2a0c1c34
@ -14,4 +14,4 @@ AGENT_PROFILE_PATH=profiles/kaya.yaml
|
||||
HEALTH_LISTEN_ADDR=:8087
|
||||
METRICS_LISTEN_ADDR=:9097
|
||||
SHUTDOWN_TIMEOUT=15s
|
||||
RESPONSE_TIMEOUT=120s
|
||||
RESPONSE_TIMEOUT=180s
|
||||
|
||||
@ -10,8 +10,8 @@ Long-lived daemon:
|
||||
2. On `comment.added` where mentions include agent `kaya` and author ≠ `kaya`:
|
||||
- dedupes by comment id
|
||||
- GET task + comments via REST
|
||||
- calls `l-ai-core` `AIService.RunAgent` (tools disabled) with Kaya persona
|
||||
- POST comment with `Idempotency-Key: mention-reply:<comment_id>`
|
||||
- calls `l-ai-core` `AIService.RunAgent` with tools enabled (`tool_profile=kaya-board`: journal, tasks, steam/faceit, discord, node — same surface as Telegram chat; no gitea/evolver)
|
||||
- POST comment with `Idempotency-Key: mention-reply:<comment_id>` (do not use `add_comment` for the reply itself)
|
||||
|
||||
No Telegram / Live Chat integration.
|
||||
|
||||
@ -35,6 +35,7 @@ No Telegram / Live Chat integration.
|
||||
| `AGENT_PROFILE_PATH` | no | `profiles/kaya.yaml` |
|
||||
| `HEALTH_LISTEN_ADDR` | no | `:8087` |
|
||||
| `METRICS_LISTEN_ADDR` | no | `:9097` |
|
||||
| `RESPONSE_TIMEOUT` | no | `180s` |
|
||||
|
||||
## Build
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ func Load() (Config, error) {
|
||||
MetricsListenAddr: env("METRICS_LISTEN_ADDR", ":9097"),
|
||||
HealthListenAddr: env("HEALTH_LISTEN_ADDR", ":8087"),
|
||||
ShutdownTimeout: envDur("SHUTDOWN_TIMEOUT", 15*time.Second),
|
||||
ResponseTimeout: envDur("RESPONSE_TIMEOUT", 120*time.Second),
|
||||
ResponseTimeout: envDur("RESPONSE_TIMEOUT", 180*time.Second),
|
||||
}
|
||||
if c.TasksWSURL == "" {
|
||||
return c, errors.New("TASKS_WS_URL is required")
|
||||
|
||||
@ -59,17 +59,25 @@ func (r *CoreRunner) RunAgent(ctx context.Context, req RunRequest) (RunResult, e
|
||||
}
|
||||
|
||||
toolsEnabled := req.ToolsEnabled
|
||||
maxIters := uint32(1)
|
||||
maxCalls := uint32(0)
|
||||
if toolsEnabled {
|
||||
maxIters = 12
|
||||
maxCalls = 20
|
||||
maxIters := req.MaxToolIterations
|
||||
maxCalls := req.MaxTotalToolCalls
|
||||
if !toolsEnabled {
|
||||
maxIters = 1
|
||||
maxCalls = 0
|
||||
} else {
|
||||
if maxIters == 0 {
|
||||
maxIters = 12
|
||||
}
|
||||
if maxCalls == 0 {
|
||||
maxCalls = 20
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := r.api.RunAgent(r.auth(ctx), &corepb.AgentRequest{
|
||||
Messages: msgs,
|
||||
ModelName: req.Model,
|
||||
AgentId: req.AgentID,
|
||||
Messages: msgs,
|
||||
ModelName: req.Model,
|
||||
AgentId: req.AgentID,
|
||||
ToolProfile: req.ToolProfile,
|
||||
ToolLoop: &corepb.AgentToolLoopOptions{
|
||||
ToolsEnabled: toolsEnabled,
|
||||
MaxToolIterations: maxIters,
|
||||
|
||||
@ -8,16 +8,19 @@ type ChatMessage struct {
|
||||
}
|
||||
|
||||
type RunRequest struct {
|
||||
Messages []ChatMessage
|
||||
Model string
|
||||
AgentID string
|
||||
RequestID string
|
||||
IdempotencyKey string
|
||||
JSONSchema string
|
||||
Repair bool
|
||||
TimeoutSeconds uint32
|
||||
Metadata map[string]string
|
||||
ToolsEnabled bool
|
||||
Messages []ChatMessage
|
||||
Model string
|
||||
AgentID string
|
||||
RequestID string
|
||||
IdempotencyKey string
|
||||
JSONSchema string
|
||||
Repair bool
|
||||
TimeoutSeconds uint32
|
||||
Metadata map[string]string
|
||||
ToolsEnabled bool
|
||||
ToolProfile string
|
||||
MaxToolIterations uint32
|
||||
MaxTotalToolCalls uint32
|
||||
}
|
||||
|
||||
type RunResult struct {
|
||||
|
||||
@ -101,8 +101,9 @@ func (p Profile) SystemPrompt() string {
|
||||
}
|
||||
b.WriteString("You reply only to task comment @mentions. Be helpful and concise. ")
|
||||
b.WriteString("Match the language of the triggering comment (Russian or English). ")
|
||||
b.WriteString("When asked to journal / diary a merged change: write a short factual note of what shipped and any PR URL from the thread. ")
|
||||
b.WriteString("Do not invent task state that is not in the provided context. ")
|
||||
b.WriteString("Tools match Telegram chat (journal, tasks, steam/faceit, discord, node) — use them when needed. ")
|
||||
b.WriteString("When asked to journal / diary a merged change: call write_journal (persona Postgres diary), then a short board reply noting what shipped and any PR URL. ")
|
||||
b.WriteString("Do not invent task state that is not in the provided context or tool results. ")
|
||||
b.WriteString("Output only the comment body to post — no preamble or quotes.\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@ -154,7 +154,8 @@ func (l *Loop) handle(ctx context.Context, ev tasksws.Event) error {
|
||||
|
||||
sys := l.Profile.SystemPrompt()
|
||||
sys += " Avoid @mentioning other agents unless you need a concrete action — never @mention just to acknowledge."
|
||||
sys += " If Mira asks you to journal a merged task, write a short diary-style board comment (what changed + PR if present)."
|
||||
sys += " CRITICAL: Do NOT call add_comment — this process posts your reply text as the board comment."
|
||||
sys += " If asked to journal / diary a merged task: call write_journal with a short factual entry (what shipped + PR URL if present), then still write a brief board reply."
|
||||
if authorType == "human" {
|
||||
sys += " A human mentioned you — always give a real reply."
|
||||
}
|
||||
@ -164,13 +165,16 @@ func (l *Loop) handle(ctx context.Context, ev tasksws.Event) error {
|
||||
{Role: "system", Content: sys},
|
||||
{Role: "user", Content: userPrompt},
|
||||
},
|
||||
Model: model,
|
||||
AgentID: agentID,
|
||||
RequestID: "mention-reply:" + commentID,
|
||||
IdempotencyKey: "mention-reply:" + commentID,
|
||||
TimeoutSeconds: timeoutSec,
|
||||
Metadata: map[string]string{"trace_reason": "kaya_mention_reply", "comment_id": commentID, "task_id": taskID},
|
||||
ToolsEnabled: false,
|
||||
Model: model,
|
||||
AgentID: agentID,
|
||||
RequestID: "mention-reply:" + commentID,
|
||||
IdempotencyKey: "mention-reply:" + commentID,
|
||||
TimeoutSeconds: timeoutSec,
|
||||
Metadata: map[string]string{"trace_reason": "kaya_mention_reply", "comment_id": commentID, "task_id": taskID},
|
||||
ToolsEnabled: true,
|
||||
ToolProfile: "kaya-board",
|
||||
MaxToolIterations: 10,
|
||||
MaxTotalToolCalls: 18,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("RunAgent: %w", err)
|
||||
@ -184,7 +188,7 @@ func (l *Loop) handle(ctx context.Context, ev tasksws.Event) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("post comment: %w", err)
|
||||
}
|
||||
l.log().Info("mention reply posted", "comment_id", commentID, "task_id", taskID, "duration_ms", res.DurationMS)
|
||||
l.log().Info("mention reply posted", "comment_id", commentID, "task_id", taskID, "duration_ms", res.DurationMS, "tools_used", res.ToolsUsed)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -207,7 +211,7 @@ func (l *Loop) shouldReplyToAgentMention(ctx context.Context, task Task, mention
|
||||
model = "deepseek-v4-flash"
|
||||
}
|
||||
user := "Task: " + task.Title + "\nTrigger comment from another agent:\n" + trimRunes(mentionBody, 800) +
|
||||
"\n\nReply true ONLY if you must add new substance (journal entry Mira asked for). Default false for thanks/repeats."
|
||||
"\n\nReply true if you must act (e.g. Mira asked you to journal via write_journal, or you need tools). Default false for thanks/acks/repeats."
|
||||
res, err := l.Core.RunAgent(ctx, inference.RunRequest{
|
||||
Messages: []inference.ChatMessage{
|
||||
{Role: "system", Content: "You gate Kaya's board replies to agent @mentions. Prefer false. Output JSON only."},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user