This commit implements fully automatic injection of online research results into the LLM prompt without user clicks.
## Backend
### Environment Variables
- Added `PAPAYU_ONLINE_AUTO_USE_AS_CONTEXT=1` (default: 0) to enable automatic injection of online research results into subsequent `proposeActions` calls.
- Added `is_online_auto_use_as_context()` helper function in `online_research/mod.rs`.
### Command Changes
- **`propose_actions` command**: Added `online_fallback_reason: Option<String>` parameter to track the error code that triggered online fallback.
- **`llm_planner::plan` function**: Added `online_fallback_reason: Option<&str>` parameter for tracing.
- **Trace Enhancements**: Added `online_fallback_reason` field to trace when `online_fallback_executed` is true.
### Module Exports
- Made `extract_error_code_prefix` public in `online_research/fallback.rs` for frontend use.
## Frontend
### Project Settings
- Added `onlineAutoUseAsContext` state (persisted in `localStorage` as `papa_yu_online_auto_use_as_context`).
- Initialized from localStorage or defaults to `false`.
- Auto-saved to localStorage on change.
### Auto-Chain Flow
- When `plan.ok === false` and `plan.online_fallback_suggested` is present:
- If `onlineAutoUseAsContext === true` and not already attempted for this goal (cycle protection via `lastGoalWithOnlineFallbackRef`):
- Automatically calls `researchAnswer(query)`.
- Truncates result to `8000` chars and `10` sources (frontend-side limits).
- Immediately calls `proposeActions` again with:
- `online_context_md`
- `online_context_sources`
- `online_fallback_executed: true`
- `online_fallback_reason: error_code`
- `online_fallback_attempted: true`
- Displays the new plan/error without requiring "Use as context" button click.
- If `onlineAutoUseAsContext === false` or already attempted:
- Falls back to manual mode (shows online research block with "Use as context (once)" button).
### Cycle Protection
- `lastGoalWithOnlineFallbackRef` tracks the last goal that triggered online fallback.
- If the same goal triggers fallback again, auto-chain is skipped to prevent infinite loops.
- Maximum 1 auto-chain per user query.
### UI Enhancements
- **Online Research Block**:
- When `onlineAutoUseAsContext === true`: displays "Auto-used ✓" badge.
- Hides "Use as context (once)" button when auto-use is enabled.
- Adds "Disable auto-use" button (red) to disable auto-use for the current project.
- When disabled, shows system message: "Auto-use отключён для текущего проекта."
### API Updates
- **`proposeActions` in `tauri.ts`**: Added `onlineFallbackReason?: string | null` parameter.
## Tests
- **`online_context_auto_test.rs`**: Added unit tests for:
- `test_is_online_auto_use_disabled_by_default`
- `test_is_online_auto_use_enabled_when_set`
- `test_extract_error_code_prefix_timeout`
- `test_extract_error_code_prefix_schema`
- `test_extract_error_code_prefix_empty_when_no_prefix`
All tests pass.
## Documentation
### README.md
- Added "Auto-use (X4)" subsection under "Online Research":
- Describes `PAPAYU_ONLINE_AUTO_USE_AS_CONTEXT=1` env var (default: 0).
- Explains cycle protection: maximum 1 auto-chain per goal.
- Documents UI behavior: "Auto-used ✓" badge and "Disable auto-use" button.
## Behavior Summary
**Without auto-use (default):**
1. `proposeActions` → error + `online_fallback_suggested`
2. UI calls `researchAnswer`
3. UI displays online research block with "Use as context (once)" button
4. User clicks button → sets `onlineContextPending` → next `proposeActions` includes context
**With auto-use enabled (`PAPAYU_ONLINE_AUTO_USE_AS_CONTEXT=1`):**
1. `proposeActions` → error + `online_fallback_suggested`
2. UI calls `researchAnswer` automatically
3. UI displays online research block with "Auto-used ✓" badge
4. UI immediately calls `proposeActions` again with online context → displays new plan
5. If still fails → no retry (cycle protection)
## Build Status
- ✅ Backend: `cargo build --lib` (2 warnings about unused code for future features)
- ✅ Frontend: `npm run build`
- ✅ Tests: `cargo test online_context_auto_test --lib` (5 passed)
Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.3 KiB
JSON
50 lines
1.3 KiB
JSON
{
|
|
"protocol": {
|
|
"schema_version": 2,
|
|
"schema_hash": "49374413940cb32f3763ae62b3450647eb7b3be1ae50668cf6936f29512cef7b"
|
|
},
|
|
"request": {
|
|
"mode": "apply",
|
|
"input_chars": 10000,
|
|
"token_budget": 4096,
|
|
"strict_json": true,
|
|
"provider": "openai",
|
|
"model": "gpt-4o-mini"
|
|
},
|
|
"context": {
|
|
"context_stats": {
|
|
"context_files_count": 1,
|
|
"context_files_dropped_count": 0,
|
|
"context_total_chars": 2000,
|
|
"context_logs_chars": 0,
|
|
"context_truncated_files_count": 0
|
|
},
|
|
"cache_stats": {
|
|
"env_hits": 0,
|
|
"env_misses": 1,
|
|
"logs_hits": 0,
|
|
"logs_misses": 0,
|
|
"read_hits": 1,
|
|
"read_misses": 0,
|
|
"search_hits": 0,
|
|
"search_misses": 0,
|
|
"hit_rate": 0.5
|
|
}
|
|
},
|
|
"result": {
|
|
"validated_json": {
|
|
"actions": [
|
|
{
|
|
"kind": "PATCH_FILE",
|
|
"path": "src/main.rs",
|
|
"patch": "--- a/src/main.rs\n+++ b/src/main.rs\n@@ -1,5 +1,5 @@\n fn main() {\n- println!(\"WRONG_CONTEXT_LINE\");\n+ println!(\"new\");\n }\n",
|
|
"base_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
}
|
|
],
|
|
"summary": "Изменил main."
|
|
},
|
|
"validation_outcome": "ok",
|
|
"error_code": "ERR_PATCH_APPLY_FAILED"
|
|
}
|
|
}
|