Commit Graph

278 Commits

Author SHA1 Message Date
Dhanji R. Prasanna
6e8dc2e866 Add template processing to /run command
Apply the same {{var}} template variable injection to prompts
loaded via the /run command in interactive mode.
2026-01-20 21:36:48 +05:30
Dhanji R. Prasanna
1a1f149206 Add template variable injection for --include-prompt
Supports {{var}} syntax for variable substitution in included prompt files.

Currently supported variables:
- {{today}}: Current date in ISO format (YYYY-MM-DD)

Unknown variables trigger a warning and are left unchanged.

- Add template.rs module with process_template() function
- Integrate template processing into read_include_prompt()
- Add comprehensive tests for template processing
2026-01-20 21:34:15 +05:30
Dhanji R. Prasanna
dec22f5e58 refactor(g3-cli): extract commands module and fix test organization
- Extract handle_command() from interactive.rs to new commands.rs module
  (320 lines, 15 match arms for /help, /compact, /thinnify, etc.)
- Fix orphaned tests in completion.rs that were outside mod tests block
- Add #[allow(dead_code)] to with_include_prompt_filename() (used in tests)
- interactive.rs reduced from 595 to 290 lines

Agent: fowler
2026-01-20 14:30:50 +05:30
Dhanji R. Prasanna
710c54105b refactor(cli): extract display utilities to eliminate code duplication
Created display.rs module with shared display functions:
- format_workspace_path() / print_workspace_path()
- LoadedContent struct for tracking loaded project files
- print_loaded_status() for status line display
- print_project_heading() for README heading

Updated interactive.rs and agent_mode.rs to use the new module,
eliminating duplicated workspace path formatting and loaded items
status line logic.

Results:
- interactive.rs: 641 → 595 lines (-46)
- agent_mode.rs: 312 → 288 lines (-24)
- New display.rs: 197 lines with 5 unit tests

Agent: fowler
2026-01-20 14:22:46 +05:30
Dhanji R. Prasanna
ecea49d328 Fix --acd flag not being passed to agent mode
The --acd flag was being checked AFTER the agent mode early return,
so it was never applied when running with --agent.

Fix: Pass acd_enabled parameter to run_agent_mode() and call
agent.set_acd_enabled(true) when the flag is set.
2026-01-20 14:12:40 +05:30
Dhanji R. Prasanna
1ec01bb4e3 Limit /resume completion to 8 most recent sessions
Always shows at most 8 sessions in tab completion, sorted by newest first.
This applies whether the user types /resume <TAB> or /resume abc<TAB>.

Implementation:
- list_sessions() returns all sessions sorted by mtime (newest first)
- Completion filters by prefix, then takes first 8 matches
2026-01-20 13:52:28 +05:30
Dhanji R. Prasanna
02ceb6e64c Add /resume <session-id> tab completion
Phase 2 of tab completion: semantic completion for session IDs.

Features:
- /resume <TAB> lists all available sessions from .g3/sessions/
- /resume abc<TAB> filters to sessions starting with 'abc'
- Gracefully returns empty if .g3/sessions/ doesn't exist

Implementation:
- Added list_sessions() helper method to G3Helper
- Added Case 4 in complete() for /resume command
- Updated module docs to reflect new capability

Tests:
- test_resume_completion_lists_sessions - verifies listing and filtering
- test_resume_completion_graceful_no_panic - verifies no crash without sessions dir
2026-01-20 13:04:05 +05:30
Dhanji R. Prasanna
8acbdd7ad4 Add tests for bare quote and non-path quoted text edge cases
Verifies that tab completion correctly ignores:
- Bare quotes: "<TAB> - no path prefix, no completion
- Quoted non-paths: "hello world<TAB> - not a path, no completion
- Quoted text without path prefix: "foo<TAB> - no completion

Also fixes test placement (moved tests inside mod tests block)
2026-01-20 11:44:29 +05:30
Dhanji R. Prasanna
58b1a51e2d Fix tab completion for quoted paths and backslash escapes
Edge cases now handled:
1. Unclosed quotes: "~/My <TAB> - completes paths inside quotes
2. Backslash escapes: ~/My\ <TAB> - unescapes before completing
3. Closed quotes: "~/My Files/"<TAB> - works correctly

Key changes:
- extract_word() now tracks backslash escapes (prev_was_backslash)
- is_path_prefix() strips leading quotes before checking
- Added strip_quotes() and unescape_path() helper methods
- complete() now:
  - Strips quotes and unescapes paths before calling FilenameCompleter
  - Re-wraps completions in quotes or escapes as appropriate
  - Preserves user's quoting style (double vs single quotes)
  - Uses backslash escapes if user was already using them

Tests added:
- test_actual_completion_with_quotes - verifies all three edge cases
2026-01-20 11:41:32 +05:30
Dhanji R. Prasanna
96cc18b83c Extend tab completion to path-like prefixes anywhere in line
Path completion now works for:
- ./<TAB> - current directory
- ../<TAB> - parent directory
- ~/<TAB> - home directory
- /<TAB> (not at start of line) - root directory

Command completion (/<TAB>) only triggers at the start of the line.
If no command matches, falls through to path completion (e.g., /etc).

Quote-aware word extraction handles paths with spaces:
- "~/My Files/<TAB>" works correctly

Added tests for:
- Path prefix detection
- Word extraction with quotes
- Command vs path disambiguation
2026-01-20 11:19:13 +05:30
Dhanji R. Prasanna
dd3db0227d Add tab completion for commands and file paths
Implement tab completion in interactive mode using rustyline:

- Command completion: /<TAB> shows all commands, /com<TAB> -> /compact
- File path completion: /run <TAB> completes file/directory paths
- Supports tilde expansion for home directory

Architecture is extensible for future semantic completions:
- /resume <TAB> -> session IDs (Phase 2)
- /rehydrate <TAB> -> fragment IDs (Phase 2)

New module: completion.rs with G3Helper struct implementing
rustyline's Completer trait.
2026-01-20 10:57:33 +05:30
Dhanji R. Prasanna
4db2150386 Change /run status message from 'running' to 'loading' 2026-01-20 10:34:06 +05:30
Dhanji R. Prasanna
6873f980a1 Use G3Status for /run command output
Change from custom emoji format to consistent g3: status message:
'g3: running <path> ... [done]'
2026-01-20 10:27:26 +05:30
Dhanji R. Prasanna
f24ea333f1 Add /run command to execute prompts from files
New interactive command: /run <file-path>
- Reads the specified file and executes its content as a prompt
- Supports tilde expansion for home directory paths
- Behaves exactly like pasting the file content into the g3> prompt
- Shows helpful error messages for missing files or empty content
2026-01-20 10:23:24 +05:30
Dhanji R. Prasanna
10bce7f66f Remove ANSI formatting codes from g3-core
Move terminal formatting responsibility to g3-cli layer:

- format_str_replace_summary(): Remove ANSI codes, add colorize_str_replace_summary()
  helper in CLI to apply green/red colors for insertions/deletions
- format_timing_footer(): Remove dimming ANSI codes (now plain text)
- str_replace tool result: Remove ANSI codes from success message

Remaining acceptable ANSI usage in g3-core:
- iTerm2 inline image protocol (terminal-specific escape sequence)
- Image metadata dimming (direct print, would need larger refactor)
- Terminal beep for stale TODO warning (audio, not visual)
- ANSI stripping utility in research.rs (not output)

This continues the separation of concerns: g3-core handles logic,
g3-cli handles all terminal formatting.
2026-01-20 10:00:37 +05:30
Dhanji R. Prasanna
182f5f98fe Centralize g3 status message formatting
Extract a new g3_status module in g3-cli that provides consistent formatting
for all 'g3:' prefixed system status messages.

Key changes:
- Add G3Status struct with methods for progress, done, failed, error, etc.
- Add Status enum with Done, Failed, Error, Resolved, Insufficient, NoChanges
- Add ThinResult struct in g3-core for semantic thinning data
- Update UiWriter trait with print_thin_result() method
- Refactor context thinning to return ThinResult instead of formatted strings
- Update all callers to use the new centralized formatting
- Session resume/decline messages now use G3Status
- Compaction status messages now use G3Status

This maintains clean separation of concerns: g3-core emits semantic data,
g3-cli handles all terminal formatting and colors.
2026-01-20 09:50:55 +05:30
Dhanji R. Prasanna
6ff21a7d47 Fix JSON filter to preserve code fence and indented content
Two cosmetic bugs fixed:
1. JSON inside code fences was being filtered - now tracks fence state
   and passes through all content inside ``` ... ``` blocks
2. Indented JSON was being filtered - now recognizes that real tool
   calls are never indented, so indented JSON is always documentation

Changes:
- Added in_code_fence and fence_buffer fields to FilterState
- Added track_code_fence() to detect ``` markers (with/without language)
- Added pass_through_char() for content inside code fences
- Modified '{' handling to only filter when no leading whitespace
- Added 4 new unit tests for code fence and indentation cases
- Updated 3 stress tests to expect new (correct) behavior

All 16 filter_json unit tests and 59 stress tests pass.
2026-01-19 17:00:43 +05:30
Dhanji R. Prasanna
07bff7691a Make /resume session prompt more compact
Output is now a single line:
  Session number to resume (Enter to cancel): 1 ... resuming scout_88871653e8e5f4f7 [done]

- Session ID displayed in cyan
- [done] displayed in bold green
- [error: ...] displayed in bold red on failure
- Added print_inline() to SimpleOutput for inline prompts
2026-01-18 18:41:24 +05:30
Dhanji R. Prasanna
0234920446 Print g3 progress and status on same line
- print_g3_progress now uses print! instead of println!
- print_g3_status completes the line with just the status
- Result: 'g3: compacting session ... [done]' on one line
2026-01-17 17:28:20 +05:30
Dhanji R. Prasanna
8dad00bdd0 Colorize session name in cyan in continuation prompt 2026-01-17 15:58:46 +05:30
Dhanji R. Prasanna
0d6a66a252 Compress session continuation prompt to single line
- Combine session info and resume prompt on one line
- Show result inline after user input (y/n)
- Green '... resuming ... [done]' on successful resume
- Dark grey '... starting fresh' when declining
- Yellow '... failed: <error>' on restore failure
2026-01-17 15:56:05 +05:30
Dhanji R. Prasanna
5622e5b21e refactor(cli): show only loaded items in startup status line
Changes the startup status line to only display items that were
actually loaded, instead of showing dots for missing items.

Before: "   · README  · AGENTS.md  ✓ Memory"
After:  "   ✓ Memory"

Also adds include prompt to the status line when specified:
"   ✓ prompt.md  ✓ Memory"

The order matches the load order: README → AGENTS.md → include prompt → Memory
2026-01-17 15:35:37 +05:30
Dhanji R. Prasanna
4877f8ae8a test(cli): add integration tests for --include-prompt and --no-auto-memory flags
Adds blackbox tests to verify:
- --include-prompt option is recognized by CLI parser
- --include-prompt appears in help output
- --no-auto-memory option is recognized by CLI parser
- --no-auto-memory appears in help output
2026-01-17 15:27:04 +05:30
Dhanji R. Prasanna
b0740b63c2 feat(cli): add --no-auto-memory flag to disable memory reminder in agent mode
Adds a flag to disable the automatic memory update reminder that runs
at the end of agent mode. Useful when running agents that should not
modify project memory.
2026-01-17 15:24:16 +05:30
Dhanji R. Prasanna
6bb5448d3f feat(project_files): add read_include_prompt() and update combine_project_content()
- Add read_include_prompt() function to read prompt content from a file
- Update combine_project_content() to accept include_prompt parameter
- Change prompt order: cwd → agents → readme → language → include_prompt → memory
- Add section markers around Project Memory for clearer boundaries
- Add comprehensive tests for include prompt functionality and ordering
2026-01-17 15:20:01 +05:30
Dhanji R. Prasanna
e45d5b25f3 feat(cli): wire up --include-prompt in main CLI and agent mode
Updates lib.rs and agent_mode.rs to read the include prompt file
and pass it through to combine_project_content(). The include prompt
is placed after language prompts but before project memory.
2026-01-17 15:19:55 +05:30
Dhanji R. Prasanna
56e8fddfc4 feat(cli): add --include-prompt flag for dynamic prompt injection
Adds a new CLI flag that allows users to include additional prompt
content from a file. The content is appended to the system prompt
before project memory is loaded.
2026-01-17 15:19:49 +05:30
Dhanji R. Prasanna
eb6268641f Fix --safari flag being blocked by Chrome diagnostics
When --safari was passed, Chrome diagnostics were still running because
--chrome-headless defaults to true. This caused the CLI to hang while
running diagnostics for a browser that wouldn't be used.

Now skip Chrome diagnostics when --safari is explicitly set.
2026-01-17 09:20:21 +05:30
Dhanji R. Prasanna
e3967a9948 refactor: remove animation from context thinning display
Simplify print_context_thinning to just print the message directly.
The message already contains proper ANSI formatting from context_window.rs.

Removes the flash animation and 'Context optimized successfully' footer.
2026-01-17 05:00:12 +05:30
Dhanji R. Prasanna
0e33465342 Add print_g3_progress/print_g3_status methods for consistent status messages 2026-01-16 20:28:24 +05:30
Dhanji R. Prasanna
95f89d3f8e Simplify compaction status messages 2026-01-16 20:26:35 +05:30
Dhanji R. Prasanna
415226ca84 Add newline before context progress display 2026-01-16 20:24:29 +05:30
Dhanji R. Prasanna
cebec23075 Fix duplicate response printing in interactive mode
The response was being printed twice: once during streaming and again
after task completion. Removed the redundant print_smart() call since
streaming already displays the response in real-time.
2026-01-16 14:48:50 +05:30
Dhanji R. Prasanna
4c6878a63d Set process title to agent name in agent mode
When running g3 --agent butler, the process title is now "g3 [butler]"
which shows up in ps, Activity Monitor, top, etc.

Uses the proctitle crate for cross-platform support.
2026-01-16 14:37:58 +05:30
Dhanji R. Prasanna
1f6a5671b2 Use agent name as prompt in --agent --chat mode (e.g., "butler>")
Changed run_interactive() parameter from bool to Option<&str> agent_name.
When agent_name is Some, use it as the prompt instead of "g3>".
2026-01-16 13:58:45 +05:30
Dhanji R. Prasanna
2e6bef4b24 Auto-memory: call once on exit for --agent --chat, per-turn for single-shot
When running g3 --agent <name> --chat:
- Skip per-turn memory checkpoint calls (too onerous)
- Call memory checkpoint once when exiting (Ctrl-D)

When running g3 --agent <name> (single-shot):
- Preserve existing behavior: call memory checkpoint after each turn

This keeps the auto-memory feature useful without being intrusive
in interactive agent sessions.
2026-01-16 13:35:40 +05:30
Dhanji R. Prasanna
6068249827 Simplify --agent --chat startup: minimal output, no session resume
When running g3 --agent <name> --chat, the output is now minimal:
- Workspace path (-> ~/path)
- Status line (README/AGENTS.md/Memory)
- Context progress bar
- Prompt (g3>)

Skipped in this mode:
- Session resume prompts
- "agent mode | name (source)" header
- "g3 programming agent" welcome
- Provider info display
- Language guidance messages

Added from_agent_mode parameter to run_interactive() to control
whether verbose welcome and session resume are shown.
2026-01-16 13:31:10 +05:30
Dhanji R. Prasanna
7c59d1993c Fix auto-memory JSON leak: tool call printed raw to UI
The JSON filter only suppresses tool calls at line boundaries. When
"Memory checkpoint: " was printed without a trailing newline, the LLM
response `{"tool": "remember", ...}` appeared on the same line and
leaked through to the UI.

Fix:
- Add trailing newline to "Memory checkpoint:" message
- Reset JSON filter state before streaming the response

Added test: test_tool_call_not_at_line_start_passes_through
Documents the filter behavior and references the fix location.
2026-01-16 13:10:18 +05:30
Dhanji R. Prasanna
94544c8f6a Add interactive mode support for agents with --chat flag
- Remove chat from conflicts_with_all for --agent flag
- Add chat parameter to run_agent_mode()
- Run interactive loop instead of single task when --chat is passed

Usage: g3 --agent <name> --chat
2026-01-16 12:01:56 +05:30
Dhanji R. Prasanna
637884f84b Fix duplicate todo_read display in agent mode
The print_todo_compact() function was missing the call to clear the
streaming hint line before printing the final tool output. This caused
the tool name to appear twice when the hint line wasn't cleared:

  ● todo_read     ● todo_read   | empty

Added the missing handle_hint(ToolParsingHint::Complete) call to match
the behavior of print_tool_compact().
2026-01-16 06:38:11 +05:30
Dhanji R. Prasanna
a84fead03b refactor: improve readability of streaming parser and JSON filter
Agent: carmack

Changes:
- streaming_parser.rs: Unified find_first/last_tool_call_start into single
  find_tool_call_start with SearchDirection enum, reducing duplication.
  Simplified is_json_invalidated from 45 to 20 lines with clearer logic.
  Fixed redundant !escape_next check in find_complete_json_object_end.

- filter_json.rs: Simplified check_tool_pattern from 40 to 24 lines.
  Replaced repetitive prefix checks with loop over ["t", "to", "too", "tool"].
  Reduced trailing return statements with direct expression returns.

- ui_writer_impl.rs: Added ansi module for duration color constants.
  Simplified duration_color function by removing redundant comments.

- language_prompts.rs: Fixed test assertions to match actual prompt content
  ("obvious, readable Racket" instead of "RACKET-SPECIFIC GUIDANCE").

All 174+ tests pass. No behavior changes.
2026-01-15 13:49:29 +05:30
Dhanji R. Prasanna
0ae1a13cdb feat: real-time tool call streaming indicator with blinking UI
- Add ToolParsingHint enum (Detected/Active/Complete) for UI feedback
- New UiWriter methods: print_tool_streaming_hint(), print_tool_streaming_active()
- Refactor ConsoleUiWriter state to use atomics in ParsingHintState
- Add tool_call_streaming field to CompletionChunk for provider hints
- Anthropic provider sends streaming hints when tool name detected
- New streaming helpers: make_tool_streaming_hint(), make_tool_streaming_active()

Parser improvements:
- Add is_json_invalidated() to detect false positive tool patterns
- Fix tool result poisoning when file contents contain partial JSON
- Unescaped newlines in strings or prose after JSON invalidates detection

User sees ' ● tool_name |' immediately when tool call starts streaming,
with blinking indicator while args are received.
2026-01-15 13:49:29 +05:30
Dhanji R. Prasanna
65807eea99 Add carmack.rust.md agent-specific language prompt
Rust-specific readability guidance for the carmack agent including:
- let...else example for shallow control flow
- Async: don't block the runtime (tokio::fs, spawn_blocking, Send)
- Visibility: prefer pub(crate), private fields with accessors
- Generics: impl Trait over explicit params, avoid complex where clauses
- Improved iterator guidance: if you need a comment, use a loop
- UTF-8 string slicing warnings
- Ownership/lifetime pragmatism
- Anti-patterns: no macros/typestate/proc-macros unless already in repo

Also adds Rust detection to LANGUAGE_PROMPTS (empty base prompt,
agent-specific prompts handle the guidance).
2026-01-15 13:49:29 +05:30
Jochen
6d1aa62ba7 Merge pull request #63 from cjustice/fix/tracing-subscriber-panic
Fix tracing subscriber panic in scout agent
2026-01-15 12:54:31 +11:00
Jochen
0bca05a1ba Merge pull request #62 from cjustice/fix/planning-verbose-flag
Fix: Initialize logging before planning mode check
2026-01-15 12:51:11 +11:00
Dhanji R. Prasanna
5d8dbc43f8 Add agent-specific language prompt injection
When running in agent mode (e.g., --agent carmack) in a workspace with
detected languages, inject agent+language-specific prompts from
prompts/langs/<agent>.<lang>.md at the end of the system prompt.

Changes:
- Add AGENT_LANGUAGE_PROMPTS static array for compile-time embedding
- Add get_agent_language_prompt() to look up specific agent+lang combos
- Add get_agent_language_prompts_for_workspace_with_langs() that returns
  both content and matched languages for display
- Update agent_mode.rs to inject prompts and show which languages loaded
- Display format: '✓ carmack: racket language guidance'
- Add tests for new functionality

Uses the same detect_languages() mechanism as regular language prompts
to avoid code-path aliasing.
2026-01-15 06:43:29 +05:30
Connor Justice
fa29a64e51 Simplify logging initialization comment
Removed unnecessary comment about logging initialization.
2026-01-14 17:53:04 -05:00
Connor Justice
505225c0bd fix: prevent panic when tracing subscriber already initialized
Use try_init() instead of init() for tracing subscriber setup to
gracefully handle cases where a global subscriber is already set.

This fixes a panic in the scout agent subprocess when spawned by the
research tool, where a dependency may have already initialized tracing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:33:22 -05:00
Connor Justice
6532442d32 fix: initialize logging before planning mode check
Move initialize_logging() call to run immediately after CLI parsing,
before any mode checks. This ensures the --verbose flag works correctly
in planning mode, which previously bypassed logging initialization.

Previously, planning mode would return early before initialize_logging()
was called, causing verbose output to be silently ignored.
2026-01-14 14:33:44 -05:00
Dhanji R. Prasanna
afec65fd50 Add language-specific prompt injection for toolchain guidance
- Add language_prompts module that auto-detects programming languages in workspace
- Scan for language files with depth limit (2) to inject relevant toolchain prompts
- Add prompts/langs/ directory for language-specific markdown files
- Include Racket/raco toolchain guidance as first language prompt
- Update combine_project_content() to accept language_content parameter
- Integrate language detection into main CLI flow and agent mode
- Update project memory with new feature documentation
2026-01-14 21:00:52 +05:30