Commit Graph

118 Commits (f4e642240c9238cf32a13b8ff47349f68230d3e3)

Author SHA1 Message Date
PeninsulaInd 0b3ab904de Add API cost tracking and switch planner to Grok 4.1 Fast
Track per-call token usage and estimated costs across all OpenRouter models.
Switch planner agent from Claude Sonnet 4.6 ($3/$15 per M) to Grok 4.1 Fast
($0.20/$0.50 per M) for ~25x cost reduction. Add budget alerts, a dashboard
card, and a check_api_usage tool for visibility into spending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:00:11 -06:00
PeninsulaInd ab2c313baa Add report_issue tool and planner agent for self-improvement tracking
- New report_issue tool logs bugs/improvements to memory/improvement_requests.md
- Planner agent (Sonnet via OpenRouter) for architecture and debugging tasks
- Heartbeat checks for pending improvement requests to surface to Bryan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:31:28 -06:00
PeninsulaInd 30757b5bcf Generate conversation titles via LLM instead of truncating first line
- _maybe_set_title sets a quick truncated fallback immediately
- Then fires a background thread to ask the LLM for a 5-8 word summary
- Background thread doesn't block the streaming response
- Title appears in sidebar on first chunk, then upgrades when LLM responds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:11:34 -06:00
PeninsulaInd d771dd5c80 Stop creating empty conversations that clutter sidebar with 'New Chat'
- agent.new_conversation() now just resets conv_id to None; DB row is
  created lazily by ensure_conversation() when user sends first message
- on_app_load no longer eagerly creates a conversation on page load
- list_conversations filters out conversations with no messages so
  orphaned empty rows don't appear in the sidebar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:08:34 -06:00
PeninsulaInd 603878e095 Fix conversation titles stuck on 'New Chat' and add loop timestamps to dashboard
- Move _maybe_set_title() to run at start of respond() generator (before streaming)
  so titles are set even if the generator is closed mid-stream by Gradio
- Refresh sidebar conv list on first streaming chunk for immediate title display
- Backfilled 34 existing conversation titles from their first user messages
- Add scheduler loop status cards (heartbeat, poll, clickup, folder_watch) to
  both System Health and Notifications tabs in the HTML dashboard
- Loop cards show relative time (e.g. "3m ago") with color-coded status

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:54:43 -06:00
PeninsulaInd f8320a9fea Set folder watcher completed tasks to 'complete' instead of 'internal review'
Link building runs that finish successfully are already deployed,
so they go straight to complete. PRs still go to internal review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:20:56 -06:00
PeninsulaInd 3c41c6bf5f Skip tasks without due dates in status counts, remove Companies card
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:07:26 -06:00
PeninsulaInd 6fd565734f Filter LB status cards to relevant statuses and recent tasks
Only show To Do, In Progress, Error, Automation Underway counts.
Exclude tasks due more than 1 month ago. Add "Scheduled next month"
card showing upcoming work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:39:39 -06:00
PeninsulaInd f9142e6669 Skip Office temp/lock files (~$) in folder watcher
Prevents the watcher from picking up ~$*.xlsx lock files created by
Excel, which would match the same ClickUp task and corrupt its status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:02:06 -06:00
PeninsulaInd ee7b4cc256 Add Cora Reports to Run queue as first section on Link Building tab
Filters out automation-touched tasks (error, automation underway, complete,
closed, done, internal review) and sorts by due date. Renders with 10-at-a-time
pagination and responsive mobile layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:55:07 -06:00
PeninsulaInd 3f2798d338 Add "automation underway" and "error" ClickUp statuses for bot visibility
Tasks now show "automation underway" when the bot picks them up and "error"
on failure, replacing the old "in progress" / "to do" fallbacks that were
invisible on Bryan's ClickUp board. Folder watcher also syncs ClickUp status
on match, missing IMSURL, pipeline failure, success, and exceptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:36:58 -06:00
PeninsulaInd 62186d8dec Fix folder watcher matching, notifications, and BLM venv isolation
- Remove status filter from folder watcher so tasks in any open status
  (including "internal review") are matched by keyword
- Add retry logic for stuck processing/blocked/unmatched KV states
- Fix notification ordering (newest first, limit 50) and date parsing
- Use BLM's own .venv Python instead of uv run for subprocess calls
- Document external tools venv convention in CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:35:54 -06:00
PeninsulaInd 3b4a8e47be Require IMSURL for Cora pipeline, fail early if missing
Remove placeholder URL fallback from ingest-cora args. Add early
validation in run_cora_backlinks and folder watcher — if IMSURL is
empty, block the task with a notification instead of running with a
fake URL. Update tests to pass money_site_url and add missing-URL test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:11:11 -06:00
PeninsulaInd 01ba657b35 Fix Cora filter, speed up Overview, add inbox path link
Remove status gate from Cora filter — LB Method is the discriminator,
not status. Derive Overview stats and Cora section from /tasks data
directly (no slow /tasks/link-building fetch). Add click-to-copy
Z:\cora-inbox path next to Cora header. Show due dates in This Month.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:51:29 -06:00
PeninsulaInd f67f1b9124 Rename Client field to Customer and refine Overview sections
ClickUp "Client" custom field was deleted; switch all references to
"Customer" across config, tools, tests, and docs. Refine Overview tab:
rename Due Soon to Up Next (today/tomorrow, fallback next 5), expand
This Month to include both month tag and due-date-in-month matches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:20:19 -06:00
PeninsulaInd 0d60b1b516 Overhaul dashboard to use Overall lists with focused views
Switch from get_tasks_from_space (all lists) to get_tasks_from_overall_lists
(only "Overall" list per folder) to reduce noise. Add tags and date_done
fields to ClickUpTask. Redesign Overview tab with Due Soon, This Month,
and Cora Reports Needed sections. Add Recently Completed and In Progress
Not Started sections to Link Building tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:59:55 -06:00
PeninsulaInd e1992fa049 Add data-driven dashboard with API backend
- New cheddahbot/api.py: FastAPI router with endpoints for tasks,
  link building, press releases, agents, system health, notifications,
  KV states, and cache management (all cached 5min)
- Rewrote dashboard/index.html: replaces all hardcoded data with JS
  that fetches from /api/ endpoints. Tabs: Overview, Link Building,
  Press Releases, By Company, System Health, Agents, Notifications
- Updated __main__.py: mounts API router, removes old inline
  /api/linkbuilding/status endpoint
- Fixed run_link_building to reject empty LB Method instead of
  defaulting to Cora Backlinks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:53:51 -06:00
PeninsulaInd dd39fa2e94 Show tool call args in chat and raise max iterations to 15
- Display tool arguments in the calling indicator so user can see what
  each tool call is doing (e.g. Calling delegate_task(prompt='...')...)
- Bump MAX_TOOL_ITERATIONS from 5 to 15 for complex chat interactions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:44:41 -06:00
PeninsulaInd d9e0020b67 Fix UI errors, message formatting, scheduler auto_execute, and LLM retry
Core fixes:
- Rewrite router.py format_messages_for_llm() to properly handle tool
  call/result message pairs in OpenAI format instead of faking them as
  user messages — root cause of most LLM API errors
- Fix scheduler ignoring auto_execute:false flag, which caused all Link
  Building tasks to be incorrectly executed and moved to internal review
- Add safety check so Skipped/Error tool results don't get marked as
  completed in ClickUp

Additional improvements:
- Add LLM retry logic (2 retries on transient 5xx/timeout/rate-limit)
- Replace raw LLM tracebacks with friendly error messages
- Fix ghost assistant bubble in UI by deferring append to first chunk
- Auto-title conversations from first user message
- Consistent tool_call_id generation (resolve once, reuse everywhere)
- Reduce pipeline status polling from 3s to 10s
- Update CLAUDE.md: remove stale watchdog/autostart docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:34:02 -06:00
PeninsulaInd 916bec8c0e Reformat code and update ClickUp tools to reset pattern
- Ruff format: consistent dict/call wrapping in agent.py, db.py,
  skills.py, delegate.py
- Replace clickup_approve_task/clickup_decline_task with
  clickup_reset_task/clickup_reset_all (simpler state machine)
- Add kv_delete() method to Database
- Add due_date and field filter tests to test_clickup.py
- Update test_clickup_tools.py for new reset tools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:44:40 -06:00
PeninsulaInd a1fc5a7c0f Fix lint issues across link building files
- Remove f-prefix from strings with no placeholders
- Use list unpacking instead of concatenation
- Fix import sorting in test file
- Remove unused Path import
- Use contextlib.suppress instead of try/except/pass
- Wrap long lines to stay under 100 chars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:13:37 -06:00
PeninsulaInd 0f4c77adc9 Add link building API endpoint and skill file
- /api/linkbuilding/status endpoint returns pending, in-progress,
  completed, and failed pipeline states for dashboard consumption
- skills/linkbuilding.md with YAML frontmatter linking tools and agents
- Skill body documents workflow, triggers, default flags, and ClickUp fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:09:00 -06:00
PeninsulaInd 90e79b77ab Add folder watcher thread to scheduler for Cora inbox
- 4th daemon thread _folder_watch_loop scans Z:/cora-inbox
- Fuzzy-matches .xlsx filename stems to ClickUp Keyword fields
- On match: runs run_cora_backlinks, moves file to processed/
- On failure: marks in KV store, notifies via NotificationBus
- Uses existing _get_clickup_client and notification infrastructure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:07:24 -06:00
PeninsulaInd 40aca81e16 Add create_custom_field to ClickUp client and link building test suite
- ClickUpClient.create_custom_field() for POST /list/{id}/field
- 40+ tests covering output parsers, CLI arg builder, pipeline,
  ClickUp state machine, and folder scanning
- All tests mock subprocess.run, never call Big-Link-Man

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:05:54 -06:00
PeninsulaInd 2d5ed29c0d Add link building tool module with pipeline orchestration
- run_link_building: dispatcher that routes to correct pipeline by LB Method
- run_cora_backlinks: full pipeline (ingest-cora → generate-batch) with ClickUp sync
- blm_ingest_cora: standalone ingest tool
- blm_generate_batch: standalone generate tool
- scan_cora_folder: utility to inspect watch folder contents
- setup_linkbuilding_fields: one-time ClickUp field creation
- Private helpers for subprocess execution, output parsing, fuzzy matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:04:02 -06:00
PeninsulaInd e2dca938a1 Add LinkBuildingConfig and link_builder agent to config
- New LinkBuildingConfig dataclass (blm_dir, watch_folder, interval, ratio)
- YAML loading block and BLM_DIR env var override in load_config()
- Link Building skill_map entry with field mappings in config.yaml
- link_building section in config.yaml
- link_builder agent definition in agents section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:01:55 -06:00
PeninsulaInd 0becf1dd89 Revert "Add link building agent with content generation pipeline"
This reverts commit 8a98b37725.
2026-02-19 18:38:51 -06:00
PeninsulaInd 8a98b37725 Add link building agent with content generation pipeline
New linkbuilder agent that handles ClickUp "Link Building" tasks.
For each keyword/company, generates three content pieces via the
execution brain: a guest article (500-700 words), a directory
listing, and a social media post — each with proper SEO anchor
text and backlinks. Integrates with ClickUp for status updates,
comments, and file attachments.

- cheddahbot/tools/linkbuilding.py: build_links tool with full pipeline
- skills/linkbuilding.md: skill prompt for SEO content generation
- config.yaml: linkbuilder agent config + Link Building skill_map entry
- tests/test_linkbuilding.py: 36 tests covering helpers, prompts,
  pipeline, file output, error handling, and ClickUp sync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:52:06 -06:00
PeninsulaInd deae147795 Hide clickup_task_id from LLM tool schema to prevent hallucination
Removed clickup_task_id from write_press_releases function signature
so the LLM cannot see or fabricate a task ID. The parameter is now
passed through ctx by the ToolRegistry — the scheduler sets it in
args, and execute() moves it into the ctx dict before filtering.
Only system-injected task IDs can reach the tool.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:38:11 -06:00
PeninsulaInd 082ca6ba44 Fix PR task flow: add ClickUp status updates, comments, and attachments
The press release tool now handles its own ClickUp sync lifecycle when
a clickup_task_id is provided — sets status to "in progress" with a
starting comment, uploads docx attachments after creation, then sets
status to "internal review" with a completion comment. The scheduler
now passes clickup_task_id to tools and defers to tool-level sync when
detected, falling back to scheduler-level sync for other tools.
ToolRegistry.execute() now filters args to accepted params to prevent
TypeError when extra keys (like clickup_task_id) are passed to tools
that don't accept them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:36:45 -06:00
PeninsulaInd 0f2274e6f1 Phase 4: UI — Agent selector, conversation history, chat persistence
Add sidebar layout with agent selector (Radio), conversation history
(gr.render), and BrowserState for localStorage session persistence.
Conversations tagged by agent_name for per-agent history filtering.
Sidebar auto-closes on mobile viewports via JS. 11 new tests (135 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:23:50 -06:00
PeninsulaInd e5e9442e3d 3.6: Add delegate_to_agent tool for cross-agent delegation
New tool in delegate.py routes tasks to named agents via
agent.respond_to_prompt(). Includes thread-local depth counter
(max 3) to prevent infinite A->B->A delegation loops. Extended
ctx injection in ToolRegistry to include agent_registry. Wired
agent_registry into ToolRegistry from __main__.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:13:32 -06:00
PeninsulaInd 9d4d12e232 3.5: Wire multi-agent startup in __main__.py
Loop over config.agents to create per-agent LLM (when model override set),
Agent, MemorySystem (with scope), and register in AgentRegistry. Shared
ToolRegistry and SkillRegistry are wired to all agents. Scheduler and UI
use the default agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:12:08 -06:00
PeninsulaInd 883fee36a3 3.4: Add per-agent memory scoping
MemorySystem now accepts optional scope parameter. When set:
- Memory files go to memory/{scope}/ subdirectory
- Fallback search covers both scoped and shared directories

Unscoped agents (scope="") use the shared memory/ root directory.
This enables agents to have private memory while still searching
shared knowledge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:09:31 -06:00
PeninsulaInd 86511d5a0f 3.3: Modify Agent and ToolRegistry for multi-agent
Agent changes:
- Accept optional AgentConfig in __init__
- Add name property
- Filter tools via agent_config.tools whitelist in respond()
- Use agent-specific personality file when configured
- Pass agent name to skills registry for filtering

ToolRegistry changes:
- get_tools_schema() accepts filter_names parameter
- get_tools_description() accepts filter_names parameter
- When filter_names is None, all tools are returned (backward compat)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:08:16 -06:00
PeninsulaInd 537e3bd528 3.2: Create AgentRegistry
New file cheddahbot/agent_registry.py. Holds multiple Agent instances
keyed by name with methods: register(), get(), list_agents(), and
default property. First registered agent is the default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:06:56 -06:00
PeninsulaInd 6c2c28e9b0 3.1: Create AgentConfig dataclass and multi-agent config
New AgentConfig dataclass in config.py with fields:
- name, display_name, personality_file, model
- tools (whitelist), skills (filter), memory_scope

Loaded from config.yaml under agents: key. Defaults to single
agent for backward compatibility when section is omitted.

config.yaml now includes 4 agent configs: default, writer,
researcher, ops — each with appropriate tool/skill whitelists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:06:12 -06:00
PeninsulaInd 724ccfebd6 2.4: Strip frontmatter in press_release.py _load_skill()
The _load_skill() function now strips YAML frontmatter (--- ... ---)
before returning skill content. This prevents the execution brain
from receiving metadata intended for the skill registry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:03:22 -06:00
PeninsulaInd 5311731855 2.3: Wire skills into system prompt
- router.py: build_system_prompt() gets skills_context parameter,
  injected between memory and tools sections
- agent.py: Agent gets set_skills_registry(), calls it in respond()
  to get skills prompt section
- __main__.py: Creates SkillRegistry from skills_dir, wires to agent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:02:34 -06:00
PeninsulaInd c651ba22b7 2.2: Create cheddahbot/skills.py — markdown skill registry
New module (not package) that discovers .md files with YAML frontmatter
in the skills/ directory. Provides:
- SkillDef dataclass: name, description, content, tools, agents, file_path
- SkillRegistry: discovers skills, filters by agent, builds prompt sections
- _parse_frontmatter(): splits YAML frontmatter from markdown body
- get_prompt_section(agent_name): builds system prompt injection
- get_body(name): returns skill content without frontmatter

Files without frontmatter (data files) are automatically skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:01:17 -06:00
PeninsulaInd 4a646373b6 1.5: Fix tool results — use role:tool with tool_call_id
Previously tool results were injected as role:user messages which
confuses some models. Now the live agent loop uses proper OpenAI
function-calling format:
- Assistant messages include tool_calls array with IDs
- Tool results use role:tool with matching tool_call_id

History replay in router.py is unchanged (no tool_call_ids in DB).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:00:21 -06:00
PeninsulaInd 202a5e99e4 1.4: Wire require_approval check for shell commands
When config.shell.require_approval is True, run_command now refuses
execution and directs the user to delegate_task instead. The execution
brain (Claude Code CLI) has its own approval controls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:59:27 -06:00
PeninsulaInd ed751d843b 1.3: Fix files parameter in agent.py — attachments now visible to LLM
Previously respond() accepted files but silently dropped them.
Now when files are attached:
- Images are base64-encoded as image_url content parts
- Text files are read and inlined as text content parts
- The last user message is converted to multipart format

Follows the same encoding pattern used in tools/image.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:58:44 -06:00
PeninsulaInd 9002fc08d2 1.2: Fix thread safety in memory.py embedding DB
Replace 4 standalone sqlite3.connect()/conn.close() pairs with a
thread-local _embed_conn property, matching the pattern in db.py.
Adds WAL mode for better concurrent read/write performance.

This prevents potential collisions between scheduler threads and
Gradio request threads accessing the embedding database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:57:41 -06:00
PeninsulaInd 0bef1e71b3 1.1: Delete dead code and fix all lint errors
Remove unused modules that were never called at startup:
- cheddahbot/skills/__init__.py (dead @skill decorator system)
- cheddahbot/providers/__init__.py (empty placeholder)
- cheddahbot/tools/build_skill.py (depends on dead skills system)
- cheddahbot/tools/build_tool.py (security risk: generates arbitrary Python)

Also fix all pre-existing ruff lint errors across the codebase:
- Fix import sorting, unused imports, line length violations
- Fix type comparisons (use `is` instead of `==`)
- Fix implicit Optional types (dict -> dict | None)
- Fix unused variables, ambiguous variable names
- Apply ruff format for consistent style

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:56:36 -06:00
PeninsulaInd a7171673fc Add clickup_task_id param to write_press_releases for chat-triggered sync
When a press release is triggered via chat with a ClickUp task ID, the
tool now uploads .docx attachments, posts a result comment, and updates
task status — matching what the scheduler does automatically. ClickUp
sync is wrapped in try/except so failures don't lose PR results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 21:42:41 -06:00
PeninsulaInd 46bc38106e Add retry logic to ClickUp API writes and fix review status
- Add _retry() helper to ClickUpClient (3 attempts, exponential backoff,
  only retries 5xx/transport errors)
- Apply retry to update_task_status, add_comment, upload_attachment
- Fix review_status from "review" to "internal review" in config and defaults
- Update SOUL.md personality and USER.md profile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 20:52:39 -06:00
PeninsulaInd cf1faceab1 Route specialized tools directly instead of delegating to execution brain
The LLM was delegating write_press_releases to the execution brain
(Claude Code CLI subprocess), bypassing the Python tool's orchestration,
skill prompts, and pipeline status updates. Add an exception to the
system prompt so specialized tools are called directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:18:00 -06:00
PeninsulaInd 76c0711704 Fix scheduler breaking DB encapsulation for one-time task disabling
Add Database.disable_task() public method and replace direct _conn
access in scheduler._run_due_tasks().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:09:38 -06:00
PeninsulaInd ff3114b515 Add .docx attachment uploads to ClickUp tasks after press release generation
When a press release task completes, docx file paths are extracted from
the tool output and uploaded as attachments to the ClickUp task. The
completion comment now includes an attachment count note.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:04:23 -06:00
PeninsulaInd 388c800bce Remove voice chat, conversation history, and settings UI sections
Strip unused UI components: voice chat accordion, conversation history
panel, and settings accordion. Removes associated event handlers and
helper functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:01:57 -06:00
PeninsulaInd 712829a610 Optimize NotificationBus subscribe cursor and update CLAUDE.md
Replace inefficient two-query approach (fetch up to 10k rows to find max ID)
with a single SELECT MAX(id) query. Update CLAUDE.md test count (51 → 118)
and add 3 missing test file descriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:01:18 -06:00
PeninsulaInd 20708e6033 Fix execution brain tool permissions in non-interactive mode
Add --allowedTools flag to Claude Code CLI subprocess so tools are
pre-approved and don't prompt for permission in pipe mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:39:21 -06:00
PeninsulaInd 5e9cef5e39 Add submit_press_release tool with Press Advantage API integration
Adds PressAdvantageClient API wrapper and submit_press_release tool that
posts finished press releases to PA as drafts. Auto-constructs SEO links
(brand+keyword → IMSURL, company name → SocialURL/GBP/homepage) with
fuzzy anchor matching and warnings when phrases can't be found. The PR
writing prompt now requests anchor text phrases and validates them after
generation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:37:41 -06:00
PeninsulaInd 8f6e218221 Add document export (.docx) and email delivery feature
Press releases now auto-generate .docx files alongside .txt for native
Google Docs import. New email_file chat tool sends files via Gmail SMTP
with app password auth, auto-converting .txt to .docx before sending.
Also includes Press Advantage API config and submit_press_release tool.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:00:54 -06:00
PeninsulaInd 7864ec6f17 Add pipeline status box to show PR tool progress in the UI
The press release pipeline takes 2-4 minutes per run with no feedback.
This adds a DB-polled status box (gr.Timer every 3s) that shows the
current step (e.g. "Step 3/4: Writing press release 1/2 — headline...")
and auto-hides when the pipeline completes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:41:33 -06:00
PeninsulaInd 7153e65ae6 Add clickup_query_tasks tool and Press Advantage API integration plan
New tool queries ClickUp API live for tasks, with optional status and
task_type filters. Fixes the execution brain instantiation bug by
providing a proper @tool wrapper around ClickUpClient.

Also saves the Press Advantage API integration plan for future work
once API access is restored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 13:21:04 -06:00
PeninsulaInd 019bf0ee3c Use Work Category field for ClickUp skill mapping
The real workspace uses "Work Category" (not "Task Type") to identify
task types like Press Release. Also update field_mapping to use "Client"
instead of "Company" to match actual custom field names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 09:52:35 -06:00
PeninsulaInd 7864ca2461 Wire NotificationBus into main and Gradio UI
Create NotificationBus in __main__.py and inject into scheduler and UI.
Gradio subscribes as the "gradio" listener with a 10-second polling
timer that displays notifications in a banner above the chatbot.
ClickUp status shown in the header bar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:29:33 -06:00
PeninsulaInd a67e714045 Add ClickUp polling loop to scheduler
Third daemon thread polls ClickUp every 20 minutes, discovers new tasks,
maps Task Type to skills via config, and auto-executes or queues for
approval. On completion updates ClickUp status + comments with results.
Recovers orphaned executing tasks on startup. Pushes all events through
the NotificationBus for UI-agnostic delivery.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:28:35 -06:00
PeninsulaInd e02f5a5cb3 Add ClickUp chat tools for task management
Four chat-facing tools: clickup_list_tasks (list/filter tracked tasks),
clickup_task_status (detailed state view), clickup_approve_task and
clickup_decline_task (approval flow for tasks awaiting permission).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:27:34 -06:00
PeninsulaInd ba89f61bc4 Add UI-agnostic notification bus
Pub/sub NotificationBus backed by DB persistence. Any interface
(Gradio, Discord, Slack) subscribes as a listener with independent
read cursors. Supports both push callbacks and poll-based consumption.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:27:02 -06:00
PeninsulaInd 0b7950cefa Add state tracking and notifications DB support
Add kv_scan() for prefix-based key-value lookups (used by ClickUp task
state tracking). Add notifications table with add_notification() and
get_notifications_after() for the UI-agnostic notification bus.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:26:38 -06:00
PeninsulaInd f34d7507c2 Add ClickUp config and REST API client
ClickUpConfig dataclass with env var loading (CLICKUP_API_TOKEN,
CLICKUP_WORKSPACE_ID, CLICKUP_SPACE_ID). Thin httpx client wrapping
ClickUp v2 API for task listing, status updates, and comments. Skill
mapping config in config.yaml maps Task Type custom fields to tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:26:16 -06:00
PeninsulaInd b3140d3522 Add autonomous press release pipeline tool
Implements write_press_releases tool that generates 7 headlines via chat
brain, AI-judges the best 2, writes 2 full press releases via execution
brain, and generates JSON-LD schemas via Sonnet with WebSearch. Saves all
output files to data/generated/press_releases/.

Also adds tools/model pass-through in agent and LLM layers, fixes Windows
command line length limit by piping prompts via stdin, and updates model
references to current versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:04:29 -06:00
PeninsulaInd 1866d48cb2 Fix chat memory persistence, duplicate tool calls, and heartbeat log noise
- Agent: deduplicate tool calls across iterations, reduce max iterations
  10→5, add system prompt instructions to prevent re-calling tools
- Router: preserve tool name in history messages, add anti-loop and
  delegate_task instructions to system prompt
- Memory: auto_flush now deletes flushed messages from DB so conversations
  don't get re-summarized repeatedly, skip tool results in summaries
- DB: add delete_messages() method, include message id in get_messages()
- Scheduler: stop logging routine heartbeat checks to daily log

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 14:23:33 -06:00
PeninsulaInd af767f9684 Implement two-brain architecture: chat brain + execution brain
Chat brain uses OpenAI-compatible APIs (OpenRouter/Ollama/LM Studio) for
all UI conversations, giving full control over system prompts so the
Cheddah personality works correctly. Execution brain uses Claude Code CLI
for heartbeat, scheduled tasks, and delegated system-level work.

- Split llm.py: chat() routes through OpenAI-compat only, new execute()
  calls Claude CLI with Bash/Read/Edit/Write/Glob/Grep tools
- Add chat_model config field (default: openai/gpt-4o-mini)
- Add delegate_task tool bridging chat brain to execution brain
- Scheduler/heartbeat now use execute_task() for real CLI power
- UI dropdown shows chat-only models with custom value support
- Updated model list to current OpenRouter top models (Feb 2026)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:59:32 -06:00
PeninsulaInd 1b73cf2e5d Initial implementation of CheddahBot personal AI assistant
Multi-model AI assistant with Gradio UI, persistent memory, 15+ tools,
and meta-tools for runtime tool creation. Routes Claude models through
Claude Code SDK (Max subscription), cloud models through OpenRouter,
and local models through Ollama/LM Studio.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 20:20:39 -06:00