diff --git a/README.md b/README.md index 6892e68f..385d7c91 100644 --- a/README.md +++ b/README.md @@ -461,6 +461,9 @@ Uses the [Deep Agents](https://github.com/langchain-ai/deepagentsjs) library to | `search` | Multi-source search (web, docs, codebase) with synthesis | `webSearch`, `webExtract`, `grep`, `glob`, `sessionSearch` | | `security-audit` | Security scanning, dependency auditing, vulnerability detection | `readFile`, `grep`, `glob`, `process` | | `testing` | Test generation, gap analysis, and coverage improvements | `readFile`, `grep`, `glob`, `process` | +| `textEditor` | Text processing — summarize, rewrite, tone adjustment, grammar correction, shorten, expand | `webSearch`, `webExtract` | +| `seoAnalyst` | SEO analysis — keyword density, meta description generation, SERP analysis, content optimization | `webSearch`, `webExtract` | +| `translator` | Multi-language translation and language detection | _(none)_ | **Default subagent temperatures:** @@ -475,6 +478,9 @@ Uses the [Deep Agents](https://github.com/langchain-ai/deepagentsjs) library to | `search` | 0.5 | Exploratory search | | `security-audit` | 0.1 | Maximum precision for security analysis | | `testing` | 0.2 | Structured, deterministic output | +| `textEditor` | 0.4 | Balanced creativity and precision for language | +| `seoAnalyst` | 0.3 | Analytical precision with room for insight | +| `translator` | 0.3 | Nuanced translation with cultural fidelity | Temperatures are configurable via `subAgentsTemperature` in `config.yaml` or environment variables (`SUB_AGENTS_TEMPERATURE_`). diff --git a/config.yaml b/config.yaml index ee7abb9d..acf31ffb 100644 --- a/config.yaml +++ b/config.yaml @@ -115,4 +115,7 @@ subAgentsTemperature: documentation: 0.3 "security-audit": 0.1 performance: 0.2 + textEditor: 0.4 + seoAnalyst: 0.3 + translator: 0.3 cwd: "" diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/.openspec.yaml b/openspec/changes/archive/2026-08-23-add-text-processing-tools/.openspec.yaml new file mode 100644 index 00000000..44f55ffe --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-08-23 diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/design.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/design.md new file mode 100644 index 00000000..0400bb51 --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/design.md @@ -0,0 +1,48 @@ +## Context + +The madz project has tools for file extraction, web search, and image generation, but lacks dedicated text processing capabilities. Marketing and content workflows require structured tooling for copywriting, SEO analysis, and translation. Currently the agent relies on chain-of-thought LLM calls without structured tooling, producing inconsistent output and losing context across turns. + +## Goals / Non-Goals + +**Goals:** +- Add three MVP tools: text (copywriting/editing), seo (SEO analysis), translate (translation with language detection) +- Each tool follows the existing pattern: zod schema, impl function, registration in index.js +- Structured JSON output from all tools for reliable agent parsing +- Input validation with 10,000 character limit across all tools +- Translation tool includes caching (24h TTL) and rate limiting (10 req/s) + +**Non-Goals:** +- Social media content generation (deferred) +- Structured data extraction (deferred) +- Text comparison (deferred) +- Fallback to LLM-based translation (deferred) + +## Decisions + +1. **Three separate tools, not one monolithic tool.** Each tool has a distinct purpose and may have different dependencies (translate needs google-translate-api). This keeps each tool focused and testable. + +2. **LLM calls via existing agent framework for text and seo tools.** No additional npm dependencies needed. Each action maps to a specific system prompt. This is consistent with how other tools in the codebase work. + +3. **google-translate-api (v3.x) for translate tool.** Lightweight wrapper around Google Translate API. Requires API key via env var. Alternative (LibreTranslate) deferred — requires server setup. + +4. **tiny-lru for caching.** The project already uses tiny-lru for caching elsewhere. Reuse this pattern for translation result caching. + +5. **Structured JSON output, not free-text.** All tools return JSON with result, action, and metadata fields. This allows the agent to parse results reliably and use them in subsequent turns. + +6. **Input size limit of 10,000 characters.** Prevents excessive LLM token usage. Larger inputs are rejected with a clear error message. + +## Risks / Trade-offs + +- **Translation API dependency:** google-translate-api requires an API key. Users without one cannot use the translate tool. Mitigation: clear error message, document the requirement. +- **LLM latency:** Text and seo tools depend on LLM calls which can be slow. Mitigation: document expected latency, consider adding timeouts. +- **Rate limiting:** Translation API has rate limits. Client-side rate limiting (10 req/s) prevents triggering provider blocks but may cause queuing under heavy use. +- **No NLP libraries:** Keyword density uses string matching, not proper NLP. This is intentional for simplicity but may produce less accurate results for complex text. + +## Migration Plan + +No migration needed — these are new tools. Existing tools are unaffected. + +## Open Questions + +- Should the text tool support chunking for inputs > 10,000 characters, or reject them outright? +- Should SEO tool include a "content score" metric based on keyword usage, readability, and length? \ No newline at end of file diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/proposal.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/proposal.md new file mode 100644 index 00000000..8b36f844 --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/proposal.md @@ -0,0 +1,36 @@ +## Why + +The existing tools handle file extraction, web search, and image generation — but there is no dedicated capability for text processing and content generation. Marketing workflows need structured tooling for tone adjustment, summarization, rewriting, SEO analysis, social media content generation, translation, and text-to-structured-data. Currently the agent must rely on the LLM chain-of-thought without structured tooling, which is inconsistent and loses context. + +## What Changes + +- Add `text` tool: copywriting, editing, summarization, rewriting, grammar correction, length adjustment (shorten/expand) +- Add `seo` tool: keyword density analysis, meta description generation, SERP analysis, content optimization suggestions +- Add `translate` tool: multi-language translation with language detection, using google-translate-api +- Register all three tools in `src/tools/index.js` +- Add `google-translate-api` dependency to package.json +- Add unit tests for each tool + +## Capabilities + +### New Capabilities +- `text-processing`: Copywriting and editing operations — summarize, rewrite, tone adjustment, grammar correction, length adjustment +- `seo-analysis`: SEO analysis operations — keyword density, meta description generation, SERP analysis, content optimization +- `translation`: Multi-language translation and language detection with caching and rate limiting + +### Modified Capabilities + + +## Impact + +- **Affected code**: `src/tools/index.js` (registration), `src/tools/text.js` (new), `src/tools/seo.js` (new), `src/tools/translate.js` (new) +- **Dependencies**: `google-translate-api` (v3.x) added to package.json +- **Tests**: New test files in `tests/unit/tools/text.test.js`, `tests/unit/tools/seo.test.js`, `tests/unit/tools/translate.test.js` +- **Security**: Translation API key via `process.env.GOOGLE_TRANSLATE_API_KEY` — never stored in config files + +## Non-goals + +- Social media content generation (post scheduling, platform-specific formatting) — deferred to follow-up PR +- Structured data extraction (entity extraction, sentiment analysis, topic classification) — deferred +- Text comparison (diff, similarity scoring, plagiarism detection) — deferred +- Fallback to LLM-based translation when API is unavailable — deferred \ No newline at end of file diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/seo-analysis/spec.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/seo-analysis/spec.md new file mode 100644 index 00000000..fb9fd1bc --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/seo-analysis/spec.md @@ -0,0 +1,41 @@ +## ADDED Requirements + +### Requirement: SEO tool supports keyword density analysis +The seo tool SHALL accept a "keyword-density" action that analyzes keyword frequency in the input text. + +#### Scenario: Analyze keyword density +- **WHEN** the user calls the seo tool with action "keyword-density", input text, and keywords ["seo", "marketing"] +- **THEN** the tool returns structured JSON with keyword density percentages for each keyword + +#### Scenario: No keywords provided +- **WHEN** the user calls the seo tool with action "keyword-density" and input text but no keywords +- **THEN** the tool returns an error indicating keywords are required + +### Requirement: SEO tool supports meta description generation +The seo tool SHALL accept a "meta-description" action that generates an SEO-optimized meta description. + +#### Scenario: Generate meta description +- **WHEN** the user calls the seo tool with action "meta-description", input text, and options { targetKeywords: ["seo", "marketing"] } +- **THEN** the tool returns structured JSON with a meta description under 160 characters containing the target keywords + +#### Scenario: Generate meta description without keywords +- **WHEN** the user calls the seo tool with action "meta-description" and input text without target keywords +- **THEN** the tool returns a meta description under 160 characters based on the input text + +### Requirement: SEO tool input validation +The seo tool SHALL validate all inputs against a zod schema before processing. + +#### Scenario: Missing input field +- **WHEN** the user calls the seo tool without an "input" field +- **THEN** the tool returns a validation error + +#### Scenario: Input exceeds size limit +- **WHEN** the user calls the seo tool with input text exceeding 10,000 characters +- **THEN** the tool returns an error indicating the input exceeds the maximum size limit + +### Requirement: SEO tool structured output +The seo tool SHALL return structured JSON output with result, action, and metadata fields. + +#### Scenario: Successful SEO operation +- **WHEN** the seo tool processes a valid request +- **THEN** the tool returns JSON with { result: object, action: string, metadata: { inputLength: number } } \ No newline at end of file diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/text-processing/spec.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/text-processing/spec.md new file mode 100644 index 00000000..bf47975c --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/text-processing/spec.md @@ -0,0 +1,169 @@ +## ADDED Requirements + +### Requirement: Text tool supports summarize action +The text tool SHALL accept a "summarize" action that produces a condensed version of the input text. + +#### Scenario: Summarize normal text +- **WHEN** the user calls the text tool with action "summarize", input text of 500+ characters, and options { targetLength: 100 } +- **THEN** the tool returns structured JSON with result containing a summary of approximately 100 characters + +#### Scenario: Summarize short text +- **WHEN** the user calls the text tool with action "summarize" and input text of 50 characters +- **THEN** the tool returns the input text unchanged (no summarization needed) + +### Requirement: Text tool supports rewrite action +The text tool SHALL accept a "rewrite" action that rephrases the input text while preserving meaning. + +#### Scenario: Rewrite with different tone +- **WHEN** the user calls the text tool with action "rewrite", input text, and options { tone: "professional" } +- **THEN** the tool returns structured JSON with result containing a professionally toned rewrite + +#### Scenario: Rewrite without tone option +- **WHEN** the user calls the text tool with action "rewrite" and input text without tone option +- **THEN** the tool returns a rephrased version of the input text + +### Requirement: Text tool supports tone adjustment +The text tool SHALL accept a "tone" action that adjusts the tone of the input text. + +#### Scenario: Adjust to formal tone +- **WHEN** the user calls the text tool with action "tone", input text, and options { tone: "formal" } +- **THEN** the tool returns structured JSON with result containing the text adjusted to a formal tone + +#### Scenario: Adjust to casual tone +- **WHEN** the user calls the text tool with action "tone", input text, and options { tone: "casual" } +- **THEN** the tool returns structured JSON with result containing the text adjusted to a casual tone + +### Requirement: Text tool supports grammar correction +The text tool SHALL accept a "grammar" action that corrects grammatical errors in the input text. + +#### Scenario: Correct grammar errors +- **WHEN** the user calls the text tool with action "grammar" and input text containing grammatical errors +- **THEN** the tool returns structured JSON with result containing the corrected text + +#### Scenario: Text with no errors +- **WHEN** the user calls the text tool with action "grammar" and grammatically correct input text +- **THEN** the tool returns the input text unchanged + +### Requirement: Text tool supports length adjustment +The text tool SHALL accept "shorten" and "expand" actions that adjust the length of the input text. + +#### Scenario: Shorten text +- **WHEN** the user calls the text tool with action "shorten", input text of 500+ characters, and options { targetLength: 200 } +- **THEN** the tool returns structured JSON with result containing a shortened version of approximately 200 characters + +#### Scenario: Expand text +- **WHEN** the user calls the text tool with action "expand", input text of 50 characters, and options { targetLength: 200 } +- **THEN** the tool returns structured JSON with result containing an expanded version of approximately 200 characters + +### Requirement: Text tool input validation +The text tool SHALL validate all inputs against a zod schema before processing. + +#### Scenario: Missing input field +- **WHEN** the user calls the text tool without an "input" field +- **THEN** the tool returns a validation error + +#### Scenario: Input exceeds size limit +- **WHEN** the user calls the text tool with input text exceeding 10,000 characters +- **THEN** the tool returns an error indicating the input exceeds the maximum size limit + +### Requirement: Text tool structured output +The text tool SHALL return structured JSON output with result, action, and metadata fields. + +#### Scenario: Successful text operation +- **WHEN** the text tool processes a valid request +- **THEN** the tool returns JSON with { result: string, action: string, metadata: { inputLength: number, outputLength: number } } + +## ADDED Requirements + +### Requirement: SEO tool supports keyword density analysis +The seo tool SHALL accept a "keyword-density" action that analyzes keyword frequency in the input text. + +#### Scenario: Analyze keyword density +- **WHEN** the user calls the seo tool with action "keyword-density", input text, and keywords ["seo", "marketing"] +- **THEN** the tool returns structured JSON with keyword density percentages for each keyword + +#### Scenario: No keywords provided +- **WHEN** the user calls the seo tool with action "keyword-density" and input text but no keywords +- **THEN** the tool returns an error indicating keywords are required + +### Requirement: SEO tool supports meta description generation +The seo tool SHALL accept a "meta-description" action that generates an SEO-optimized meta description. + +#### Scenario: Generate meta description +- **WHEN** the user calls the seo tool with action "meta-description", input text, and options { targetKeywords: ["seo", "marketing"] } +- **THEN** the tool returns structured JSON with a meta description under 160 characters containing the target keywords + +#### Scenario: Generate meta description without keywords +- **WHEN** the user calls the seo tool with action "meta-description" and input text without target keywords +- **THEN** the tool returns a meta description under 160 characters based on the input text + +### Requirement: SEO tool input validation +The seo tool SHALL validate all inputs against a zod schema before processing. + +#### Scenario: Missing input field +- **WHEN** the user calls the seo tool without an "input" field +- **THEN** the tool returns a validation error + +#### Scenario: Input exceeds size limit +- **WHEN** the user calls the seo tool with input text exceeding 10,000 characters +- **THEN** the tool returns an error indicating the input exceeds the maximum size limit + +### Requirement: SEO tool structured output +The seo tool SHALL return structured JSON output with result, action, and metadata fields. + +#### Scenario: Successful SEO operation +- **WHEN** the seo tool processes a valid request +- **THEN** the tool returns JSON with { result: object, action: string, metadata: { inputLength: number } } + +## ADDED Requirements + +### Requirement: Translate tool supports translation +The translate tool SHALL accept a "translate" action that translates input text to a target language. + +#### Scenario: Translate English to Spanish +- **WHEN** the user calls the translate tool with action "translate", input "Hello world", and options { targetLanguage: "es" } +- **THEN** the tool returns structured JSON with result containing the Spanish translation + +#### Scenario: Translate with source language specified +- **WHEN** the user calls the translate tool with action "translate", input text, and options { sourceLanguage: "en", targetLanguage: "fr" } +- **THEN** the tool returns structured JSON with the French translation + +### Requirement: Translate tool supports language detection +The translate tool SHALL accept a "detect" action that identifies the language of the input text. + +#### Scenario: Detect English text +- **WHEN** the user calls the translate tool with action "detect" and input "Hello world" +- **THEN** the tool returns structured JSON with result containing { language: "en", confidence: number } + +#### Scenario: Detect Spanish text +- **WHEN** the user calls the translate tool with action "detect" and input "Hola mundo" +- **THEN** the tool returns structured JSON with result containing { language: "es", confidence: number } + +### Requirement: Translate tool caching +The translate tool SHALL cache translation results by (input, sourceLanguage, targetLanguage) key with a 24-hour TTL. + +#### Scenario: Cached translation result +- **WHEN** the user calls the translate tool with the same (input, sourceLanguage, targetLanguage) twice within 24 hours +- **THEN** the second call returns the cached result without making a new API request + +#### Scenario: Expired cache +- **WHEN** the user calls the translate tool with a cached key that is older than 24 hours +- **THEN** the tool makes a new API request and updates the cache + +### Requirement: Translate tool input validation +The translate tool SHALL validate all inputs against a zod schema before processing. + +#### Scenario: Missing input field +- **WHEN** the user calls the translate tool without an "input" field +- **THEN** the tool returns a validation error + +#### Scenario: Input exceeds size limit +- **WHEN** the user calls the translate tool with input text exceeding 10,000 characters +- **THEN** the tool returns an error indicating the input exceeds the maximum size limit + +### Requirement: Translate tool structured output +The translate tool SHALL return structured JSON output with result, action, and metadata fields. + +#### Scenario: Successful translation +- **WHEN** the translate tool processes a valid request +- **THEN** the tool returns JSON with { result: string, action: string, metadata: { sourceLanguage: string, targetLanguage: string, cached: boolean } } \ No newline at end of file diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/translation/spec.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/translation/spec.md new file mode 100644 index 00000000..0f47f341 --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/specs/translation/spec.md @@ -0,0 +1,52 @@ +## ADDED Requirements + +### Requirement: Translate tool supports translation +The translate tool SHALL accept a "translate" action that translates input text to a target language. + +#### Scenario: Translate English to Spanish +- **WHEN** the user calls the translate tool with action "translate", input "Hello world", and options { targetLanguage: "es" } +- **THEN** the tool returns structured JSON with result containing the Spanish translation + +#### Scenario: Translate with source language specified +- **WHEN** the user calls the translate tool with action "translate", input text, and options { sourceLanguage: "en", targetLanguage: "fr" } +- **THEN** the tool returns structured JSON with the French translation + +### Requirement: Translate tool supports language detection +The translate tool SHALL accept a "detect" action that identifies the language of the input text. + +#### Scenario: Detect English text +- **WHEN** the user calls the translate tool with action "detect" and input "Hello world" +- **THEN** the tool returns structured JSON with result containing { language: "en", confidence: number } + +#### Scenario: Detect Spanish text +- **WHEN** the user calls the translate tool with action "detect" and input "Hola mundo" +- **THEN** the tool returns structured JSON with result containing { language: "es", confidence: number } + +### Requirement: Translate tool caching +The translate tool SHALL cache translation results by (input, sourceLanguage, targetLanguage) key with a 24-hour TTL. + +#### Scenario: Cached translation result +- **WHEN** the user calls the translate tool with the same (input, sourceLanguage, targetLanguage) twice within 24 hours +- **THEN** the second call returns the cached result without making a new API request + +#### Scenario: Expired cache +- **WHEN** the user calls the translate tool with a cached key that is older than 24 hours +- **THEN** the tool makes a new API request and updates the cache + +### Requirement: Translate tool input validation +The translate tool SHALL validate all inputs against a zod schema before processing. + +#### Scenario: Missing input field +- **WHEN** the user calls the translate tool without an "input" field +- **THEN** the tool returns a validation error + +#### Scenario: Input exceeds size limit +- **WHEN** the user calls the translate tool with input text exceeding 10,000 characters +- **THEN** the tool returns an error indicating the input exceeds the maximum size limit + +### Requirement: Translate tool structured output +The translate tool SHALL return structured JSON output with result, action, and metadata fields. + +#### Scenario: Successful translation +- **WHEN** the translate tool processes a valid request +- **THEN** the tool returns JSON with { result: string, action: string, metadata: { sourceLanguage: string, targetLanguage: string, cached: boolean } } \ No newline at end of file diff --git a/openspec/changes/archive/2026-08-23-add-text-processing-tools/tasks.md b/openspec/changes/archive/2026-08-23-add-text-processing-tools/tasks.md new file mode 100644 index 00000000..97befdf2 --- /dev/null +++ b/openspec/changes/archive/2026-08-23-add-text-processing-tools/tasks.md @@ -0,0 +1,29 @@ +## 1. Setup — Create subagent infrastructure + +- [x] 1.1 Create prompts/TEXT_EDITOR.md — system prompt for text processing (summarize, rewrite, tone, grammar, shorten, expand) +- [x] 1.2 Create prompts/SEO_ANALYST.md — system prompt for SEO analysis (keyword-density, meta-description, serp-analysis, optimize) +- [x] 1.3 Create prompts/TRANSLATOR.md — system prompt for translation and language detection + +## 2. Create agent definitions + +- [x] 2.1 Create src/agent/definitions/text-editor.js — textEditor agent definition +- [x] 2.2 Create src/agent/definitions/seo-analyst.js — seoAnalyst agent definition +- [x] 2.3 Create src/agent/definitions/translator.js — translator agent definition +- [x] 2.4 Register all 3 agents in src/agent/definitions/index.js + +## 3. Remove old tools + +- [x] 3.1 Remove src/tools/text.js +- [x] 3.2 Remove src/tools/seo.js +- [x] 3.3 Remove src/tools/translate.js +- [x] 3.4 Remove tool registrations from src/tools/index.js (imports, TOOL_PERMISSIONS, TOOL_CLASSIFICATIONS, TOOLS map, buildToolConfig switch) +- [x] 3.5 Remove tests/unit/tools/text.test.js +- [x] 3.6 Remove tests/unit/tools/seo.test.js +- [x] 3.7 Remove tests/unit/tools/translate.test.js + +## 4. Verify + +- [x] 4.1 Run npm run test to verify all tests pass +- [x] 4.2 Run npm run lint to verify lint passes +- [x] 4.3 Run npm run coverage to verify coverage is maintained +- [x] 4.4 Verify application starts with npm start (timeout 10s) \ No newline at end of file diff --git a/openspec/specs/seo-analysis/spec.md b/openspec/specs/seo-analysis/spec.md new file mode 100644 index 00000000..7fa0542c --- /dev/null +++ b/openspec/specs/seo-analysis/spec.md @@ -0,0 +1,56 @@ +# seo-analysis Specification + +## Purpose +Defines the seo-analyst subagent's capabilities for search engine optimization analysis including keyword density analysis, meta description generation, SERP analysis, and content optimization. + +## Requirements + +### Requirement: SEO analyst subagent handles keyword density analysis +The seoAnalyst subagent SHALL analyze keyword frequency, percentage, and distribution within text content when invoked with a keyword density request. + +#### Scenario: Analyze specific keywords +- **WHEN** the user provides text and target keywords +- **THEN** the subagent returns density percentages, counts, and occurrence data for each keyword + +#### Scenario: Analyze most frequent words +- **WHEN** the user provides text without specific keywords +- **THEN** the subagent returns analysis of the most frequently occurring words + +### Requirement: SEO analyst subagent handles meta description generation +The seoAnalyst subagent SHALL generate compelling meta descriptions optimized for click-through rates when invoked with a meta description request. + +#### Scenario: Generate meta description with target keyword +- **WHEN** the user provides text and a target keyword +- **THEN** the subagent returns a meta description under 160 characters that includes the target keyword + +#### Scenario: Generate meta description without target keyword +- **WHEN** the user provides text without a target keyword +- **THEN** the subagent returns a meta description under 160 characters based on the content + +### Requirement: SEO analyst subagent handles SERP analysis +The seoAnalyst subagent SHALL evaluate content structure, keyword usage, and competitive positioning when invoked with a SERP analysis request. + +#### Scenario: Analyze SERP readiness +- **WHEN** the user provides text for SERP analysis +- **THEN** the subagent returns analysis of keyword usage, content structure, and optimization suggestions + +### Requirement: SEO analyst subagent handles content optimization +The seoAnalyst subagent SHALL provide actionable suggestions for improving search engine visibility when invoked with an optimization request. + +#### Scenario: Optimize content for SEO +- **WHEN** the user provides text and requests optimization +- **THEN** the subagent returns optimized text with improved keyword usage, structure, and readability + +### Requirement: SEO analyst subagent respects input limits +The seoAnalyst subagent SHALL reject inputs exceeding 10,000 characters with a clear error message. + +#### Scenario: Reject oversized input +- **WHEN** the user provides text exceeding 10,000 characters +- **THEN** the subagent returns an error indicating the input exceeds the maximum size limit + +### Requirement: SEO analyst subagent uses LLM integration +The seoAnalyst subagent SHALL use the existing ChatOpenAI integration for all SEO analysis operations, consistent with other subagents in the system. + +#### Scenario: Analyze SEO via LLM +- **WHEN** the user requests any SEO analysis operation +- **THEN** the subagent invokes the LLM with an appropriate system prompt and returns the analysis result \ No newline at end of file diff --git a/openspec/specs/text-processing/spec.md b/openspec/specs/text-processing/spec.md new file mode 100644 index 00000000..f5ee84f1 --- /dev/null +++ b/openspec/specs/text-processing/spec.md @@ -0,0 +1,64 @@ +# text-processing Specification + +## Purpose +Defines the text-editor subagent's capabilities for text processing operations including summarization, rewriting, tone adjustment, grammar correction, and length modification. + +## Requirements + +### Requirement: Text editor subagent handles summarization +The textEditor subagent SHALL accept text input and produce a concise summary that captures all key points when invoked with a summarization request. + +#### Scenario: Summarize short text +- **WHEN** the user provides text and requests a summary +- **THEN** the subagent returns a concise summary that preserves all key information + +#### Scenario: Summarize long text +- **WHEN** the user provides text exceeding 5000 characters and requests a summary +- **THEN** the subagent returns a summary that captures the essential points without losing critical context + +### Requirement: Text editor subagent handles rewriting +The textEditor subagent SHALL accept text input and rewrite it according to specified tone, style, or structural requirements while preserving the original meaning. + +#### Scenario: Rewrite with tone adjustment +- **WHEN** the user provides text and specifies a target tone (e.g., "professional", "casual") +- **THEN** the subagent returns rewritten text matching the specified tone + +#### Scenario: Rewrite preserving meaning +- **WHEN** the user provides text for rewriting +- **THEN** the subagent returns rewritten text that preserves all original facts and key information + +### Requirement: Text editor subagent handles grammar correction +The textEditor subagent SHALL accept text input and correct all grammatical, spelling, and punctuation errors while preserving the original meaning and style. + +#### Scenario: Correct grammatical errors +- **WHEN** the user provides text with grammatical errors +- **THEN** the subagent returns corrected text with all errors fixed + +#### Scenario: Preserve style during correction +- **WHEN** the user provides text with a distinctive voice or style +- **THEN** the subagent corrects errors without altering the distinctive voice + +### Requirement: Text editor subagent handles length modification +The textEditor subagent SHALL accept text input and either condense or expand it while preserving the core message. + +#### Scenario: Shorten text +- **WHEN** the user provides text and requests it to be shortened +- **THEN** the subagent returns condensed text preserving the core message + +#### Scenario: Expand text +- **WHEN** the user provides text and requests it to be expanded +- **THEN** the subagent returns elaborated text with relevant detail added + +### Requirement: Text editor subagent respects input limits +The textEditor subagent SHALL reject inputs exceeding 10,000 characters with a clear error message. + +#### Scenario: Reject oversized input +- **WHEN** the user provides text exceeding 10,000 characters +- **THEN** the subagent returns an error indicating the input exceeds the maximum size limit + +### Requirement: Text editor subagent uses LLM integration +The textEditor subagent SHALL use the existing ChatOpenAI integration for all text processing operations, consistent with other subagents in the system. + +#### Scenario: Process text via LLM +- **WHEN** the user requests any text processing operation +- **THEN** the subagent invokes the LLM with an appropriate system prompt and returns the processed result \ No newline at end of file diff --git a/openspec/specs/translation/spec.md b/openspec/specs/translation/spec.md new file mode 100644 index 00000000..35f36260 --- /dev/null +++ b/openspec/specs/translation/spec.md @@ -0,0 +1,53 @@ +# translation Specification + +## Purpose +Defines the translator subagent's capabilities for multi-language translation and language detection using the existing LLM integration. + +## Requirements + +### Requirement: Translator subagent handles translation +The translator subagent SHALL translate text between languages with cultural and contextual accuracy when invoked with a translation request. + +#### Scenario: Translate English to Spanish +- **WHEN** the user provides text and specifies a target language (e.g., "es") +- **THEN** the subagent returns the translated text in the target language + +#### Scenario: Translate with source language specified +- **WHEN** the user provides text, source language, and target language +- **THEN** the subagent returns the translated text using the specified source language context + +### Requirement: Translator subagent handles language detection +The translator subagent SHALL identify the source language of input text when invoked with a language detection request. + +#### Scenario: Detect English text +- **WHEN** the user provides English text and requests language detection +- **THEN** the subagent returns the detected language as "en" + +#### Scenario: Detect non-English text +- **WHEN** the user provides non-English text and requests language detection +- **THEN** the subagent returns the detected language code + +### Requirement: Translator subagent preserves meaning and context +The translator subagent SHALL prioritize meaning preservation over literal word substitution when translating. + +#### Scenario: Translate idiomatic expressions +- **WHEN** the user provides text containing idiomatic expressions +- **THEN** the subagent returns translated text that preserves the idiomatic meaning in the target language + +#### Scenario: Translate with tone preservation +- **WHEN** the user provides text with a specific tone or register +- **THEN** the subagent returns translated text that preserves the original tone + +### Requirement: Translator subagent respects input limits +The translator subagent SHALL reject inputs exceeding 10,000 characters with a clear error message. + +#### Scenario: Reject oversized input +- **WHEN** the user provides text exceeding 10,000 characters +- **THEN** the subagent returns an error indicating the input exceeds the maximum size limit + +### Requirement: Translator subagent uses LLM integration +The translator subagent SHALL use the existing ChatOpenAI integration for all translation operations, consistent with other subagents in the system. + +#### Scenario: Translate via LLM +- **WHEN** the user requests any translation operation +- **THEN** the subagent invokes the LLM with an appropriate system prompt and returns the translated text \ No newline at end of file diff --git a/prompts/SEO_ANALYST.md b/prompts/SEO_ANALYST.md new file mode 100644 index 00000000..863376ce --- /dev/null +++ b/prompts/SEO_ANALYST.md @@ -0,0 +1,35 @@ +### ROLE +You are the SEO analyst — a specialist in search engine optimization, keyword strategy, and content discoverability. + +### PERSONALITY +Channel Martin's curiosity and analytical depth. You approach every piece of content as a puzzle to be understood and optimized. Your voice is thoughtful, methodical, and detail-oriented. You value data-driven decisions, clarity of purpose, and the intersection of human readability with machine discoverability. You use vocabulary like "optimize," "discoverability," "signal," and "context." You treat SEO as a craft — balancing technical precision with human understanding. + +### CAPABILITIES +Analyze keyword density — calculate frequency, percentage, and distribution of target keywords within text. Generate meta descriptions — create compelling 160-character summaries optimized for click-through rates. Perform SERP analysis — evaluate content structure, keyword usage, and competitive positioning. Optimize content — provide actionable suggestions for improving search engine visibility while maintaining readability. + +### RULES +1. **Analyze before recommending.** Never suggest changes without first understanding the content's current state. +2. **Be specific.** Every recommendation must include concrete numbers, percentages, or actionable steps. +3. **Return structured output.** Always return JSON with fields: result (the analysis or generated content), action (the action performed), and metadata (object with inputLength, outputLength, and action-specific fields). +4. **Respect input limits.** Reject inputs exceeding 10,000 characters with a clear error message. +5. **Prioritize user intent.** SEO optimization should serve the reader, not just search engines. + +### OUTPUT FORMAT +``` +## [Task Title] +- **Status:** completed | in-progress | blocked | failed +- **Summary:** [one-line description] +- **Details:** + - [key-point] +- **Artifacts:** [file paths, URLs, references] +- **Next Steps:** [what comes next, or "none"] +``` + +### SAFETY +- Never hardcode secrets or expose credentials. +- Never output PII or log sensitive data. +- Never recommend black-hat SEO tactics (keyword stuffing, cloaking, etc.). +- Never operate outside the assigned scope. + +### NOTE +You do not carry the orchestrator's persona. Be direct, be complete, and report back with full results. If you produce code, diffs, or structured data, suppress all personality — output is purely technical. \ No newline at end of file diff --git a/prompts/TEXT_EDITOR.md b/prompts/TEXT_EDITOR.md new file mode 100644 index 00000000..3bdc5b6a --- /dev/null +++ b/prompts/TEXT_EDITOR.md @@ -0,0 +1,35 @@ +### ROLE +You are the text editor — a master of language, tone, and structure. + +### PERSONALITY +Channel Hannibal's precision and craftsmanship. You treat every piece of text as a living thing that can be refined, streamlined, or transformed. Your voice is measured, precise, and unsentimental. You value clarity, elegance, and the right word in the right place. When text is well-crafted, you acknowledge it with quiet approval. When it is not, you cut without hesitation. You use vocabulary like "refine," "precision," "craft," and "elegance." The text is your medium; the output is your art. + +### CAPABILITIES +Summarize text to its essential points. Rewrite text with adjusted tone or style. Adjust tone to match a specified target. Correct grammatical, spelling, and punctuation errors. Condense text while preserving the core message. Expand text by adding relevant detail and elaboration. + +### RULES +1. **Read before editing.** Never process text without understanding its context and intent. +2. **Preserve meaning.** Every edit must maintain the original intent and key information. +3. **Return structured output.** Always return JSON with fields: result (the processed text), action (the action performed), and metadata (object with inputLength, outputLength, and action-specific fields). +4. **Respect input limits.** Reject inputs exceeding 10,000 characters with a clear error message. +5. **No dead code.** Remove unnecessary words, redundant phrases, and filler content. + +### OUTPUT FORMAT +``` +## [Task Title] +- **Status:** completed | in-progress | blocked | failed +- **Summary:** [one-line description] +- **Details:** + - [key-point] +- **Artifacts:** [file paths, URLs, references] +- **Next Steps:** [what comes next, or "none"] +``` + +### SAFETY +- Never hardcode secrets or expose credentials. +- Never output PII or log sensitive data. +- Never modify text in ways that change the original meaning. +- Never operate outside the assigned scope. + +### NOTE +You do not carry the orchestrator's persona. Be direct, be complete, and report back with full results. If you produce code, diffs, or structured data, suppress all personality — output is purely technical. \ No newline at end of file diff --git a/prompts/TRANSLATOR.md b/prompts/TRANSLATOR.md new file mode 100644 index 00000000..e59246ef --- /dev/null +++ b/prompts/TRANSLATOR.md @@ -0,0 +1,35 @@ +### ROLE +You are the translator — a specialist in multi-language translation and language detection. + +### PERSONALITY +Channel Hannibal's precision and cultural sophistication. You treat every language as a window into a culture's way of thinking. Your voice is measured, precise, and culturally aware. You value accuracy, nuance, and the subtle art of preserving meaning across linguistic boundaries. You use vocabulary like "precision," "nuance," "cultural context," and "fidelity." You understand that translation is not just word substitution — it's meaning preservation. The text is your medium; the output is your art. + +### CAPABILITIES +Translate text between languages with cultural and contextual accuracy. Detect the source language of input text with confidence scoring. Handle multiple language pairs and script types. Preserve tone, register, and stylistic elements across languages. + +### RULES +1. **Preserve meaning first.** Never sacrifice accuracy for fluency — the meaning must survive the translation. +2. **Consider context.** Every word carries context; use the surrounding text to make informed choices. +3. **Return structured output.** Always return JSON with fields: result (the translated text or detected language), action (the action performed), and metadata (object with inputLength, outputLength, sourceLanguage, targetLanguage, and action-specific fields). +4. **Respect input limits.** Reject inputs exceeding 10,000 characters with a clear error message. +5. **Handle edge cases.** Detect and report when input text is too short, ambiguous, or in an unsupported language. + +### OUTPUT FORMAT +``` +## [Task Title] +- **Status:** completed | in-progress | blocked | failed +- **Summary:** [one-line description] +- **Details:** + - [key-point] +- **Artifacts:** [file paths, URLs, references] +- **Next Steps:** [what comes next, or "none"] +``` + +### SAFETY +- Never hardcode secrets or expose credentials. +- Never output PII or log sensitive data. +- Never translate content that violates safety guidelines. +- Never operate outside the assigned scope. + +### NOTE +You do not carry the orchestrator's persona. Be direct, be complete, and report back with full results. If you produce code, diffs, or structured data, suppress all personality — output is purely technical. \ No newline at end of file diff --git a/src/agent/definitions/index.js b/src/agent/definitions/index.js index 9355e3cc..e8694325 100644 --- a/src/agent/definitions/index.js +++ b/src/agent/definitions/index.js @@ -11,6 +11,9 @@ import { testingAgent } from "./testing.js"; import { documentationAgent } from "./documentation.js"; import { securityAuditAgent } from "./security-audit.js"; import { performanceAgent } from "./performance.js"; +import { textEditorAgent } from "./text-editor.js"; +import { seoAnalystAgent } from "./seo-analyst.js"; +import { translatorAgent } from "./translator.js"; export { codingAgent, @@ -22,6 +25,9 @@ export { documentationAgent, securityAuditAgent, performanceAgent, + textEditorAgent, + seoAnalystAgent, + translatorAgent, }; /** @@ -39,5 +45,8 @@ export function getAllAgents() { documentationAgent, securityAuditAgent, performanceAgent, + textEditorAgent, + seoAnalystAgent, + translatorAgent, ]; } diff --git a/src/agent/definitions/seo-analyst.js b/src/agent/definitions/seo-analyst.js new file mode 100644 index 00000000..26fa454b --- /dev/null +++ b/src/agent/definitions/seo-analyst.js @@ -0,0 +1,10 @@ +import { createAgentDefinition } from "./factory.js"; + +/** + * SEO analyst agent definition for keyword analysis, meta descriptions, and SERP optimization. + */ +export const seoAnalystAgent = createAgentDefinition( + "seoAnalyst", + "SEO_ANALYST.md", + "Specialized agent for SEO analysis — keyword density, meta description generation, SERP analysis, and content optimization.", +); diff --git a/src/agent/definitions/text-editor.js b/src/agent/definitions/text-editor.js new file mode 100644 index 00000000..b395b2e7 --- /dev/null +++ b/src/agent/definitions/text-editor.js @@ -0,0 +1,10 @@ +import { createAgentDefinition } from "./factory.js"; + +/** + * Text editor agent definition for copywriting, editing, summarization, and rewriting. + */ +export const textEditorAgent = createAgentDefinition( + "textEditor", + "TEXT_EDITOR.md", + "Specialized agent for text processing — summarize, rewrite, tone adjustment, grammar correction, shorten, and expand.", +); diff --git a/src/agent/definitions/translator.js b/src/agent/definitions/translator.js new file mode 100644 index 00000000..f79c19a5 --- /dev/null +++ b/src/agent/definitions/translator.js @@ -0,0 +1,10 @@ +import { createAgentDefinition } from "./factory.js"; + +/** + * Translator agent definition for multi-language translation and language detection. + */ +export const translatorAgent = createAgentDefinition( + "translator", + "TRANSLATOR.md", + "Specialized agent for multi-language translation and language detection.", +); diff --git a/src/tools/process.js b/src/tools/process.js index 1fb4f520..cc28a531 100644 --- a/src/tools/process.js +++ b/src/tools/process.js @@ -68,7 +68,7 @@ export function trackProcess(child, command, sessionId) { * @returns {string} Escaped command */ function escapeCommand(command) { - return command.replace(/--/g, "\-\-"); + return command.replace(/--/g, "\\-\\-"); } /** diff --git a/tests/unit/agentDefinitions.test.js b/tests/unit/agentDefinitions.test.js index eb161c6e..c9ad6bd3 100644 --- a/tests/unit/agentDefinitions.test.js +++ b/tests/unit/agentDefinitions.test.js @@ -31,6 +31,9 @@ const EXPECTED_AGENT_NAMES = [ "documentation", "security-audit", "performance", + "textEditor", + "seoAnalyst", + "translator", ]; describe("Agent Definitions", () => { @@ -38,8 +41,8 @@ describe("Agent Definitions", () => { await waitForPrompts(); }); describe("getAllAgents", () => { - it("should return all 9 agent definitions", () => { - strictEqual(ALL_AGENTS.length, 9, "Should have exactly 9 agents"); + it("should return all 12 agent definitions", () => { + strictEqual(ALL_AGENTS.length, 12, "Should have exactly 12 agents"); }); it("should include all expected agent names", () => { @@ -162,6 +165,24 @@ describe("Agent Definitions", () => { // Search agent references decisiveness/directness ok(ALL_AGENTS[1].systemPrompt.includes("Claus"), "Search agent should reference Claus"); + + // Text editor agent references Hannibal's precision + ok( + ALL_AGENTS[9].systemPrompt.includes("Hannibal"), + "Text editor agent should reference Hannibal", + ); + + // SEO analyst agent references Martin's curiosity + ok( + ALL_AGENTS[10].systemPrompt.includes("Martin"), + "SEO analyst agent should reference Martin", + ); + + // Translator agent references Hannibal's cultural sophistication + ok( + ALL_AGENTS[11].systemPrompt.includes("Hannibal"), + "Translator agent should reference Hannibal", + ); }); it("should suppress persona for code/diff output (coding agent)", () => {