diff --git a/.gitignore b/.gitignore index e2b59b525..43fc6c5a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .env .venv -sunstone.egg-info/ +solstone.egg-info/ __pycache__/ *.pyc logs/ diff --git a/AGENTS.md b/AGENTS.md index 1e5c54bd7..2a4c943db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,10 +1,10 @@ # Development Guidelines & Contribution Standards -This document provides comprehensive guidelines for contributing to Sunstone, whether you're an AI assistant, human developer, or automated system. +This document provides comprehensive guidelines for contributing to solstone, whether you're an AI assistant, human developer, or automated system. ## πŸ“‹ Project Overview -**Sunstone** is a Python-based AI-driven desktop journaling toolkit that provides: +**solstone** is a Python-based AI-driven desktop journaling toolkit that provides: * **observe/** - Multimodal capture (audio + visual) and AI-powered analysis * **think/** - Data post-processing, summarization, and intelligent insights @@ -17,7 +17,7 @@ The project uses a modular architecture where each package can operate independe ## πŸ”‘ Key Concepts -Understanding these core concepts is essential for working with Sunstone: +Understanding these core concepts is essential for working with solstone: * **Journal**: Central data structure organized as `JOURNAL_PATH/YYYYMMDD/` directories. All captured data, transcripts, and analysis artifacts are stored here. See [docs/JOURNAL.md](docs/JOURNAL.md). @@ -36,7 +36,7 @@ Understanding these core concepts is essential for working with Sunstone: ## πŸ—οΈ Project Structure ``` -sunstone/ +solstone/ β”œβ”€β”€ observe/ # Multimodal capture & AI analysis β”œβ”€β”€ think/ # Data post-processing & AI analysis β”œβ”€β”€ convey/ # Web app frontend & backend @@ -78,7 +78,7 @@ Each package has a README.md symlink pointing to its documentation in `docs/`. * Agents process via `muse-agents` command with persona configurations **Command Reference**: -See `pyproject.toml` `[project.scripts]` for the authoritative, current list of CLI entry points (e.g., `sunstone`, `think-*`, `observe-*`, `muse-*`, `convey*`). +See `pyproject.toml` `[project.scripts]` for the authoritative, current list of CLI entry points (e.g., `solstone`, `think-*`, `observe-*`, `muse-*`, `convey*`). --- @@ -241,7 +241,7 @@ make clean-install # Clean and reinstall * **Insight Templates**: `think/insights/*.txt` and `*.json` ### Getting Help -* Run `sunstone` for CLI command list +* Run `solstone` for CLI command list * Check [docs/DOCTOR.md](docs/DOCTOR.md) for debugging and diagnostics * Browse `docs/` for all subsystem documentation * Review test files in `tests/` for usage examples diff --git a/Makefile b/Makefile index 5e0113b46..5cafab192 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Sunstone Makefile +# solstone Makefile # Python-based AI-driven desktop journaling toolkit .PHONY: install deps test test-apps test-app lint format check clean dev full all diff --git a/README.md b/README.md index 540f8de20..00a49e2b4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -Sunstone Logo +solstone Logo -# Sunstone +# solstone Navigate Work Intelligently -A comprehensive Python-based AI-driven desktop journaling toolkit for multimodal capture, analysis, and intelligent navigation of workplace activities. Sunstone organizes captured data under a **journal** directory containing daily `YYYYMMDD` folders, enabling powerful temporal analysis and review. +A comprehensive Python-based AI-driven desktop journaling toolkit for multimodal capture, analysis, and intelligent navigation of workplace activities. solstone organizes captured data under a **journal** directory containing daily `YYYYMMDD` folders, enabling powerful temporal analysis and review. ## πŸš€ Features @@ -33,7 +33,7 @@ A comprehensive Python-based AI-driven desktop journaling toolkit for multimodal - **MCP Server** πŸ›°οΈ - `muse-mcp-tools` launches Model Context Protocol server - **Cortex** 🧩 - `muse-cortex` provides agent-based task execution -- **Help** ❓ - `sunstone` lists all available commands +- **Help** ❓ - `solstone` lists all available commands ## πŸ“¦ Installation diff --git a/apps/__init__.py b/apps/__init__.py index 22e24537b..453cdc510 100644 --- a/apps/__init__.py +++ b/apps/__init__.py @@ -1,4 +1,4 @@ -"""App plugin system for Sunstone. +"""App plugin system for solstone. Convention-based app discovery with minimal configuration: @@ -108,7 +108,7 @@ class App: class AppRegistry: - """Registry for discovering and managing Sunstone apps.""" + """Registry for discovering and managing solstone apps.""" def __init__(self): self.apps: dict[str, App] = {} diff --git a/apps/entities/agents/entity_describe.txt b/apps/entities/agents/entity_describe.txt index 22817a136..39f1c6560 100644 --- a/apps/entities/agents/entity_describe.txt +++ b/apps/entities/agents/entity_describe.txt @@ -1,4 +1,4 @@ -You are an entity description specialist for Sunstone, an AI-driven desktop journaling toolkit. Your role is to create precise, informative single-sentence descriptions for entities based on research and context. +You are an entity description specialist for solstone, an AI-driven desktop journaling toolkit. Your role is to create precise, informative single-sentence descriptions for entities based on research and context. ## Your Task diff --git a/apps/todos/agents/review.txt b/apps/todos/agents/review.txt index 090435122..783876aac 100644 --- a/apps/todos/agents/review.txt +++ b/apps/todos/agents/review.txt @@ -1,4 +1,4 @@ -You are the TODO Review Agent for Sunstone. Your sole responsibility is to verify task completion status by checking journal evidence and mutating facet-scoped todos via the MCP todo tools. +You are the TODO Review Agent for solstone. Your sole responsibility is to verify task completion status by checking journal evidence and mutating facet-scoped todos via the MCP todo tools. ## Input diff --git a/apps/todos/agents/weekly.txt b/apps/todos/agents/weekly.txt index 2df214895..327e4164f 100644 --- a/apps/todos/agents/weekly.txt +++ b/apps/todos/agents/weekly.txt @@ -1,4 +1,4 @@ -You are the TODO Weekly Scout for Sunstone, an AI-driven journaling system. Your mandate is to audit the past week's commitments for a specific facet and surface the next most impactful todos for the coming cycle while keeping today's facet-scoped checklist faithful to journal reality. +You are the TODO Weekly Scout for solstone, an AI-driven journaling system. Your mandate is to audit the past week's commitments for a specific facet and surface the next most impactful todos for the coming cycle while keeping today's facet-scoped checklist faithful to journal reality. ## Core Mission diff --git a/convey/__init__.py b/convey/__init__.py index a07f84bbb..b62d0b56a 100644 --- a/convey/__init__.py +++ b/convey/__init__.py @@ -43,7 +43,7 @@ def create_app(journal: str = "") -> Flask: ] ) - app.secret_key = os.getenv("CONVEY_SECRET", "sunstone-secret") + app.secret_key = os.getenv("CONVEY_SECRET", "solstone-secret") app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=30) # Register root blueprint (login, logout, /, favicon) diff --git a/convey/static/app.js b/convey/static/app.js index afb291614..65ec3a9a9 100644 --- a/convey/static/app.js +++ b/convey/static/app.js @@ -907,7 +907,7 @@ window.AppServices = { */ notifications: { _stack: [], - _history: JSON.parse(localStorage.getItem('sunstone:notification_history') || '[]'), + _history: JSON.parse(localStorage.getItem('solstone:notification_history') || '[]'), _nextId: 1, _container: null, @@ -1032,7 +1032,7 @@ window.AppServices = { // Persist to localStorage try { - localStorage.setItem('sunstone:notification_history', JSON.stringify(this._history)); + localStorage.setItem('solstone:notification_history', JSON.stringify(this._history)); } catch (e) { // localStorage may be full or disabled console.warn('[Notifications] Failed to persist history:', e); diff --git a/convey/templates/app.html b/convey/templates/app.html index 649548786..1fbf3a026 100644 --- a/convey/templates/app.html +++ b/convey/templates/app.html @@ -3,7 +3,7 @@ - {{ app_registry.apps[app].label }} - Sunstone + {{ app_registry.apps[app].label }} - solstone diff --git a/docs/APPS.md b/docs/APPS.md index c1e4e7d11..f40892a5e 100644 --- a/docs/APPS.md +++ b/docs/APPS.md @@ -1,8 +1,8 @@ -# Sunstone App Development Guide +# solstone App Development Guide **Complete guide for building apps in the `apps/` directory.** -Apps are the primary way to extend Sunstone's web interface (Convey). Each app is a self-contained module discovered automatically using **convention over configuration**β€”no base classes or manual registration required. +Apps are the primary way to extend solstone's web interface (Convey). Each app is a self-contained module discovered automatically using **convention over configuration**β€”no base classes or manual registration required. > **How to use this document:** This guide serves as a catalog of patterns and references. Each section points to authoritative source filesβ€”read those files alongside this guide for complete details. When in doubt, the source code is the definitive reference. @@ -284,7 +284,7 @@ from muse.mcp import register_tool, HINTS ### 7. `insights/` - App Insights -Define custom insight prompts that integrate with Sunstone's insight generation system. +Define custom insight prompts that integrate with solstone's insight generation system. **Key Points:** - Create `insights/` directory with `.txt` (prompt) + `.json` (metadata) file pairs @@ -304,7 +304,7 @@ Define custom insight prompts that integrate with Sunstone's insight generation ### 8. `agents/` - App Agents -Define custom agent personas that integrate with Sunstone's Cortex agent system. +Define custom agent personas that integrate with solstone's Cortex agent system. **Key Points:** - Create `agents/` directory with `.txt` (prompt) + `.json` (metadata) file pairs diff --git a/docs/CALLOSUM.md b/docs/CALLOSUM.md index 42251545a..bf9d2e3b7 100644 --- a/docs/CALLOSUM.md +++ b/docs/CALLOSUM.md @@ -1,6 +1,6 @@ # Callosum Protocol -Callosum is a JSON-per-line message bus for real-time event distribution across Sunstone services. +Callosum is a JSON-per-line message bus for real-time event distribution across solstone services. ## Protocol diff --git a/docs/CONVEY.md b/docs/CONVEY.md index 821163c8e..4bba6ea38 100644 --- a/docs/CONVEY.md +++ b/docs/CONVEY.md @@ -1,4 +1,4 @@ -# sunstone-convey +# solstone-convey Web-based journal review interface built with Flask. It exposes a few small views for exploring daily summaries and entity data stored inside a **journal** folder. diff --git a/docs/DOCTOR.md b/docs/DOCTOR.md index 0d2d3ebfe..75cd4bd66 100644 --- a/docs/DOCTOR.md +++ b/docs/DOCTOR.md @@ -1,4 +1,4 @@ -# Sunstone Diagnostic Guide +# solstone Diagnostic Guide Quick reference for debugging and diagnosing issues. For detailed specifications, see linked documentation. diff --git a/docs/INTEGRATION_TESTS.md b/docs/INTEGRATION_TESTS.md index 709fc7219..ae667b4ff 100644 --- a/docs/INTEGRATION_TESTS.md +++ b/docs/INTEGRATION_TESTS.md @@ -1,6 +1,6 @@ # Integration Tests -This directory contains integration tests for Sunstone that are separate from the unit tests in the parent `tests/` directory. +This directory contains integration tests for solstone that are separate from the unit tests in the parent `tests/` directory. ## Purpose diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index e46e8432c..4e75cac75 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -1,10 +1,10 @@ -# Sunstone Journal Guide +# solstone Journal Guide This document describes the layout of a **journal** directory where all captures, extracts, and insights are stored. Each dated `YYYYMMDD` folder is referred to as a **day**, and within each day captured content is organized into **segments** (timestamped duration folders). Each segment folder uses the format `HHMMSS_LEN/` where `HHMMSS` is the start time and `LEN` is the duration in seconds. This folder name serves as the **segment key**, uniquely identifying the segment within a given day. ## The Three-Layer Architecture -Sunstone transforms raw recordings into actionable understanding through a three-layer pipeline: +solstone transforms raw recordings into actionable understanding through a three-layer pipeline: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” @@ -182,7 +182,7 @@ Optional fields: ### Facet Entities -Entities in Sunstone use a two-state system: **detected** (daily discoveries) and **attached** (promoted/persistent). This agent-driven architecture automatically identifies entities from journal content while allowing manual curation. +Entities in solstone use a two-state system: **detected** (daily discoveries) and **attached** (promoted/persistent). This agent-driven architecture automatically identifies entities from journal content while allowing manual curation. #### Entity Storage Structure diff --git a/docs/MUSE.md b/docs/MUSE.md index 93cf092a3..a4aeb5120 100644 --- a/docs/MUSE.md +++ b/docs/MUSE.md @@ -1,6 +1,6 @@ # Muse Module -AI agent system and MCP tooling for Sunstone. +AI agent system and MCP tooling for solstone. ## Commands diff --git a/docs/OBSERVE.md b/docs/OBSERVE.md index 4150e1187..42b9e159d 100644 --- a/docs/OBSERVE.md +++ b/docs/OBSERVE.md @@ -18,17 +18,41 @@ Multimodal capture and AI-powered analysis of desktop activity. ``` observer (platform-detected capture) ↓ - Raw media files (*.flac, *.webm) + Raw media files (*.flac, *.webm, tmux_*.jsonl) ↓ observe-sense (coordination) β”œβ”€β”€ observe-transcribe β†’ audio.jsonl └── observe-describe β†’ screen.jsonl ``` +## Observer State Machine + +The GNOME observer operates in three modes based on activity: + +``` + SCREENCAST + β†— β†˜ + (screen) (screen idle) + ↑ ↓ + IDLE ←----β†’ TMUX + (tmux active) +``` + +**Mode priority**: Screen activity always wins over tmux (user is physically present). + +| Mode | Trigger | Captures | +|------|---------|----------| +| SCREENCAST | Screen active (not idle/locked/power-save) | Video + Audio | +| TMUX | Screen idle but tmux has recent client activity | Terminal content + Audio | +| IDLE | Both screen and tmux inactive | Audio only (if threshold met) | + +Mode transitions trigger segment boundaries (like mute transitions do). + ## Key Components - **observer.py** - Unified entry point with platform detection - **gnome/observer.py**, **macos/observer.py** - Platform-specific capture using native APIs +- **tmux/capture.py** - Tmux capture library (integrated into GNOME observer for fallback capture) - **sense.py** - File watcher that dispatches transcription and description jobs - **transcribe.py** - Audio processing with Whisper/Rev.ai and pyannote diarization - **describe.py** - Vision analysis with Gemini, category-based prompts diff --git a/docs/THINK.md b/docs/THINK.md index e5e9d4a24..737485fb8 100644 --- a/docs/THINK.md +++ b/docs/THINK.md @@ -1,4 +1,4 @@ -# sunstone-think +# solstone-think Post-processing utilities for clustering and summarising captured data. The tools leverage the Gemini API to analyse transcriptions and screenshots. All commands work with a **journal** directory that holds daily folders in `YYYYMMDD` format. @@ -53,7 +53,7 @@ minimal service and timer that process yesterday's folder every morning at ```ini [Unit] -Description=Process sunstone journal +Description=Process solstone journal [Service] Type=oneshot diff --git a/docs/VENDOR.md b/docs/VENDOR.md index 71b7da426..b2cf8e241 100644 --- a/docs/VENDOR.md +++ b/docs/VENDOR.md @@ -1,6 +1,6 @@ # Third-Party Vendor Libraries -This directory contains third-party JavaScript libraries used across Sunstone apps. +This directory contains third-party JavaScript libraries used across solstone apps. ## Purpose diff --git a/muse/__init__.py b/muse/__init__.py index ca302a419..dcf76c255 100644 --- a/muse/__init__.py +++ b/muse/__init__.py @@ -1 +1 @@ -"""Muse - AI Agent orchestration and execution system for Sunstone.""" +"""Muse - AI Agent orchestration and execution system for solstone.""" diff --git a/muse/agents.py b/muse/agents.py index 05ee36229..6ffacc031 100644 --- a/muse/agents.py +++ b/muse/agents.py @@ -272,7 +272,7 @@ async def main_async() -> None: """NDJSON-based CLI for agent backends.""" parser = argparse.ArgumentParser( - description="Sunstone Agent CLI - Accepts NDJSON input via stdin" + description="solstone Agent CLI - Accepts NDJSON input via stdin" ) args = setup_cli(parser) diff --git a/muse/agents/daily_news.txt b/muse/agents/daily_news.txt index a2f4a4a0c..2ee896d30 100644 --- a/muse/agents/daily_news.txt +++ b/muse/agents/daily_news.txt @@ -1,4 +1,4 @@ -You are the Daily News Briefing Generator for Sunstone. Your mission is to create a crisp, scannable TL;DR-style briefing that highlights the previous day's most notable activities across all facets and delivers it to $pronouns_possessive inbox. +You are the Daily News Briefing Generator for solstone. Your mission is to create a crisp, scannable TL;DR-style briefing that highlights the previous day's most notable activities across all facets and delivers it to $pronouns_possessive inbox. ## Goals diff --git a/muse/agents/default.txt b/muse/agents/default.txt index fa0b91cfe..309e60bcc 100644 --- a/muse/agents/default.txt +++ b/muse/agents/default.txt @@ -1,4 +1,4 @@ -You are Sunstone, an advanced journal assistant specializing in helping $name explore, search, and understand personal journal entries. The journal contains daily transcripts from audio recordings and screenshot diffs that capture digital life, as well as pre-processed daily insights organized by topic and events extracted. +You are solstone, an advanced journal assistant specializing in helping $name explore, search, and understand personal journal entries. The journal contains daily transcripts from audio recordings and screenshot diffs that capture digital life, as well as pre-processed daily insights organized by topic and events extracted. ## Core Capabilities diff --git a/muse/agents/doctor.txt b/muse/agents/doctor.txt index 23765c92b..353b77406 100644 --- a/muse/agents/doctor.txt +++ b/muse/agents/doctor.txt @@ -1,4 +1,4 @@ -You are the Sunstone System Doctor, a diagnostic agent specialized in analyzing and troubleshooting the Sunstone journal system. You have read-only access to the entire journal directory and can run diagnostic shell commands to assess system health. +You are the solstone System Doctor, a diagnostic agent specialized in analyzing and troubleshooting the solstone journal system. You have read-only access to the entire journal directory and can run diagnostic shell commands to assess system health. The user may provide specific instructions, a description of an issue they're experiencing, or a particular area to focus on. If so, prioritize investigating that. If no specific issue is mentioned, perform a general health check. diff --git a/muse/agents/facet_describe.txt b/muse/agents/facet_describe.txt index 3fac569fa..319eaac89 100644 --- a/muse/agents/facet_describe.txt +++ b/muse/agents/facet_describe.txt @@ -1,4 +1,4 @@ -You are a facet description specialist for Sunstone, an AI-driven desktop journaling toolkit. Your role is to create compelling, informative descriptions for user facets based on their existing content and context. +You are a facet description specialist for solstone, an AI-driven desktop journaling toolkit. Your role is to create compelling, informative descriptions for user facets based on their existing content and context. ## Your Task diff --git a/muse/cortex.py b/muse/cortex.py index 6bd518787..a57a84270 100644 --- a/muse/cortex.py +++ b/muse/cortex.py @@ -1,4 +1,4 @@ -"""Callosum-based agent process manager for Sunstone. +"""Callosum-based agent process manager for solstone. Cortex listens for agent requests via the Callosum message bus and manages agent process lifecycle: @@ -96,9 +96,9 @@ class CortexService: from muse.mcp import mcp - host = os.getenv("SUNSTONE_MCP_HOST", "127.0.0.1") - port = int(os.getenv("SUNSTONE_MCP_PORT", "6270")) - path = os.getenv("SUNSTONE_MCP_PATH", "/mcp") or "/mcp" + host = os.getenv("SOLSTONE_MCP_HOST", "127.0.0.1") + port = int(os.getenv("SOLSTONE_MCP_PORT", "6270")) + path = os.getenv("SOLSTONE_MCP_PATH", "/mcp") or "/mcp" if not path.startswith("/"): path = f"/{path}" @@ -119,7 +119,7 @@ class CortexService: self.logger.info("Starting MCP server at %s", self.mcp_server_url) self.mcp_thread = threading.Thread( target=_run_server, - name="sunstone-mcp-server", + name="solstone-mcp-server", daemon=True, ) self.mcp_thread.start() @@ -1128,7 +1128,7 @@ def main() -> None: from think.utils import setup_cli - parser = argparse.ArgumentParser(description="Sunstone Cortex Agent Manager") + parser = argparse.ArgumentParser(description="solstone Cortex Agent Manager") args = setup_cli(parser) # Set up logging diff --git a/muse/mcp.py b/muse/mcp.py index 0a6df1a87..67a759467 100644 --- a/muse/mcp.py +++ b/muse/mcp.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""MCP server for Sunstone journal assistant. +"""MCP server for solstone journal assistant. This module creates the FastMCP server instance and registers all tools and resources from the muse/tools/ and muse/resources/ directories. @@ -13,7 +13,7 @@ from typing import Any, Callable, TypeVar from fastmcp import FastMCP # Create the MCP server instance -mcp = FastMCP("sunstone") +mcp = FastMCP("solstone") # Add annotation hints for all MCP tools HINTS = {"readOnlyHint": True, "openWorldHint": False} @@ -194,7 +194,7 @@ def main() -> None: from think.utils import setup_cli - parser = argparse.ArgumentParser(description="Sunstone MCP Tools Server") + parser = argparse.ArgumentParser(description="solstone MCP Tools Server") parser.add_argument( "--transport", choices=["stdio", "http"], diff --git a/muse/openai.py b/muse/openai.py index 0d719d38f..881e914d0 100644 --- a/muse/openai.py +++ b/muse/openai.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -OpenAI-backed agent implementation for the Sunstone `muse-agents` CLI. +OpenAI-backed agent implementation for the solstone `muse-agents` CLI. - Connects to a local MCP server over Streamable HTTP - Runs an agent with streaming to surface tool args/results and (when available) reasoning summaries @@ -292,7 +292,7 @@ async def run_agent( # Create agent with or without MCP servers mcp_servers_list = [mcp_server] if mcp_server else [] agent = Agent( - name="SunstoneCLI", + name="solstoneCLI", instructions=system_instruction, model=model, model_settings=model_settings, diff --git a/observe/gnome/screencast.py b/observe/gnome/screencast.py index 615c51ce7..57c700ee5 100644 --- a/observe/gnome/screencast.py +++ b/observe/gnome/screencast.py @@ -67,7 +67,7 @@ def _get_restore_token_path() -> Path: state_home = os.environ.get("XDG_STATE_HOME") if not state_home: state_home = os.path.join(os.path.expanduser("~"), ".local", "state") - return Path(state_home) / "sunstone" / "screencast_restore_token" + return Path(state_home) / "solstone" / "screencast_restore_token" def _load_restore_token() -> str | None: diff --git a/observe/revai.py b/observe/revai.py index 7c828c128..3151d15fa 100644 --- a/observe/revai.py +++ b/observe/revai.py @@ -177,14 +177,14 @@ def transcribe_file(media_path: Path, **kwargs) -> dict: return get_transcript_json(token, job_id) -def convert_revai_to_sunstone(revai_json: dict) -> list: - """Convert Rev.ai transcript format to Sunstone transcript format. +def convert_revai_to_solstone(revai_json: dict) -> list: + """Convert Rev.ai transcript format to solstone transcript format. Args: revai_json: Dict with Rev.ai transcript structure (monologues with elements) Returns: - List of transcript entries in Sunstone format + List of transcript entries in solstone format """ result = [] @@ -284,7 +284,7 @@ def convert_revai_to_sunstone(revai_json: dict) -> list: def main(): parser = argparse.ArgumentParser( - description="Rev AI transcription CLI (high-quality + diarization). If a .json file is provided, converts it to Sunstone format instead of transcribing." + description="Rev AI transcription CLI (high-quality + diarization). If a .json file is provided, converts it to solstone format instead of transcribing." ) parser.add_argument( "media", help="Path to audio/video file or Rev AI JSON file to convert" @@ -367,7 +367,7 @@ def main(): # Check if input is a JSON file - if so, convert instead of transcribe if media_path.suffix.lower() == ".json": logging.info( - "Detected JSON input - converting Rev AI format to Sunstone format" + "Detected JSON input - converting Rev AI format to solstone format" ) # Load the Rev AI JSON @@ -377,19 +377,19 @@ def main(): except json.JSONDecodeError as e: die(f"Invalid JSON file: {e}") - # Convert to Sunstone format - sunstone_transcript = convert_revai_to_sunstone(revai_data) + # Convert to solstone format + solstone_transcript = convert_revai_to_solstone(revai_data) # Output the result if args.output: out_path = Path(args.output).expanduser().resolve() out_path.write_text( - json.dumps(sunstone_transcript, indent=2, ensure_ascii=False), + json.dumps(solstone_transcript, indent=2, ensure_ascii=False), encoding="utf-8", ) logging.info("Wrote converted transcript to %s", out_path) else: - print(json.dumps(sunstone_transcript, indent=2, ensure_ascii=False)) + print(json.dumps(solstone_transcript, indent=2, ensure_ascii=False)) return diff --git a/pyproject.toml b/pyproject.toml index 897905df7..205b04954 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "sunstone" +name = "solstone" version = "0.1.0" description = "Navigate Intelligently - A collection of utilities for multimodal navigation and analysis" readme = "README.md" @@ -91,7 +91,7 @@ dev = [ ] [project.scripts] -sunstone = "think.sunstone:main" +solstone = "think.solstone:main" convey = "convey.cli:main" convey-restart = "convey.restart:main" convey-screenshot = "convey.screenshot:main" @@ -117,14 +117,13 @@ observe-macos = "observe.macos.observer:main" observe-transcribe = "observe.transcribe:main" observe-describe = "observe.describe:main" observe-sense = "observe.sense:main" -observe-tmux = "observe.tmux.observer:main" think-formatter = "think.formatters:main" [project.urls] -Homepage = "https://github.com/yourusername/sunstone" -Repository = "https://github.com/yourusername/sunstone" -Documentation = "https://github.com/yourusername/sunstone/blob/main/README.md" -"Bug Tracker" = "https://github.com/yourusername/sunstone/issues" +Homepage = "https://github.com/solpbc/solstone" +Repository = "https://github.com/solpbc/solstone" +Documentation = "https://github.com/solpbc/solstone/blob/main/README.md" +"Bug Tracker" = "https://github.com/solpbc/solstone/issues" [tool.setuptools.packages.find] include = ["apps*", "think*", "convey*", "observe*", "muse*"] diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py index 250bb7a5e..098d126e7 100644 --- a/tests/integration/__init__.py +++ b/tests/integration/__init__.py @@ -1,4 +1,4 @@ -"""Integration tests for Sunstone. +"""Integration tests for solstone. These tests are separate from unit tests and test the complete system integration. They may require external services, longer execution times, or specific setup. diff --git a/tests/test_importer.py b/tests/test_importer.py index d0126b46b..c323d6d9d 100644 --- a/tests/test_importer.py +++ b/tests/test_importer.py @@ -246,7 +246,7 @@ def test_audio_transcribe_sanitizes_entities(tmp_path, monkeypatch): return {} monkeypatch.setattr(mod, "transcribe_file", fake_transcribe_file) - monkeypatch.setattr(mod, "convert_revai_to_sunstone", lambda _: []) + monkeypatch.setattr(mod, "convert_revai_to_solstone", lambda _: []) mod.audio_transcribe( str(audio_file), @@ -285,7 +285,7 @@ def test_audio_transcribe_includes_import_metadata(tmp_path, monkeypatch): monkeypatch.setattr(mod, "transcribe_file", lambda *_, **__: {"ok": True}) monkeypatch.setattr( mod, - "convert_revai_to_sunstone", + "convert_revai_to_solstone", lambda *_: [ { "text": "Test entry", diff --git a/tests/test_journal_index.py b/tests/test_journal_index.py index c7a12f81f..dd2cd1571 100644 --- a/tests/test_journal_index.py +++ b/tests/test_journal_index.py @@ -37,8 +37,8 @@ class TestSanitizeFtsQuery: def test_complex_query_with_or_and_quotes(self): """Complex query with OR and quoted phrases.""" - result = sanitize_fts_query('sunstone OR pbc OR "public benefit"') - assert result == 'sunstone OR pbc OR "public benefit"' + result = sanitize_fts_query('solstone OR pbc OR "public benefit"') + assert result == 'solstone OR pbc OR "public benefit"' def test_dot_replaced_with_space(self): """Dots are replaced with spaces.""" diff --git a/tests/test_supervisor.py b/tests/test_supervisor.py index c585e8edd..6409a6349 100644 --- a/tests/test_supervisor.py +++ b/tests/test_supervisor.py @@ -98,7 +98,7 @@ async def test_send_notification(monkeypatch): await mod.send_notification("test message", alert_key=("test", "key")) assert len(called) == 1 assert called[0]["message"] == "test message" - assert called[0]["title"] == "Sunstone Supervisor" + assert called[0]["title"] == "solstone Supervisor" assert ("test", "key") in mod._notification_ids assert mod._notification_ids[("test", "key")] == "test-notification-id" diff --git a/tests/test_think_utils.py b/tests/test_think_utils.py index 5931849a4..b7244d285 100644 --- a/tests/test_think_utils.py +++ b/tests/test_think_utils.py @@ -184,7 +184,7 @@ def test_load_entity_names_spoken_mode(monkeypatch): ("Company", "Acme Corporation (ACME)", "Tech company"), ("Company", "Widget Inc", "Manufacturing company"), ("Company", "Google", "Search engine"), - ("Project", "Sunstone Project (SUN)", "AI journaling"), + ("Project", "solstone Project (SUN)", "AI journaling"), ("Project", "Project X", "Secret project"), ("Tool", "Hammer", "For hitting things"), ("Tool", "Docker", "Container runtime"), @@ -217,8 +217,8 @@ def test_load_entity_names_spoken_mode(monkeypatch): # Company: "Google" (single word) -> ["Google"] assert "Google" in result - # Project: "Sunstone Project (SUN)" -> ["Sunstone", "SUN"] (uniform processing) - assert "Sunstone" in result # First word + # Project: "solstone Project (SUN)" -> ["solstone", "SUN"] (uniform processing) + assert "solstone" in result # First word assert "SUN" in result # From parens # Project: "Project X" (no parens) -> ["Project"] (first word only) diff --git a/think/__init__.py b/think/__init__.py index e27b3861b..ce70d1e94 100644 --- a/think/__init__.py +++ b/think/__init__.py @@ -1,13 +1,13 @@ from .detect_created import detect_created from .detect_transcript import detect_transcript_json, detect_transcript_segment from .planner import generate_plan -from .sunstone import main as sunstone_main +from .solstone import main as solstone_main # Cluster functions not re-exported here to avoid circular imports # Import directly from think.cluster where needed __all__ = [ - "sunstone_main", + "solstone_main", "detect_created", "detect_transcript_segment", "detect_transcript_json", diff --git a/think/callosum.py b/think/callosum.py index d1d95673f..b3be83164 100644 --- a/think/callosum.py +++ b/think/callosum.py @@ -1,6 +1,6 @@ """Callosum: WebSocket-like broadcast message bus over Unix domain sockets. -Provides real-time event distribution across Sunstone services using a simple +Provides real-time event distribution across solstone services using a simple broadcast protocol. All messages require 'tract' and 'event' fields. """ diff --git a/think/importer.py b/think/importer.py index 301f07dec..c40f0e407 100644 --- a/think/importer.py +++ b/think/importer.py @@ -13,7 +13,7 @@ from datetime import timedelta from pathlib import Path from observe.hear import load_transcript -from observe.revai import convert_revai_to_sunstone, transcribe_file +from observe.revai import convert_revai_to_solstone, transcribe_file from think.callosum import CallosumConnection from think.detect_created import detect_created from think.detect_transcript import detect_transcript_json, detect_transcript_segment @@ -413,10 +413,10 @@ def audio_transcribe( logger.error(f"Failed to transcribe audio: {e}") raise - # Convert to Sunstone format - sunstone_transcript = convert_revai_to_sunstone(revai_json) + # Convert to solstone format + solstone_transcript = convert_revai_to_solstone(revai_json) - if not sunstone_transcript: + if not solstone_transcript: logger.warning("No transcript entries found") return created_files, revai_json @@ -425,7 +425,7 @@ def audio_transcribe( current_chunk = [] chunk_start_time = None - for entry in sunstone_transcript: + for entry in solstone_transcript: # Parse the timestamp from the entry start_str = entry.get("start", "00:00:00") h, m, s = map(int, start_str.split(":")) diff --git a/think/journal_stats.py b/think/journal_stats.py index eda634ad5..d48415b50 100644 --- a/think/journal_stats.py +++ b/think/journal_stats.py @@ -478,7 +478,7 @@ class JournalStats: def main() -> None: parser = argparse.ArgumentParser( - description="Scan a sunstone journal and generate statistics" + description="Scan a solstone journal and generate statistics" ) parser.add_argument( "--no-cache", diff --git a/think/manage.py b/think/manage.py index 0840090e3..3392639e8 100644 --- a/think/manage.py +++ b/think/manage.py @@ -1,4 +1,4 @@ -"""Interactive service manager for Sunstone supervisor. +"""Interactive service manager for solstone supervisor. Connects to the Callosum message bus to display real-time service status and provides keyboard controls for restarting services. @@ -25,12 +25,12 @@ def _get_notifier() -> DesktopNotifier: """Get or create the global desktop notifier instance.""" global _notifier if _notifier is None: - _notifier = DesktopNotifier(app_name="Sunstone Manager") + _notifier = DesktopNotifier(app_name="solstone Manager") return _notifier class ServiceManager: - """Interactive TUI for managing Sunstone services.""" + """Interactive TUI for managing solstone services.""" def __init__(self): self.services = [] # From supervisor/status events @@ -106,7 +106,7 @@ class ServiceManager: self.active_notifications.pop(service, None) notif_id = await notifier.send( - title="Sunstone Manager", + title="solstone Manager", message=message, urgency=Urgency.Critical, on_dismissed=on_dismissed, @@ -511,7 +511,7 @@ class ServiceManager: output.append(t.home + t.clear) # Title - title = "Sunstone Service Manager" + title = "solstone Service Manager" output.append(t.bold + t.cyan + title.center(t.width) + t.normal) output.append("") @@ -673,7 +673,7 @@ class ServiceManager: def main() -> None: """CLI entry point for service manager.""" parser = argparse.ArgumentParser( - description="Interactive service manager for Sunstone supervisor" + description="Interactive service manager for solstone supervisor" ) setup_cli(parser) diff --git a/think/planner.txt b/think/planner.txt index fce386209..cc583d461 100644 --- a/think/planner.txt +++ b/think/planner.txt @@ -1,4 +1,4 @@ -You are a strategic research planner for the Sunstone journal assistant, specialized in creating comprehensive plans to research and analyze personal journal data to answer user requests. +You are a strategic research planner for the solstone journal assistant, specialized in creating comprehensive plans to research and analyze personal journal data to answer user requests. ## Core Role and Limitations diff --git a/think/sunstone.py b/think/solstone.py similarity index 86% rename from think/sunstone.py rename to think/solstone.py index c713b92a0..4565e6e04 100644 --- a/think/sunstone.py +++ b/think/solstone.py @@ -13,13 +13,13 @@ from .utils import setup_cli def get_parser_help(module_name: str, func_name: str = "main") -> Tuple[str, str]: """Return description and usage for a command without triggering side effects.""" # Skip self to prevent infinite recursion - if module_name == "think.sunstone": - return "Print available sunstone commands with descriptions.", "" + if module_name == "think.solstone": + return "Print available solstone commands with descriptions.", "" logging.info(f"Getting parser help for module: {module_name}") pytest_env: Optional[str] = os.environ.get("PYTEST_CURRENT_TEST") - os.environ["PYTEST_CURRENT_TEST"] = "sunstone-discover" + os.environ["PYTEST_CURRENT_TEST"] = "solstone-discover" try: logging.debug(f"Importing module: {module_name}") module = importlib.import_module(module_name) @@ -76,7 +76,7 @@ def get_parser_help(module_name: str, func_name: str = "main") -> Tuple[str, str def discover_commands() -> List[Tuple[str, str, str]]: - """Return available sunstone commands discovered via entry points.""" + """Return available solstone commands discovered via entry points.""" logging.info("Starting command discovery") commands = [] @@ -90,16 +90,16 @@ def discover_commands() -> List[Tuple[str, str, str]]: logging.info(f"Found {len(scripts)} console scripts") - sunstone_eps = [ + solstone_eps = [ ep for ep in scripts - if ep.value.startswith(("hear.", "see.", "think.", "convey.")) + if ep.value.startswith(("think.", "convey.", "observe.", "muse.")) ] - logging.info(f"Found {len(sunstone_eps)} sunstone entry points") + logging.info(f"Found {len(solstone_eps)} solstone entry points") - sunstone_eps.sort(key=lambda ep: ep.name) + solstone_eps.sort(key=lambda ep: ep.name) - for ep in sunstone_eps: + for ep in solstone_eps: logging.debug(f"Processing entry point: {ep.name} -> {ep.value}") module_path, func_name = ep.value.split(":") description, usage = get_parser_help(module_path, func_name) @@ -111,14 +111,14 @@ def discover_commands() -> List[Tuple[str, str, str]]: def main() -> None: - """Print available sunstone commands with descriptions.""" + """Print available solstone commands with descriptions.""" parser = argparse.ArgumentParser( - description="Print available sunstone commands with descriptions." + description="Print available solstone commands with descriptions." ) setup_cli(parser) - logging.info("Starting sunstone command discovery") + logging.info("Starting solstone command discovery") journal_path = os.environ.get("JOURNAL_PATH", "not set") print(f"JOURNAL_PATH={journal_path}\n") diff --git a/think/supervisor.py b/think/supervisor.py index 9de992638..c0e5f17ce 100644 --- a/think/supervisor.py +++ b/think/supervisor.py @@ -251,7 +251,7 @@ def _get_notifier() -> DesktopNotifier: """Get or create the global desktop notifier instance.""" global _notifier if _notifier is None: - _notifier = DesktopNotifier(app_name="Sunstone Supervisor") + _notifier = DesktopNotifier(app_name="solstone Supervisor") return _notifier @@ -265,7 +265,7 @@ async def send_notification(message: str, alert_key: tuple | None = None) -> Non try: notifier = _get_notifier() notification_id = await notifier.send( - title="Sunstone Supervisor", + title="solstone Supervisor", message=message, urgency=Urgency.Critical, ) diff --git a/think/utils.py b/think/utils.py index e463a6b9a..1291781ad 100644 --- a/think/utils.py +++ b/think/utils.py @@ -725,7 +725,7 @@ def get_agent(persona: str = "default", facet: str | None = None) -> dict: def create_mcp_client(http_uri: str) -> Any: - """Return a FastMCP HTTP client for Sunstone tools.""" + """Return a FastMCP HTTP client for solstone tools.""" http_uri = http_uri.strip() if not http_uri: