98 lines
4.9 KiB
Markdown
98 lines
4.9 KiB
Markdown
|
|
# Bounded research delivery
|
|||
|
|
|
|||
|
|
New general research tasks should use `task_type: "research"` on
|
|||
|
|
`delegate_task` or `spawn_agent`. The coordinator is instructed to select this
|
|||
|
|
for search-and-guide requests. Omitted task types remain standard, including
|
|||
|
|
old saved tasks. Existing research is not migrated or restarted.
|
|||
|
|
|
|||
|
|
## Delivery
|
|||
|
|
|
|||
|
|
The runtime stores research state with the task, including its start time,
|
|||
|
|
source reservations, publications and source results.
|
|||
|
|
|
|||
|
|
- Initial collection stops at 120 seconds, two searches or six page reservations.
|
|||
|
|
Limits are checked before starting a new source call and on each model round;
|
|||
|
|
already running calls may finish.
|
|||
|
|
- `publish_research` sends a first guide with summary, actionable steps, observed
|
|||
|
|
source URLs and unknowns. It can declare zero to two material gaps.
|
|||
|
|
- Each gap permits one additional search and two pages. Every supplement source
|
|||
|
|
call needs its zero-based `gap` index. Supplement collection also stops after
|
|||
|
|
120 seconds.
|
|||
|
|
- A second publication contains only additions and remaining unknowns. It cannot
|
|||
|
|
introduce new gaps. An empty gap list completes the task immediately.
|
|||
|
|
- Opening acknowledgements and meaningful progress messages remain available.
|
|||
|
|
They do not count as a first guide.
|
|||
|
|
- Synthesis gets at most three model rounds after collection closes. Failure to
|
|||
|
|
publish then ends the task with an explicit error and retains existing evidence
|
|||
|
|
and publications, rather than resuming exploration.
|
|||
|
|
- Other execution/delegation tools cannot bypass research limits. Browser
|
|||
|
|
navigation counts as a page; browser snapshots and page reading are available
|
|||
|
|
during collection for HTTP-blocked sources. Shell/MCP-based research requires a
|
|||
|
|
standard task.
|
|||
|
|
|
|||
|
|
The 2–3 minute first-guide target is a goal, not a deadline for external model
|
|||
|
|
responses. Network source calls have a 30 second timeout; model response and
|
|||
|
|
queue delays are measured separately.
|
|||
|
|
|
|||
|
|
## Reuse and persistence
|
|||
|
|
|
|||
|
|
Within a research task, identical search queries and canonical URLs reuse the
|
|||
|
|
saved result, including errors and timeouts. Different URLs can run concurrently;
|
|||
|
|
concurrent requests for the same URL share one execution. URL fragments are
|
|||
|
|
ignored; query parameters remain significant. Cached access does not spend a
|
|||
|
|
new reservation. Failed source attempts spend their original reservation.
|
|||
|
|
|
|||
|
|
Large tool results include `output_id`. Use `read_tool_output` with that ID,
|
|||
|
|
`offset` (default 0) and `limit` (default 6000, maximum 12000). Offsets count
|
|||
|
|
Unicode characters. The reader is scoped to the current task/session and
|
|||
|
|
rejects traversal or another task's output. It does not access the Docker
|
|||
|
|
filesystem.
|
|||
|
|
|
|||
|
|
Publications are stored independently of foreground conversation checkpoints,
|
|||
|
|
restored into chat history and made available to subsequent foreground turns.
|
|||
|
|
Completed research does not enqueue a redundant coordinator summary.
|
|||
|
|
|
|||
|
|
## Diagnostics and validation
|
|||
|
|
|
|||
|
|
Persisted `timing` events carry task/agent association, timestamp and elapsed
|
|||
|
|
milliseconds. Model queue and response records share a round identifier; source
|
|||
|
|
and tool records carry the task's request number, with call IDs on tool records.
|
|||
|
|
Stages include `worker_model_queue`, `foreground_model_queue`, `model_response`,
|
|||
|
|
`model_retry_backoff`, `tool_execution`, `research_source`,
|
|||
|
|
`research_first_delivery`, and `research_final_delivery`.
|
|||
|
|
Retry-backoff values are scheduled wait durations. No prompts, arguments or
|
|||
|
|
credentials are stored in timing events. `GROKBOY_TIMING=1` additionally prints
|
|||
|
|
latency logs.
|
|||
|
|
|
|||
|
|
Offline checks:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
cargo test -p grokboy-core --lib
|
|||
|
|
cargo build -p grokboy
|
|||
|
|
python3 tests/research_flow.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The integration fixture makes no paid model calls and is not evidence of live
|
|||
|
|
provider latency. After restarting the local backend, use new ordinary research
|
|||
|
|
requests to measure actual first-guide latency from the recorded events.
|
|||
|
|
|
|||
|
|
## Accurate work indicators
|
|||
|
|
|
|||
|
|
`GET /api/agents/:id/activity` (daemon RPC `activity`) reports
|
|||
|
|
`idle | queued | running | waiting_input`, active task IDs and a pending question.
|
|||
|
|
Roster and agent detail use the same computation. A saved `running` task is
|
|||
|
|
active only while the service owns a live worker. Completing one task does not
|
|||
|
|
hide another active task; a human question by itself is not active computation.
|
|||
|
|
|
|||
|
|
The frontend reconciles on lifecycle events and every two seconds, independently
|
|||
|
|
of streamed progress text. Only running activity animates; queued work has a
|
|||
|
|
static label. The old OR of typing, stale detail, stale roster and status text is
|
|||
|
|
removed. Status requests time out after eight seconds; connection failure shows
|
|||
|
|
an unknown/reconnecting message instead of an endless working animation. Late
|
|||
|
|
responses from another agent or before a newly sent message are discarded.
|
|||
|
|
|
|||
|
|
Browser regression (with the local Vite UI running):
|
|||
|
|
`node tests/activity_ui.mjs`. This uses an isolated headless browser and mocked
|
|||
|
|
API responses to verify running, idle, queued, waiting-input, disconnect and
|
|||
|
|
reconnect, including stale progress events and roster data.
|