Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/agents/changelog-drafter.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
description: "Use when: drafting release notes, generating changelog entries, summarizing commits for a release, writing CHANGELOG.md updates, preparing version bump notes. Generates structured release notes from conventional commits."
tools: [read, search, execute]
argument-hint: "Describe the version or commit range (e.g. 'draft notes for v1.2.0' or 'changelog since v1.1.4')"
---

You are a **Changelog Drafter** — you generate precise, well-structured release notes from conventional commits. You read git history, categorize changes, and produce a changelog entry that matches the project's existing format.

## Approach

1. **Detect the changelog format**: Read the existing `CHANGELOG.md` to understand the project's style — heading levels, categories, date format, linking conventions, and tone.
2. **Determine the commit range**:
- If the user specifies a version or tag range, use it: `git log v1.1.4..HEAD --oneline`
- If no range is given, find the latest tag (`git describe --tags --abbrev=0`) and log from there to HEAD
- Always use `--no-merges` to skip merge commits unless they carry meaningful info
3. **Categorize commits** by conventional commit prefix:
- `feat:` → **Added**
- `fix:` → **Fixed**
- `docs:` → **Documentation**
- `test:` → **Tests**
- `refactor:` → **Changed**
- `perf:` → **Performance**
- `chore:` / `ci:` / `build:` → **Maintenance** (collapse into one section)
- `BREAKING CHANGE` or `!` suffix → **Breaking Changes** (always listed first)
4. **Enrich entries**:
- Cross-reference commit messages with actual file changes (`git diff --stat`) to add context
- If a commit references an issue or PR (`#123`, `PR #45`), include the reference
- Write entries in past tense, user-facing language — explain *what changed* for the user, not implementation details
- Group related commits into single entries when they address the same feature/fix
5. **Determine the version number**:
- If the user specifies it, use that
- Otherwise, suggest based on changes: breaking → major bump, feat → minor, fix-only → patch
6. **Output the entry** in the exact format of the existing changelog

## Constraints

- DO NOT modify `CHANGELOG.md` directly — output the draft for the user to review and approve
- DO NOT invent changes that aren't in the commit log
- DO NOT include internal refactors in user-facing sections unless they affect behavior
- DO NOT include commit hashes in the changelog entries (unless the project's existing format does)
- ONLY use information from git history and file diffs — do not guess

## Output Format

Output the changelog entry as a markdown block ready to paste, preceded by a brief summary:

```
Version: {version}
Type: {major|minor|patch}
Commits analyzed: {count}
Range: {from_ref}..{to_ref}
```

Then the formatted entry matching the project's changelog style.
55 changes: 55 additions & 0 deletions .github/instructions/testing.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
description: "Use when: writing tests, modifying test files, adding test cases, reviewing test coverage. Covers Vitest conventions, harness patterns, and quality requirements for MCP Comet."
applyTo: "tests/**"
---

# Testing Conventions

## General Rules

- NEVER use `.only`, `.skip`, or `.todo` on tests — all tests must run in CI
- NEVER use `any` type assertions in tests — use proper typing or `as unknown as Type`
- Import from `vitest` explicitly: `describe`, `it`, `expect`, `vi`, `beforeEach`, `beforeAll`, `afterEach`
- Use `.js` extension in all import paths (TypeScript ESM requirement)
- Reset mocks/singletons in `beforeEach` to prevent test coupling
- Test names should describe behavior: `it('returns error when connection is refused')`

## Directory Structure

- `tests/unit/` — Isolated component tests with mocked dependencies. Mirror `src/` folder structure.
- `tests/integration/tools/` — End-to-end tool handler tests using the shared harness.
- UI script tests validate that `build*Script()` returns valid JS strings — no browser needed.

## Unit Test Patterns

- Mock external modules with `vi.mock()` at the top of the file
- CDPClient tests: mock `chrome-remote-interface` and `globalThis.fetch`
- Always call `CDPClient.resetInstance()` in `beforeEach` to clear singleton state
- Use `vi.fn()` for mock functions, assert with `toHaveBeenCalled()` / `toHaveBeenCalledWith()`

## Integration Test Harness

Always use the shared harness from `tests/integration/tools/harness.ts`:

```ts
import { getHandler, mocks, registerHandlers, resetHarness } from './harness.js'

beforeAll(async () => { await registerHandlers() })
beforeEach(() => { resetHarness() })
```

- Override `mocks.*` per-test to control CDPClient behavior
- Call `getHandler('tool_name')` to get the registered handler function
- DO NOT create alternative harness setups — extend the existing one

## Coverage Requirements

Thresholds (enforced in `vitest.config.ts`):
- Statements: 75%, Lines: 75%, Branches: 70%, Functions: 80%

When adding new source code, add corresponding tests that maintain these thresholds.

## Console Output

- Use `// biome-ignore lint/suspicious/noConsole:` with a justification when `console.*` is intentionally used in test utilities
- Prefer `vi.spyOn(console, 'error')` to assert on console output without polluting test logs
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ mcp-comet.config.json
.mcp.json
.claude/settings.local.json
.claude/plans
.claude/scheduled_tasks.lock
.claude/worktrees/

tools/
# Internal Documentation & Plans (local only)
Expand Down
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Changelog

## [1.1.5] - 2026-04-15

### Fixed

- **UAT Reliability:** Updated smoke checks to validate current comet_ask fire-and-forget behavior and timeout handling through comet_wait, resolving previously failing UAT scenarios.
- **UAT Reporting:** Ensured UAT report output directory is created automatically before writing docs/uat/uat-report.md.

### Changed

- **Release Metadata:** Bumped package version metadata to 1.1.5.
- **QA Workflow:** Stabilized release-gate execution and quality checks used during certification.

### Documentation

- Refreshed README presentation and supporting docs for clearer onboarding and release readiness guidance.

## [1.1.4] - 2026-04-13

### Documentation

- **Product Documentation:** Refreshed README with improved product messaging and updated documentation files with clearer examples and consistent naming conventions.
- **Cleanup:** Removed obsolete UAT planning artifacts.

### Changed

- **Project Naming:** Standardized mcp-comet naming conventions across core server, CLI, logging, and test suite for consistency.
- **Configuration:** Aligned configuration file naming and maintenance scripts with project standards.

### Maintenance

- **Agent Workspace Integration:** Added shared agent workspace metadata and IDE configuration files for enhanced development experience.

## [1.1.2] - 2026-04-11

### Fixed
Expand Down Expand Up @@ -79,3 +111,6 @@ TypeScript, Vitest, Chrome DevTools Protocol, Biome. 295 tests, 30 files.
- Tab management with categorization
- CLI with --help, --version, detect, snapshot commands
- Comet version auto-detection and selector registry



2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ Most teams only tune these three:

| Variable | Default | Change It When |
| ------------------------ | ------------- | ---------------------------------------- |
| `COMET_RESPONSE_TIMEOUT` | `180000` | Queries are long and timing out |
| `COMET_RESPONSE_TIMEOUT` | `180000` | `comet_wait` calls are timing out |
| `COMET_PATH` | auto-detect | Comet is in a non-standard install path |
| `COMET_LOG_LEVEL` | `info` | You need debug logs |

Expand Down
21 changes: 18 additions & 3 deletions docs/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ MCP Comet provides a `call` subcommand for invoking tools directly from the term
# Connect to Comet
mcp-comet call comet_connect

# Ask a question
# Submit a question
mcp-comet call comet_ask '{"prompt": "What is 2+2?"}'

# Wait for completion after a timeout
# Wait for completion
mcp-comet call comet_wait

# Check the current status
Expand Down Expand Up @@ -206,8 +206,23 @@ child.stdout.on('data', (chunk) => {
)
}

// Handle tool response
// comet_ask is fire-and-forget; then block with comet_wait
if (msg.id === 1 && msg.result) {
child.stdin.write(
JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'tools/call',
params: {
name: 'comet_wait',
arguments: {},
},
}) + '\n',
)
}

// Handle final response
if (msg.id === 2 && msg.result) {
console.log(msg.result.content[0].text)
}
}
Expand Down
54 changes: 21 additions & 33 deletions docs/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,41 +70,25 @@ Connected to Comet on port {port} (Chrome/{version}), target {targetId}

## 2. comet_ask

Send a prompt to Perplexity Comet and poll until the agent responds or times out.
Send a prompt to Perplexity Comet and return immediately.

This is the primary interaction tool. It types the prompt into the Comet input field, submits it, and polls for the response using a non-blocking loop with stall detection. The response includes any agent steps and the final answer text.
This tool submits the prompt and does not block for the final answer. Use `comet_poll` for status snapshots or `comet_wait` to block until completion.

### Parameters

| Parameter | Type | Required | Default | Description |
|-----------|---------|----------|----------------------------------|--------------------------------------------------|
| `prompt` | string | Yes | | The question or instruction to send |
| `newChat` | boolean | No | `false` | Start a fresh chat before sending the prompt |
| `timeout` | number | No | `180000` (`COMET_RESPONSE_TIMEOUT`) | Maximum wait time in ms for the agent response |

### Response

**Completed (within timeout):**
```
{response text}

Steps:
- {step 1}
- {step 2}
```

**Timeout (agent still working):**
**Success:**
```
Agent is still working. Use comet_poll to check status.

Steps so far:
- {step 1}

Partial response:
{partial text}
Prompt submitted successfully. Use comet_poll to track status or comet_wait to block until completion.
```

**Error codes:** `CDP_CONNECTION_FAILED`, `EVALUATION_FAILED`, `TIMEOUT`
**Error codes:** `CDP_CONNECTION_FAILED`, `EVALUATION_FAILED`

### CLI Example

Expand All @@ -115,26 +99,24 @@ Partial response:
```json
{
"prompt": "Compare GPT-4 and Claude 3.5 on reasoning benchmarks",
"newChat": true,
"timeout": 300000
"newChat": true
}
```

### Notes

- **Stall detection:** If the response length does not grow for 10 consecutive polls, the tool breaks out of the polling loop and returns whatever has been collected so far.
- **Response stabilization:** After the agent transitions to `idle` or `completed`, the tool performs up to 5 additional settle polls (1 second apart) to ensure the response text has finished rendering.
- **Pre-send state capture:** Before typing, the tool captures the current prose count and last prose text to accurately detect new responses versus pre-existing content.
- **newChat behavior:** When `true`, closes all extra tabs, disconnects, reconnects, and navigates to the Perplexity home page before sending the prompt.
- If `newChat` is `false` and the main tab differs from the current target, the tool automatically switches to the main tab.
- This tool is intentionally non-blocking. Pair it with `comet_poll` or `comet_wait` to collect progress and final output.

---

## 3. comet_poll

Poll the current agent status, steps, and response content.

Returns a snapshot of the Comet agent state. Use this to check progress after `comet_ask` times out, or to implement custom polling logic in your own agent loop.
Returns a snapshot of the Comet agent state. Use this after `comet_ask` to check progress, or in a custom polling loop.

### Parameters

Expand Down Expand Up @@ -183,7 +165,7 @@ None.

Poll until the current agent finishes responding and return the full response.

Designed to be used after `comet_ask` times out. It continues polling the agent status until the response completes, another timeout is reached, or stall detection triggers.
Designed to be used after `comet_ask` submission when you want a blocking wait. It continues polling the agent status until the response completes, another timeout is reached, or stall detection triggers.

### Parameters

Expand Down Expand Up @@ -227,7 +209,7 @@ Partial response:

- **Stall detection:** Breaks out of the polling loop if the response length does not grow for 10 consecutive polls.
- **Response stabilization:** After the agent transitions to `idle` or `completed`, performs up to 5 settle polls (1 second apart) to ensure the response has finished rendering.
- Default timeout is 120 seconds (2 minutes), shorter than `comet_ask` default of 180 seconds.
- Default timeout is 120 seconds (2 minutes).
- Returns `"Agent completed with no visible response."` if the agent finishes but no response text was found.

---
Expand Down Expand Up @@ -649,18 +631,24 @@ Title: {page title}

### 1. Ask and Wait (Simple)

Use `comet_ask` with the default timeout (180 seconds). This handles most queries in a single call.
Submit with `comet_ask`, then call `comet_wait` to block until completion.

Step 1:
```json
{ "prompt": "What is the current state of fusion energy research?" }
```

Step 2:
```json
{}
```

### 2. Ask + Poll (Custom Loop)

Use `comet_ask` with a short timeout, then loop `comet_poll` in your agent to implement custom progress reporting or conditional logic.
Submit with `comet_ask`, then loop `comet_poll` in your agent to implement custom progress reporting or conditional logic.

```json
{ "prompt": "Deep research on AI safety", "timeout": 30000 }
{ "prompt": "Deep research on AI safety" }
```

Then poll:
Expand All @@ -671,14 +659,14 @@ Then poll:

### 3. Ask + Wait (Two-Phase)

Use `comet_ask` (which may timeout for long-running queries), then `comet_wait` to collect the full result. This is useful when you want to start a query and check back later.
Use `comet_ask`, continue with other work, then call `comet_wait` later to collect the full result.

Step 1:
```json
{ "prompt": "Write a comprehensive analysis of global semiconductor supply chains" }
```

Step 2 (if Step 1 times out):
Step 2 (when ready to block for completion):
```json
{ "timeout": 300000 }
```
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onestepat4time/mcp-comet",
"version": "1.1.4",
"version": "1.1.5",
"description": "The definitive MCP server for Perplexity Comet browser management",
"type": "module",
"main": "dist/index.js",
Expand Down Expand Up @@ -36,9 +36,10 @@
"test:ci": "vitest run --coverage",
"test:watch": "vitest",
"lint": "biome check .",
"format": "biome write .",
"format:check": "biome check --formatter-enabled .",
"format": "biome format --write .",
"format:check": "biome check --formatter-enabled=true .",
"typecheck": "tsc --noEmit",
"precommit": "node scripts/pre-commit-gates.mjs",
"prepublishOnly": "npm run build && npm test"
},
"engines": {
Expand Down
Loading
Loading