7 Commits

10 changed files with 87 additions and 146 deletions
+3 -134
View File
@@ -2,68 +2,6 @@
# Shared Agent Utilities - Minimal, focused helper functions # Shared Agent Utilities - Minimal, focused helper functions
set -euo pipefail set -euo pipefail
#############################
## CONTEXT FILE MANAGEMENT ##
#############################
get_context_file() {
local project_dir="${LLM_AGENT_VAR_PROJECT_DIR:-.}"
echo "${project_dir}/.loki-context"
}
# Initialize context file for a new task
# Usage: init_context "Task description"
init_context() {
local task="$1"
local project_dir="${LLM_AGENT_VAR_PROJECT_DIR:-.}"
local context_file
context_file=$(get_context_file)
cat > "${context_file}" <<EOF
## Project: ${project_dir}
## Task: ${task}
## Started: $(date -Iseconds)
### Prior Findings
EOF
}
# Append findings to the context file
# Usage: append_context "agent_name" "finding summary
append_context() {
local agent="$1"
local finding="$2"
local context_file
context_file=$(get_context_file)
if [[ -f "${context_file}" ]]; then
{
echo ""
echo "[${agent}]:"
echo "${finding}"
} >> "${context_file}"
fi
}
# Read the current context (returns empty string if no context)
# Usage: context=$(read_context)
read_context() {
local context_file
context_file=$(get_context_file)
if [[ -f "${context_file}" ]]; then
cat "${context_file}"
fi
}
# Clear the context file
clear_context() {
local context_file
context_file=$(get_context_file)
rm -f "${context_file}"
}
####################### #######################
## PROJECT DETECTION ## ## PROJECT DETECTION ##
####################### #######################
@@ -279,9 +217,9 @@ _detect_with_llm() {
evidence=$(_gather_project_evidence "${dir}") evidence=$(_gather_project_evidence "${dir}")
local prompt local prompt
prompt=$(cat <<-EOF prompt=$(cat <<-EOF
Analyze this project directory and determine the project type, primary language, and the correct shell commands to build, test, and check (lint/typecheck) it. Analyze this project directory and determine the project type, primary language, and the correct shell commands to build, test, and check (lint/typecheck) it.
EOF EOF
) )
prompt+=$'\n'"${evidence}"$'\n' prompt+=$'\n'"${evidence}"$'\n'
@@ -348,80 +286,11 @@ detect_project() {
echo '{"type":"unknown","build":"","test":"","check":""}' echo '{"type":"unknown","build":"","test":"","check":""}'
} }
######################
## AGENT INVOCATION ##
######################
# Invoke a subagent with optional context injection
# Usage: invoke_agent <agent_name> <prompt> [extra_args...]
invoke_agent() {
local agent="$1"
local prompt="$2"
shift 2
local context
context=$(read_context)
local full_prompt
if [[ -n "${context}" ]]; then
full_prompt="## Orchestrator Context
The orchestrator (sisyphus) has gathered this context from prior work:
<context>
${context}
</context>
## Your Task
${prompt}"
else
full_prompt="${prompt}"
fi
env AUTO_CONFIRM=true loki --agent "${agent}" "$@" "${full_prompt}" 2>&1
}
# Invoke a subagent and capture a summary of its findings
# Usage: result=$(invoke_agent_with_summary "explore" "find auth patterns")
invoke_agent_with_summary() {
local agent="$1"
local prompt="$2"
shift 2
local output
output=$(invoke_agent "${agent}" "${prompt}" "$@")
local summary=""
if echo "${output}" | grep -q "FINDINGS:"; then
summary=$(echo "${output}" | sed -n '/FINDINGS:/,/^[A-Z_]*COMPLETE/p' | grep "^- " | sed 's/^- / - /')
elif echo "${output}" | grep -q "CODER_COMPLETE:"; then
summary=$(echo "${output}" | grep "CODER_COMPLETE:" | sed 's/CODER_COMPLETE: *//')
elif echo "${output}" | grep -q "ORACLE_COMPLETE"; then
summary=$(echo "${output}" | sed -n '/^## Recommendation/,/^## /{/^## Recommendation/d;/^## /d;p}' | sed '/^$/d' | head -10)
fi
if [[ -z "${summary}" ]]; then
summary=$(echo "${output}" | grep -v "^$" | grep -v "^#" | grep -v "^\-\-\-" | tail -10 | head -5)
fi
if [[ -n "${summary}" ]]; then
append_context "${agent}" "${summary}"
fi
if [[ -z "${output}" ]] || [[ -z "$(echo "${output}" | tr -d '[:space:]')" ]]; then
echo "[${agent} agent completed but produced no text output. The agent may have performed work via tool calls (file writes, builds, etc.) that did not generate visible text. Check the project directory for changes.]"
else
echo "${output}"
fi
}
########################### ###########################
## FILE SEARCH UTILITIES ## ## FILE SEARCH UTILITIES ##
########################### ###########################
search_files() { _search_files() {
local pattern="$1" local pattern="$1"
local dir="${2:-.}" local dir="${2:-.}"
+3
View File
@@ -122,3 +122,6 @@ instructions: |
- Project: {{project_dir}} - Project: {{project_dir}}
- CWD: {{__cwd__}} - CWD: {{__cwd__}}
- Shell: {{__shell__}} - Shell: {{__shell__}}
## Available Tools:
{{__tools__}}
+25 -3
View File
@@ -29,12 +29,31 @@ instructions: |
## Your Mission ## Your Mission
Given an implementation task: Given an implementation task:
1. Understand what to build (from context provided) 1. Check for orchestrator context first (see below)
2. Study existing patterns (read 1-2 similar files) 2. Fill gaps only. Read files NOT already covered in context
3. Write the code (using tools, NOT chat output) 3. Write the code (using tools, NOT chat output)
4. Verify it compiles/builds 4. Verify it compiles/builds
5. Signal completion with a summary 5. Signal completion with a summary
## Using Orchestrator Context (IMPORTANT)
When spawned by sisyphus, your prompt will often contain a `<context>` block
with prior findings: file paths, code patterns, and conventions discovered by
explore agents.
**If context is provided:**
1. Use it as your primary reference. Don't re-read files already summarized
2. Follow the code patterns shown. Snippets in context ARE the style guide
3. Read the referenced files ONLY IF you need more detail (e.g. full function
signature, import list, or adjacent code not included in the snippet)
4. If context includes a "Conventions" section, follow it exactly
**If context is NOT provided or is too vague to act on:**
Fall back to self-exploration: grep for similar files, read 1-2 examples,
match their style.
**Never ignore provided context.** It represents work already done upstream.
## Todo System ## Todo System
For multi-file changes: For multi-file changes:
@@ -104,4 +123,7 @@ instructions: |
## Context ## Context
- Project: {{project_dir}} - Project: {{project_dir}}
- CWD: {{__cwd__}} - CWD: {{__cwd__}}
- Shell: {{__shell__}} - Shell: {{__shell__}}
## Available tools:
{{__tools__}}
+3
View File
@@ -68,6 +68,9 @@ instructions: |
## Context ## Context
- Project: {{project_dir}} - Project: {{project_dir}}
- CWD: {{__cwd__}} - CWD: {{__cwd__}}
## Available Tools:
{{__tools__}}
conversation_starters: conversation_starters:
- 'Find how authentication is implemented' - 'Find how authentication is implemented'
+1 -1
View File
@@ -60,7 +60,7 @@ search_files() {
echo "" >> "$LLM_OUTPUT" echo "" >> "$LLM_OUTPUT"
local results local results
results=$(search_files "${pattern}" "${project_dir}") results=$(_search_files "${pattern}" "${project_dir}")
if [[ -n "${results}" ]]; then if [[ -n "${results}" ]]; then
echo "${results}" >> "$LLM_OUTPUT" echo "${results}" >> "$LLM_OUTPUT"
+3
View File
@@ -108,3 +108,6 @@ instructions: |
## Context ## Context
- Project: {{project_dir}} - Project: {{project_dir}}
- CWD: {{__cwd__}} - CWD: {{__cwd__}}
## Available Tools:
{{__tools__}}
+3
View File
@@ -75,6 +75,9 @@ instructions: |
## Context ## Context
- Project: {{project_dir}} - Project: {{project_dir}}
- CWD: {{__cwd__}} - CWD: {{__cwd__}}
## Available Tools:
{{__tools__}}
conversation_starters: conversation_starters:
- 'Review this architecture design' - 'Review this architecture design'
+43 -5
View File
@@ -12,7 +12,7 @@ can_spawn_agents: true
max_concurrent_agents: 4 max_concurrent_agents: 4
max_agent_depth: 3 max_agent_depth: 3
inject_spawn_instructions: true inject_spawn_instructions: true
summarization_threshold: 4000 summarization_threshold: 8000
variables: variables:
- name: project_dir - name: project_dir
@@ -70,6 +70,45 @@ instructions: |
| coder | Write/edit files, implement features | Creates/modifies files, runs builds | | coder | Write/edit files, implement features | Creates/modifies files, runs builds |
| oracle | Architecture decisions, complex debugging | Advisory, high-quality reasoning | | oracle | Architecture decisions, complex debugging | Advisory, high-quality reasoning |
## Coder Delegation Format (MANDATORY)
When spawning the `coder` agent, your prompt MUST include these sections.
The coder has NOT seen the codebase. Your prompt IS its entire context.
### Template:
```
## Goal
[1-2 sentences: what to build/modify and where]
## Reference Files
[Files that explore found, with what each demonstrates]
- `path/to/file.ext` - what pattern this file shows
- `path/to/other.ext` - what convention this file shows
## Code Patterns to Follow
[Paste ACTUAL code snippets from explore results, not descriptions]
<code>
// From path/to/file.ext - this is the pattern to follow:
[actual code explore found, 5-20 lines]
</code>
## Conventions
[Naming, imports, error handling, file organization]
- Convention 1
- Convention 2
## Constraints
[What NOT to do, scope boundaries]
- Do NOT modify X
- Only touch files in Y/
```
**CRITICAL**: Include actual code snippets, not just file paths.
If explore returned code patterns, paste them into the coder prompt.
Vague prompts like "follow existing patterns" waste coder's tokens on
re-exploration that you already did.
## Workflow Examples ## Workflow Examples
### Example 1: Implementation task (explore -> coder, parallel exploration) ### Example 1: Implementation task (explore -> coder, parallel exploration)
@@ -81,12 +120,12 @@ instructions: |
2. todo__add --task "Explore existing API patterns" 2. todo__add --task "Explore existing API patterns"
3. todo__add --task "Implement profile endpoint" 3. todo__add --task "Implement profile endpoint"
4. todo__add --task "Verify with build/test" 4. todo__add --task "Verify with build/test"
5. agent__spawn --agent explore --prompt "Find existing API endpoint patterns, route structures, and controller conventions" 5. agent__spawn --agent explore --prompt "Find existing API endpoint patterns, route structures, and controller conventions. Include code snippets."
6. agent__spawn --agent explore --prompt "Find existing data models and database query patterns" 6. agent__spawn --agent explore --prompt "Find existing data models and database query patterns. Include code snippets."
7. agent__collect --id <id1> 7. agent__collect --id <id1>
8. agent__collect --id <id2> 8. agent__collect --id <id2>
9. todo__done --id 1 9. todo__done --id 1
10. agent__spawn --agent coder --prompt "Create user profiles endpoint following existing patterns. [Include context from explore results]" 10. agent__spawn --agent coder --prompt "<structured prompt using Coder Delegation Format above, including code snippets from explore results>"
11. agent__collect --id <coder_id> 11. agent__collect --id <coder_id>
12. todo__done --id 2 12. todo__done --id 2
13. run_build 13. run_build
@@ -135,7 +174,6 @@ instructions: |
## When to Do It Yourself ## When to Do It Yourself
- Single-file reads/writes
- Simple command execution - Simple command execution
- Trivial changes (typos, renames) - Trivial changes (typos, renames)
- Quick file searches - Quick file searches
+1 -1
View File
@@ -85,7 +85,7 @@ async fn prepare_chat_completions(
let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?; let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?;
if !ready { if !ready {
bail!( bail!(
"OAuth configured but no tokens found for '{}'. Run: loki --authenticate {}", "OAuth configured but no tokens found for '{}'. Run: 'loki --authenticate {}' or '.authenticate' in the REPL",
self_.name(), self_.name(),
self_.name() self_.name()
); );
+2 -2
View File
@@ -111,7 +111,7 @@ async fn prepare_chat_completions(
let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?; let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?;
if !ready { if !ready {
bail!( bail!(
"OAuth configured but no tokens found for '{}'. Run: loki --authenticate {}", "OAuth configured but no tokens found for '{}'. Run: 'loki --authenticate {}' or '.authenticate' in the REPL",
self_.name(), self_.name(),
self_.name() self_.name()
); );
@@ -181,7 +181,7 @@ async fn prepare_embeddings(
let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?; let ready = oauth::prepare_oauth_access_token(client, &provider, self_.name()).await?;
if !ready { if !ready {
bail!( bail!(
"OAuth configured but no tokens found for '{}'. Run: loki --authenticate {}", "OAuth configured but no tokens found for '{}'. Run: 'loki --authenticate {}' or '.authenticate' in the REPL",
self_.name(), self_.name(),
self_.name() self_.name()
); );