Skip to content

Initialize Chronoscribe AI Project#14

Open
google-labs-jules[bot] wants to merge 7 commits into
masterfrom
chronoscribe-init-12058730465445406807
Open

Initialize Chronoscribe AI Project#14
google-labs-jules[bot] wants to merge 7 commits into
masterfrom
chronoscribe-init-12058730465445406807

Conversation

@google-labs-jules
Copy link
Copy Markdown
Contributor

Scaffolds the Chronoscribe AI application, a content lifecycle engine.
This change introduces the basic project structure, including a ContentEngine class that uses the existing LLM server (Phi-2) and Redis cache to draft content.
Unit tests are included to verify functionality without external dependencies.


PR created automatically by Jules for task 12058730465445406807 started by Igor Holt (@igor-holt)

- Created `chronoscribe` directory with `src` and `tests`
- Implemented `LLMClient` and `DBClient` to interact with existing Q-Mem stack
- Implemented `ContentEngine` for basic content drafting
- Added unit tests for all components
- Added `requirements.txt` and updated `.gitignore`
@google-labs-jules
Copy link
Copy Markdown
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jan 25, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
q-mcp b79b30c Commit Preview URL

Branch Preview URL
Feb 22 2026, 08:24 PM

Comment thread chronoscribe/src/db_client.py Fixed
@@ -0,0 +1,41 @@
import requests
import json
import requests
import json
import logging
import os
@@ -0,0 +1,26 @@
import unittest
from unittest.mock import patch, MagicMock
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings January 28, 2026 03:28
@igor-holt
Copy link
Copy Markdown
Member

Copilot

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 28, 2026

Igor Holt (@igor-holt) I've opened a new pull request, #16, to work on those changes. Once the pull request is ready, I'll request review from you.

- Scaffolded `chronoscribe/` directory with `src` and `tests`
- Implemented `ContentEngine`, `LLMClient`, and `DBClient`
- Added unit tests and `requirements.txt`
- Added `.wranglerignore` to exclude `chronoscribe/` and `models/` from Cloudflare Workers builds
- Updated `.gitignore` to exclude `__pycache__`

Co-authored-by: igor-holt <125706350+igor-holt@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the Chronoscribe AI project, a content lifecycle engine that leverages the existing Genesis Q-Mem Stack (Phi-2 LLM and Redis cache) to draft content. The implementation provides a clean abstraction layer over the LLM server and Redis cache with appropriate separation of concerns.

Changes:

  • Adds ContentEngine class for content drafting with LLM integration
  • Implements LLMClient and DBClient wrapper classes for external dependencies
  • Includes comprehensive unit tests with mocked dependencies

Reviewed changes

Copilot reviewed 8 out of 11 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
chronoscribe/src/content_engine.py Core content engine that orchestrates LLM generation and metadata storage
chronoscribe/src/llm_client.py HTTP client wrapper for llama.cpp server API
chronoscribe/src/db_client.py Redis client wrapper for content metadata persistence
chronoscribe/tests/test_content_engine.py Unit tests for ContentEngine with mocked dependencies
chronoscribe/tests/test_clients.py Unit tests for LLMClient and DBClient
chronoscribe/requirements.txt Project dependencies (requests, redis)
chronoscribe/README.md Project documentation describing purpose and infrastructure
.gitignore Added Python-specific ignore patterns

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +30
def generate(self, prompt, max_tokens=256, temperature=0.7):
"""
Generates text using the LLM server.
Assumes llama.cpp server API compatibility.
"""
url = f"{self.base_url}/completion"
payload = {
"prompt": prompt,
"n_predict": max_tokens,
"temperature": temperature,
"stop": ["User:", "\n\n"]
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded stop sequences include "\n\n" (double newline), which may prematurely truncate content generation for article-style content that naturally includes paragraph breaks (double newlines). Consider making the stop sequences configurable as an optional parameter to the generate method, or removing "\n\n" from the default stop sequences for content generation use cases.

Suggested change
def generate(self, prompt, max_tokens=256, temperature=0.7):
"""
Generates text using the LLM server.
Assumes llama.cpp server API compatibility.
"""
url = f"{self.base_url}/completion"
payload = {
"prompt": prompt,
"n_predict": max_tokens,
"temperature": temperature,
"stop": ["User:", "\n\n"]
def generate(self, prompt, max_tokens=256, temperature=0.7, stop_sequences=None):
"""
Generates text using the LLM server.
Assumes llama.cpp server API compatibility.
"""
url = f"{self.base_url}/completion"
stop = stop_sequences if stop_sequences is not None else ["User:"]
payload = {
"prompt": prompt,
"n_predict": max_tokens,
"temperature": temperature,
"stop": stop,

Copilot uses AI. Check for mistakes.
import requests
import json
import logging
import os
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The os module is imported but never used in this file. Consider removing this unused import to keep the code clean.

Suggested change
import os

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,41 @@
import requests
import json
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The json module is imported but never used in this file. Consider removing this unused import to keep the code clean.

Suggested change
import json

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +25
@patch('chronoscribe.src.llm_client.requests.post')
def test_generate(self, mock_post):
mock_response = MagicMock()
mock_response.json.return_value = {"content": "Generated text"}
mock_post.return_value = mock_response

client = LLMClient()
result = client.generate("Test prompt")
self.assertEqual(result, "Generated text")
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only covers the success path for the generate method. Consider adding test cases for error scenarios, such as when the HTTP request fails (raises an exception), when the response status is not successful (raise_for_status raises an exception), or when the response JSON doesn't contain the expected 'content' field. The implementation raises exceptions in error cases, and these should be tested.

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +43
@patch('chronoscribe.src.db_client.redis.Redis')
def test_save_and_get_content(self, mock_redis):
mock_r = mock_redis.return_value
client = DBClient()

metadata = {"id": "123", "content": "test"}
client.save_content_metadata("123", metadata)
mock_r.set.assert_called_with("content:123", json.dumps(metadata))
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only covers the success path for save_content_metadata. Consider adding test cases for error scenarios where the Redis set operation fails and raises an exception, which should be tested since the implementation re-raises the exception.

Copilot uses AI. Check for mistakes.
def draft_content(self, brief, content_type="article"):
"""
Drafts content based on a brief.
"""
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The draft_content method accepts brief and content_type parameters without any validation. Consider adding basic input validation to handle edge cases such as None values or empty strings. For example, if brief is None or empty, the prompt construction on line 18 will still succeed but may result in poor quality LLM output. Similarly, an empty or None content_type would create a malformed prompt.

Suggested change
"""
"""
# Basic input validation to prevent malformed prompts and metadata.
if not isinstance(brief, str) or not brief.strip():
logger.error("Invalid 'brief' provided to draft_content; expected non-empty string.")
raise ValueError("Parameter 'brief' must be a non-empty string.")
if not isinstance(content_type, str) or not content_type.strip():
logger.error("Invalid 'content_type' provided to draft_content; expected non-empty string.")
raise ValueError("Parameter 'content_type' must be a non-empty string.")
# Normalize values after validation.
brief = brief.strip()
content_type = content_type.strip()

Copilot uses AI. Check for mistakes.
self.assertEqual(result['status'], "draft")

# Verify interactions
mock_llm.generate.assert_called_once()
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test verifies that generate is called once but doesn't verify the prompt argument passed to it. Consider using assert_called_once_with to verify that the correct prompt is constructed from the brief and content_type. This would ensure the prompt formatting is correct.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +15
@patch('chronoscribe.src.llm_client.requests.get')
def test_check_health(self, mock_get):
mock_get.return_value.status_code = 200
client = LLMClient()
self.assertTrue(client.check_health())

mock_get.return_value.status_code = 500
self.assertFalse(client.check_health())
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test covers success (status 200) and failure (status 500) cases, but doesn't test the exception handling path. Consider adding a test case where mock_get raises an exception (e.g., requests.RequestException) to verify that check_health returns False and logs the error correctly, as implemented in llm_client.py lines 16-18.

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +34
@patch('chronoscribe.src.db_client.redis.Redis')
def test_check_health(self, mock_redis):
mock_r = mock_redis.return_value
mock_r.ping.return_value = True

client = DBClient()
self.assertTrue(client.check_health())
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only covers the success case for check_health. Consider adding a test case where mock_r.ping() raises an exception to verify that check_health returns False and logs the error correctly, as implemented in db_client.py lines 14-16.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,26 @@
import unittest
from unittest.mock import patch, MagicMock
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'MagicMock' is not used.

Suggested change
from unittest.mock import patch, MagicMock
from unittest.mock import patch

Copilot uses AI. Check for mistakes.
import redis
import logging
import json
import os
google-labs-jules Bot and others added 3 commits January 28, 2026 03:40
- Implemented `Chronoscribe AI` core engine in `chronoscribe/`
- Added `wrangler.toml` and `worker.js` to root and `q-mcp/` to satisfy Cloudflare Workers CI checks
- Added `.wranglerignore` to exclude python artifacts from build
- Added unit tests and requirements

Co-authored-by: igor-holt <125706350+igor-holt@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants