Imported from screenfluent/pi (
extensions/pi-jobs/AGENTS.md). Install upstream withnpx skills add screenfluent/pi --skill pi-jobs. Copyright stays with the author.
Overview
Self-contained pi extension that auto-tracks all agent runs via lifecycle hooks. Stores data in SQLite (default) or the shared pi-kysely database. Provides an LLM jobs tool for querying stats, a /jobs TUI command, and a web dashboard at /jobs via pi-webserver.
Stack: TypeScript · better-sqlite3 · optional pi-kysely · pi-webserver
Architecture
src/index.ts— Entry point. Initializes the store backend, callsregisterTracker()andregisterJobsTool(), mounts web routes, registers/jobscommand.src/tracker.ts— Lifecycle hooks:model_select,turn_start,turn_end,tool_call,tool_result. Also listens forsubagent:complete,heartbeat:result,cron:job_completeto record external runs.src/tool.ts—jobsLLM tool. Actions:stats,recent,cost_report,models,tools. Period parameter maps to days (today=1, week=7, month=30, all=3650).src/store.ts— Store abstraction. ExportsgetJobsStore(),setJobsStore(),isStoreReady(). Two factory functions:createSqliteStore(dbPath)andcreateKyselyStore(eventBus).src/db.ts— SQLite backend via better-sqlite3. WAL mode. Tables:jobs,job_tool_calls. Migrations tracked injobs_migrations.src/db-kysely.ts— Kysely backend: same schema via pi-kysely event bus.src/settings.ts— Loads"pi-jobs"from global + projectsettings.json.src/web.ts— Mounts/jobsdashboard and/api/jobsAPI routes via pi-webserver event bus.src/logger.ts— Extension logger (emits to pi-logger).
Database Schema
jobs — id (text PK), channel (tui|cron|heartbeat|subagent), prompt, model, provider, status (running|done|error), response, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, total_tokens, cost_input, cost_output, cost_cache_read, cost_cache_write, cost_total, tool_call_count, turn_count, duration_ms, error, created_at, updated_at.
job_tool_calls — id, job_id (FK), tool_name, is_error, duration_ms, created_at.
Key Patterns
- Auto-tracking —
turn_startatturnIndex === 0creates a job;turn_endwith no pending tool results completes it. Tool calls are recorded individually viatool_call/tool_resultevents. - Channel taxonomy — Jobs are categorized as
tui(interactive session),cron,heartbeat, orsubagent. - Store init probe — For Kysely backend, probes
kysely:infoto detect if pi-kysely is already running before subscribing tokysely:ready. - Telemetry resilience — All tracker callbacks catch and swallow errors; telemetry must never break the agent.
web:readyre-mount — Listens forweb:readyto re-mount routes if pi-webserver starts after pi-jobs.
Settings
// settings.json
{
"pi-jobs": {
"dbPath": "jobs/jobs.db", // SQLite file path (relative to agent home)
"useKysely": false // Use pi-kysely shared DB instead of SQLite
}
}
LLM Tool: jobs
Actions:
stats— Total runs, errors, tokens, cost, tool calls, avg durationrecent— Last N jobs (default 20) with status, channel, prompt, tokens, costcost_report— Daily cost breakdown (grouped by date)models— Usage and cost by provider/modeltools— Tool call frequency, error count, avg duration
Optional parameters: period (today|week|month|all), channel (tui|cron|heartbeat|subagent), limit (for recent).
Integration Points
| Extension | Integration | Mechanism |
|---|---|---|
| pi-webserver | Job dashboard + API | web:mount, web:mount-api, web:ready |
| pi-kysely | Shared DB backend | kysely:info, kysely:ready |
| pi-heartbeat | Track heartbeat runs | heartbeat:result event |
| pi-cron | Track cron runs | cron:job_complete event |
| pi-logger | Structured logging | log event |
Commands
/jobs [channel]— Show quick stats (total runs, errors, tokens, cost, tool calls, avg duration). Channel optional filter (tui|cron|heartbeat|subagent).
Events Emitted
jobs:recorded—{ jobId, type: "start"|"complete" }— fired on job creation and completion.
Conventions
- No
console.log— usecreateLogger(pi). - SQLite DB stored at
<agentDir>/jobs/jobs.dbby default. closeDb()is called onsession_shutdownto flush WAL and close handles.