192 lines
6.2 KiB
HTML
192 lines
6.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Agent Runner — UML Sequence Diagram</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
|
<style>
|
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=DM+Sans:wght@400;500;700&display=swap');
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
|
|
body {
|
|
background: #0f1117;
|
|
color: #c9cdd8;
|
|
font-family: 'DM Sans', sans-serif;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 40px 24px;
|
|
}
|
|
|
|
h1 {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
letter-spacing: -0.02em;
|
|
color: #e4e7ef;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.subtitle {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.78rem;
|
|
color: #5b6078;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.mermaid {
|
|
width: 100%;
|
|
max-width: 1200px;
|
|
}
|
|
|
|
.mermaid svg {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
footer {
|
|
margin-top: 40px;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.65rem;
|
|
color: #3d4156;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Agent Runner — Batch File Processing</h1>
|
|
<p class="subtitle">UML Sequence · Electron FE ↔ FastAPI BE ↔ LLM</p>
|
|
|
|
<pre class="mermaid">
|
|
sequenceDiagram
|
|
autonumber
|
|
|
|
participant FE as Electron FE<br/>(AgentScheduler · DrizzleExecutor)
|
|
participant BE as FastAPI BE<br/>(AgentRunner · routes/agents)
|
|
participant LLM as LLM<br/>(gpt-4.1 via LiteLLM)
|
|
|
|
note over FE: AgentScheduler cron tick<br/>or manual "Run Now"
|
|
|
|
rect rgb(30, 33, 48)
|
|
note right of FE: PHASE 1 — TRIGGER
|
|
FE->>+BE: POST /agents/trigger<br/>(agent config, directories, schedule)
|
|
BE->>BE: billing check · concurrency guard<br/>create AgentRunLog (status=running)
|
|
BE-->>-FE: 202 Accepted { run_id }
|
|
note over FE: store runId in local agentRuns
|
|
note over BE: asyncio.create_task(run_local_agent)<br/>fire-and-forget background task
|
|
end
|
|
|
|
rect rgb(25, 37, 35)
|
|
note right of FE: PHASE 2 — DIRECTORY SCAN (via WS → FE filesystem)
|
|
loop For each directory in agent config (max depth=5)
|
|
BE->>FE: WS tool_call: list_directory { path }
|
|
FE->>FE: fs.readdir(path)
|
|
FE-->>BE: WS tool_result: { entries[] }
|
|
BE->>FE: WS tool_call: get_file_metadata { path }
|
|
FE->>FE: fs.stat(file)
|
|
FE-->>BE: WS tool_result: { modifiedAt, size }
|
|
note over BE: Skip if modifiedAt ≤ last_run_at<br/>(first run: last_run_at=null → all pass)
|
|
end
|
|
note over BE: Result: file_list[] — paths passing<br/>extension + date filters (e.g., 22 files)
|
|
end
|
|
|
|
BE->>FE: WS tool_call: select { table: "projects" }
|
|
FE-->>BE: WS tool_result: { rows[] }
|
|
note over BE: Cache project list for prompt context
|
|
|
|
rect rgb(35, 30, 22)
|
|
note right of FE: PHASE 3+4 — FOR EACH FILE: READ → PREPROCESS → LLM
|
|
loop For each file in file_list (sequential)
|
|
|
|
rect rgb(40, 35, 25)
|
|
note over BE: Phase 3 — Read + Preprocess
|
|
BE->>FE: WS tool_call: read_file_content { path }
|
|
FE->>FE: fs.readFile(path)
|
|
FE-->>BE: WS tool_result: { content }
|
|
BE->>BE: detect_content_type(filename, content)<br/>preprocess() → clean text + metadata<br/>(Python only, zero LLM calls)
|
|
end
|
|
|
|
rect rgb(30, 28, 42)
|
|
note over BE: Phase 4 — LLM Agent Tool Loop
|
|
BE->>+LLM: system prompt + clean text<br/>+ available tools + project list
|
|
loop Max 12 tool-call iterations
|
|
LLM-->>BE: tool_call (e.g., list_tasks, create_note)
|
|
BE->>FE: WS tool_call: select/insert/update<br/>{ table, data }
|
|
FE->>FE: DrizzleExecutor<br/>local SQLite CRUD
|
|
FE-->>BE: WS tool_result: { rows }
|
|
BE->>LLM: tool_result → continue
|
|
end
|
|
LLM-->>-BE: final text response (no more tool_calls)
|
|
end
|
|
|
|
note over BE: log: file processed, created=N entities
|
|
opt If create_project was called
|
|
BE->>FE: WS tool_call: select { table: "projects" }
|
|
FE-->>BE: WS tool_result: { rows[] }
|
|
note over BE: Refresh project list cache
|
|
end
|
|
end
|
|
end
|
|
|
|
rect rgb(22, 35, 32)
|
|
note right of FE: PHASE 5 — COMPLETION
|
|
BE->>BE: _finalize_run()<br/>update AgentRunLog in PostgreSQL<br/>status = success | partial | error
|
|
BE->>FE: WS run_complete: { run_id, status }
|
|
FE->>FE: update local agentRuns table<br/>{ status, completedAt }
|
|
end
|
|
|
|
note over FE,LLM: ⚠ No file-path journal exists. On re-trigger,<br/>BE re-scans all files. Date filter (modifiedAt > last_run_at)<br/>skips unchanged files, but LLM dedup is the only guard<br/>if last_run_at is null or files are unmodified.
|
|
</pre>
|
|
|
|
<footer>
|
|
adiuvAI · Agent Runner Sequence · April 2026 ·
|
|
FE = Electron (filesystem + SQLite owner) · BE = FastAPI (orchestrator) · LLM = gpt-4.1 via LiteLLM
|
|
</footer>
|
|
|
|
<script>
|
|
mermaid.initialize({
|
|
startOnLoad: true,
|
|
theme: 'dark',
|
|
themeVariables: {
|
|
actorBkg: '#1e2130',
|
|
actorBorder: '#3b82f6',
|
|
actorTextColor: '#e4e7ef',
|
|
actorLineColor: '#3d4156',
|
|
signalColor: '#c9cdd8',
|
|
signalTextColor: '#c9cdd8',
|
|
noteBkgColor: '#1c1f2e',
|
|
noteTextColor: '#a0a6be',
|
|
noteBorderColor: '#2e3248',
|
|
activationBkgColor: '#252840',
|
|
activationBorderColor: '#4f5580',
|
|
sequenceNumberColor: '#0f1117',
|
|
loopTextColor: '#8b8fc4',
|
|
labelBoxBkgColor: '#1a1d2e',
|
|
labelBoxBorderColor: '#2e3248',
|
|
labelTextColor: '#a0a6be',
|
|
},
|
|
sequence: {
|
|
diagramMarginX: 20,
|
|
diagramMarginY: 20,
|
|
actorMargin: 80,
|
|
width: 220,
|
|
height: 50,
|
|
boxMargin: 6,
|
|
boxTextMargin: 6,
|
|
noteMargin: 12,
|
|
messageMargin: 40,
|
|
mirrorActors: true,
|
|
useMaxWidth: true,
|
|
wrap: true,
|
|
},
|
|
fontFamily: '"JetBrains Mono", monospace',
|
|
fontSize: 13,
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|