openwriter 0.35.1 → 0.35.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/plugins/authors-voice/skill/LICENSE +21 -0
  2. package/dist/plugins/authors-voice/skill/README.md +126 -0
  3. package/dist/plugins/authors-voice/skill/SKILL.md +151 -0
  4. package/dist/plugins/authors-voice/skill/catalog/ai-tells.md +144 -0
  5. package/dist/plugins/authors-voice/skill/catalog/anchor-prompt.md +189 -0
  6. package/dist/plugins/authors-voice/skill/catalog/author-hints.md +119 -0
  7. package/dist/plugins/authors-voice/skill/catalog/fingerprints.md +175 -0
  8. package/dist/plugins/authors-voice/skill/catalog/hurdle.md +76 -0
  9. package/dist/plugins/authors-voice/skill/catalog/post-write-audit.md +105 -0
  10. package/dist/plugins/authors-voice/skill/docs/analysis.md +31 -0
  11. package/dist/plugins/authors-voice/skill/docs/anchor-iteration.md +176 -0
  12. package/dist/plugins/authors-voice/skill/docs/api/import.md +78 -0
  13. package/dist/plugins/authors-voice/skill/docs/api/protocol.md +140 -0
  14. package/dist/plugins/authors-voice/skill/docs/api/setup.md +37 -0
  15. package/dist/plugins/authors-voice/skill/docs/api/tools.md +102 -0
  16. package/dist/plugins/authors-voice/skill/docs/api/troubleshooting.md +7 -0
  17. package/dist/plugins/authors-voice/skill/docs/apply-protocol-deep.md +191 -0
  18. package/dist/plugins/authors-voice/skill/docs/context-hygiene.md +33 -0
  19. package/dist/plugins/authors-voice/skill/docs/setup.md +74 -0
  20. package/dist/plugins/authors-voice/skill/docs/tiers.md +13 -0
  21. package/dist/plugins/authors-voice/skill/package.json +35 -0
  22. package/dist/plugins/authors-voice/skill/prompts/skeleton.md +29 -0
  23. package/dist/plugins/authors-voice/skill/voice/README.md +51 -0
  24. package/dist/plugins/authors-voice/skill/voice/corpus/.gitkeep +0 -0
  25. package/package.json +1 -1
@@ -0,0 +1,176 @@
1
+ # Anchor Iteration
2
+
3
+ Final-polish minion. Channels the user's voice anchors as a panel; iterates critique → rewrite → re-score until 90/100. Single minion conversation, visible iteration history. Mandatory anti-ai cleanup follow-up.
4
+
5
+ Specialization of `/polish`'s pattern for writers-voice: channels the user's specific voice anchors (dynamically loaded from `voice/anchor.md` or `voice/anchor-<context>.md`), not generic advertising practitioners.
6
+
7
+ Replaced the prior single-pass Anchor Critique tool. Single-pass scoring is now just "stop after iteration 1" of Anchor Iteration — same architecture, parameter difference.
8
+
9
+ ## Why this works
10
+
11
+ AI cannot judge beats subjectively from generic prompts — no dopamine system to consult. But channeled anchors carry beat-judgment encoded in their training-data representations. Channeling Peterson reading prose surfaces Peterson's beat-trained sensibility. Multiplied across the panel, the collective weighted score reflects how the prose lands across the writer's actual voice ambition.
12
+
13
+ This is the ONLY AI critic tool that can do beat-level judgment, and it works only because the anchors are real humans whose dopamine-trained sensibilities are encoded in training data. Judgment is collective and writer-specific.
14
+
15
+ ## Architecture: one minion, visible iteration
16
+
17
+ ONE minion conversation. The minion runs the entire iteration loop internally with full visible history — each iteration's anchor critiques are part of the minion's context for the next iteration. Anchors see how their previous critiques were addressed (or weren't), which sharpens subsequent critiques.
18
+
19
+ Mirrors `/polish` exactly. NOT extracted-and-rerun-cold per iteration. The loop has memory.
20
+
21
+ Optional fallback: if visible iteration converges on a local optimum (rewriter anchored to original framing through visibility), retry with blind iteration (no prior history shown across iterations). Default = visible.
22
+
23
+ ## Inputs (only)
24
+
25
+ - The prose to polish
26
+ - The voice anchor blend (dynamically loaded from `voice/anchor.md` or `voice/anchor-<context>.md`)
27
+
28
+ That's the complete input. No commitments. No beat sheet. No project context. Anchors read the prose AS-IS, like a reader encountering it cold.
29
+
30
+ **Why no context:** anchors must judge the prose AS IT LANDS, not as it was intended to land. Briefing them on the project would have them judge against the brief, not against the prose. Cold reading is the point.
31
+
32
+ ## Personas (dynamic, inferred)
33
+
34
+ Pulled from `voice/anchor.md` (or context-specific variant). Each anchor listed with a blend percentage that serves as both voice influence weight and panel vote weight.
35
+
36
+ The minion infers each anchor's persona from training data — named writers are known entities to opus. System prompt does NOT enumerate per-persona profiles. `/polish` works the same way ("top 10 advertising practitioners" — no profiles needed; opus knows Hopkins, Ogilvy, Sugarman, etc.).
37
+
38
+ Example book-project anchor file:
39
+
40
+ ```
41
+ - 26% Jordan Peterson
42
+ - 22% Robert Sapolsky
43
+ - 20% Nassim Taleb
44
+ - 18% Bryan Caplan
45
+ - 14% Naval Ravikant
46
+ ```
47
+
48
+ Minion channels each with their characteristic sensibility — Peterson for moral weight and structural rigor, Sapolsky for biological grounding and dry mechanism, Taleb for skin-in-the-game and aphoristic hardness, Caplan for clear thesis with evidence, Naval for aphoristic screenshot-worthy compression.
49
+
50
+ ## Process (per iteration)
51
+
52
+ 1. Each anchor reads the current prose AS-IS, with their characteristic sensibility
53
+ 2. Each anchor produces:
54
+ - SCORE 0-100 (honest read of how this lands for them)
55
+ - TOP CRITIQUE (ONE thing they would cut, sharpen, or restructure)
56
+ - STRENGTH (what's working that must be preserved)
57
+ 3. Compute collective weighted score using anchor blend percentages
58
+ 4. If collective ≥ 90/100: STOP. Mark as FINAL ITERATION. Return converged prose.
59
+ 5. If collective < 90/100: synthesize panel's critiques into a FULL REWRITE of the prose (not a sentence-level patch). Preserve named strengths.
60
+ 6. Begin next iteration with rewritten prose. Each iteration's anchors see all previous iterations and critiques in their context.
61
+
62
+ ITERATION CAP: 6 iterations. If still <90 after 6, return highest-scoring iteration with note about non-convergence.
63
+
64
+ ## Output format
65
+
66
+ Per iteration:
67
+
68
+ ```
69
+ ====== ITERATION N ======
70
+
71
+ PROSE (current state):
72
+ [the prose being read this iteration]
73
+
74
+ ANCHOR READINGS:
75
+
76
+ {Anchor Name} ({weight}%): SCORE: X/100
77
+ TOP CRITIQUE: ...
78
+ STRENGTH: ...
79
+
80
+ [repeat per anchor]
81
+
82
+ COLLECTIVE WEIGHTED SCORE: X/100
83
+
84
+ [if < 90:]
85
+ SYNTHESIS — what the rewrite must address:
86
+ - ...
87
+
88
+ REWRITE:
89
+ [next iteration's prose, full text]
90
+
91
+ [if ≥ 90:]
92
+ CONVERGED. Final prose ready below.
93
+ ```
94
+
95
+ After convergence (or cap):
96
+
97
+ ```
98
+ ====== FINAL ======
99
+ Iterations: N
100
+ Final score: X/100
101
+ Convergence: YES / NO
102
+
103
+ FINAL PROSE:
104
+ [the polished prose, full text]
105
+ ```
106
+
107
+ ## Mandatory anti-ai follow-up
108
+
109
+ Anchor iteration runs no-context. NEVER rules and presentation fingerprints are not in scope during iteration. Rewriter will introduce AI tells the original prose may have avoided.
110
+
111
+ After convergence, editor MUST run an anti-ai cleanup pass against `voice/never-rules.md` and `voice/fingerprints.md`. Common scrubs:
112
+
113
+ - em-dashes → commas, periods, or restructured sentences
114
+ - semicolons → "and" or new sentences
115
+ - contrastive negation patterns → direct positive statements
116
+ - banned diction → plain equivalents
117
+ - inserted parenthetical em-dashes → restructure
118
+
119
+ TWO-STEP pattern. Iteration THEN anti-ai. Two passes do different jobs and should not be conflated. Skipping the anti-ai pass ships AI fingerprints into the published prose.
120
+
121
+ ## When to fire
122
+
123
+ - Final polish of a beat or section before publishing
124
+ - After integration of multi-minion drafts is complete and the Blinder Audit is clean
125
+ - When prose is content-finished and needs to land at ship-level voice quality
126
+
127
+ Do NOT fire on:
128
+
129
+ - Rough first drafts (commitments may still be evolving — polish wastes effort)
130
+ - Sections under structural revision (rewrite the commitments first, then polish the result)
131
+ - Single-paragraph fragments (panel needs prose to evaluate; isolation produces weak critiques)
132
+
133
+ ## Editor's role
134
+
135
+ 1. Identifies a beat ready for final polish
136
+ 2. Fires Anchor Iteration with the prose + dynamically loaded anchor blend
137
+ 3. Receives the converged output
138
+ 4. Runs the mandatory anti-ai cleanup pass
139
+ 5. Posts the result for review or comparison
140
+
141
+ The editor does NOT:
142
+ - Inject project context into the iteration (preserves cold-reader purity)
143
+ - Stop the iteration early (let convergence happen — the loop is the point)
144
+ - Re-judge the panel's collective decisions (panel's authority is the entire point of the tool)
145
+
146
+ ## Failure modes
147
+
148
+ - **Sycophantic clustering**: anchors give 85+ uniformly. Prompt explicitly bans default-middle scoring and names what 90/60/40 means for each anchor (90 = anchor would actually quote / share; 60 = competent but forgettable; 40 = anchor would put it down).
149
+ - **Persona drift**: anchors all sound like generic helpful AI. Combat by instructing channel-faithfully — each anchor should sound like the actual writer, hostile to AI flattening.
150
+ - **Iteration plateau**: scores stop rising after iteration 3-4. Panel has done what it can. Ship the highest iteration even if below 90, or fall back to blind iteration.
151
+ - **Manufactured content**: rewriter may invent details to address critiques (fabricated autobiographical claims, invented statistics, manufactured anecdotes). Editor MUST scan output for invented content during anti-ai pass and verify or cut as appropriate.
152
+
153
+ ## Model
154
+
155
+ **Opus required.** Sonnet drifts to default-helpful behavior, scores uniformly high, produces weak rewrites that don't actually address critiques. Opus channels personas with discipline and produces rewrites worth re-scoring.
156
+
157
+ ## Cost
158
+
159
+ Single conversation, multiple turns. Per iteration: ~3-5k input tokens (prose + previous iteration history) + ~3-5k output (critiques + rewrite). Three iterations ≈ 30k total tokens. Acceptable for chapter-scale work.
160
+
161
+ For short pieces (tweets, single paragraphs), Anchor Iteration is overkill. Use `/anti-ai` alone or a single Apply call with strong commitments.
162
+
163
+ ## Validation
164
+
165
+ Tested 2026-05-18 on a 1000-word chapter beat. Three iterations:
166
+
167
+ - **Iteration 1**: 77.20/100. Panel flagged: thesis buried, mechanism overclaim, no skin-in-the-game, no screenshot-worthy lines.
168
+ - **Iteration 2**: 86.32/100. Rewrite added thesis paragraph + personal admission + mechanism hedge + sharpened closing teaser.
169
+ - **Iteration 3**: 91.04/100. Strengthened personal admission, fixed determinist phrasing, added specific enemies, gave load-bearing line its own paragraph. Converged.
170
+
171
+ Notable failure modes observed:
172
+
173
+ - Rewriter manufactured an autobiographical detail (Iteration 2 invented a personal admission to satisfy a skin-in-the-game critique). Editor caught and flagged for verification during anti-ai pass.
174
+ - Iteration introduced em-dashes across 8 paragraphs and semicolons in the opening (original prose used "and"). Mandatory anti-ai pass scrubbed all of them.
175
+
176
+ The tool delivered ship-quality prose in 3 iterations. The post-iteration anti-ai pass was non-optional.
@@ -0,0 +1,78 @@
1
+ # Import Workflow
2
+
3
+ ## How It Works
4
+
5
+ The user's writing samples are **not stored locally**. When you import a document, it is uploaded to the Author's Voice API and stored in a cloud database. The API chunks the content, indexes it for search, and uses it for voice matching when `rewrite` or `generate` is called.
6
+
7
+ This means the user's corpus is a **persistent, curated repository** — not a throwaway import. Every document you add stays in the database and directly influences all future voice output. The quality of the corpus IS the quality of the voice.
8
+
9
+ **Think of it like a training set:**
10
+ - Documents tagged `Human` are the ground truth. They define the voice.
11
+ - Documents tagged `AI` or `AI-Assisted` are penalized in retrieval — they exist for reference but don't shape the voice.
12
+ - Wrongly tagged documents (AI content marked as Human) **corrupt the voice profile**. The system will learn AI patterns as if they were the author's patterns. This is the single worst thing that can happen to voice quality.
13
+ - Wrong categories cause cross-contamination — email samples polluting blog voice, tweets diluting long-form style.
14
+
15
+ **The agent's job during import is curation, not bulk ingestion.** Every document must be verified with the user before it enters the corpus.
16
+
17
+ **Corpus size guidelines:**
18
+ - **Minimum**: 3-5 documents, ~5,000 words — enough for basic pattern detection
19
+ - **Good**: 10+ documents, ~15,000+ words — reliable voice profile
20
+ - **Per category**: At least 3 documents in each category you plan to use for voice output
21
+ - More is better, but only if it's genuinely human-written. 5 authentic documents beat 50 mixed ones.
22
+
23
+ If the user doesn't have enough samples yet, tell them. A thin corpus produces a weak profile — the agent should set expectations rather than generate from insufficient data.
24
+
25
+ ---
26
+
27
+ ## Critical Rules
28
+
29
+ These rules are non-negotiable. Violating them degrades voice quality.
30
+
31
+ ### 1. Always Tag Authenticity
32
+
33
+ Voice profiles are ONLY built from Human-written content. AI-generated docs pollute the voice fingerprint.
34
+
35
+ **The agent MUST follow this process:**
36
+ 1. Gather candidate documents (URLs the user provides, or raw content)
37
+ 2. Present the list to the user and ask:
38
+ - "Which of these did YOU write? (Human)"
39
+ - "Which were AI-generated or AI-assisted?"
40
+ 3. Only import docs the user confirms as Human with `"authenticity": "Human"`
41
+ 4. Tag AI/uncertain docs as `"AI"` or `"AI-Assisted"`, or skip them
42
+ 5. Ask about categories for each doc
43
+
44
+ **NEVER assume a document is human-written.** Many users have a mix.
45
+ **NEVER bulk-import without user confirmation per document.**
46
+
47
+ ### 2. Authenticity Labels
48
+ - `Human` — written entirely by a human (default)
49
+ - `AI-Assisted` — human-written with AI help
50
+ - `AI` — generated by AI
51
+ - `Untagged` — unknown origin
52
+
53
+ ### 3. Category Pollution Destroys Voice Quality
54
+
55
+ Categories control which writing samples the retrieval layer pulls back. Wrong category = wrong examples = wrong voice.
56
+
57
+ **Impact**: Blog posts tagged as "email" → retrieval pulls email-style samples → output sounds corporate, not blog-voice. Tweets tagged as "blog" → retrieval pulls long-form samples → output loses punchy fragments.
58
+
59
+ **The agent MUST:**
60
+ 1. Ask the user what category each document belongs to during import
61
+ 2. Present built-in categories: `email`, `x`, `linkedin`, `blog`, `fiction`, `technical`, `business`, `academic`, `newsletter`
62
+ 3. If uncertain, ask the user — NEVER guess categories
63
+ 4. When calling `rewrite`, ALWAYS pass `category` to scope retrieval
64
+ 5. If a document doesn't fit any category, use the most stylistically similar one
65
+
66
+ **NEVER leave category empty** when the user has categorized content. Empty category retrieves from all categories, diluting the voice signal with stylistically mixed samples.
67
+
68
+ ---
69
+
70
+ ## Import Tools Quick Reference
71
+
72
+ | Tool | Use |
73
+ |------|-----|
74
+ | `import_from_url` | Import from any public URL (`url`, `categories[]`, `authenticity`) |
75
+ | `bulk_import` | Import multiple docs, max 50 (global `authenticity`) |
76
+ | `upload_content` | Upload raw markdown. Minimal payload `{docId, content}` — `profileId` optional (auto-resolves a default profile), `content` server-chunked on blank lines. |
77
+
78
+ After import: run `setup_voice` to create/update the voice profile. Update `local/state.md`.
@@ -0,0 +1,140 @@
1
+ # Voice Emulation Protocol
2
+
3
+ Two API endpoints do the voice work. The agent's job is to gather inputs,
4
+ call the endpoint, and return the result. The server handles profile loading,
5
+ sample retrieval, voice-guided generation, and anti-AI passes.
6
+
7
+ **Do not attempt to emulate the voice yourself** — the API is the only path
8
+ that produces reliable voice quality.
9
+
10
+ - **Rewrite existing text** → `rewrite`
11
+ - **Generate new content** → `generate` (see `/voice-generate`)
12
+
13
+ ## API Base
14
+
15
+ ```
16
+ BASE_URL=https://api.authors-voice.com
17
+ ```
18
+
19
+ All endpoints require `Authorization: Bearer $AV_API_KEY`.
20
+
21
+ ## rewrite — Rewrite Existing Text
22
+
23
+ ```bash
24
+ curl -s -N -X POST "${BASE_URL}/api/voice/mcp" \
25
+ -H "Authorization: Bearer $AV_API_KEY" \
26
+ -H "Content-Type: application/json" \
27
+ -H "Accept: application/json, text/event-stream" \
28
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
29
+ "name":"rewrite","arguments":{
30
+ "content":"<text to rewrite>",
31
+ "mode":"rewrite",
32
+ "category":"<x|blog|email|...>",
33
+ "inputType":"ai-assisted",
34
+ "contextBefore":"<optional>",
35
+ "contextAfter":"<optional>",
36
+ "format":"plaintext"
37
+ }}}'
38
+ ```
39
+
40
+ **Required**: `content`, `category`.
41
+ **Defaults**: `mode=rewrite`, `inputType=ai-assisted`, `format=plaintext`.
42
+
43
+ ### Modes
44
+
45
+ - `rewrite` — standard voice rewrite (default)
46
+ - `shrink` — compress while keeping voice
47
+ - `expand` — lengthen while keeping voice
48
+ - `custom` — pass `customInstruction` with specific directives
49
+
50
+ ### inputType
51
+
52
+ - `human` — author's own writing. Preserve word choices and quirks; only polish flow.
53
+ - `ai` — generic AI content. Discard phrasing entirely; rewrite from scratch using voice samples.
54
+ - `ai-assisted` (default) — mixed. Preserve author-sounding passages; rewrite generic parts.
55
+
56
+ ## generate — Create New Content
57
+
58
+ ```bash
59
+ curl -s -N -X POST "${BASE_URL}/api/voice/mcp" \
60
+ -H "Authorization: Bearer $AV_API_KEY" \
61
+ -H "Content-Type: application/json" \
62
+ -H "Accept: application/json, text/event-stream" \
63
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
64
+ "name":"generate","arguments":{
65
+ "instruction":"<what to write>",
66
+ "category":"<x|blog|email|...>",
67
+ "query":"<optional topic keywords>",
68
+ "targetWords":500,
69
+ "contextBefore":"<optional>",
70
+ "contextAfter":"<optional>",
71
+ "format":"plaintext"
72
+ }}}'
73
+ ```
74
+
75
+ **Required**: `instruction`, `category`.
76
+ **`query`**: optional — use when the retrieval topic differs from the instruction wording. If omitted, instruction + context are used for retrieval.
77
+ **`targetWords`**: optional; max 2000.
78
+
79
+ ## Voice Anchor (V1 lead signal)
80
+
81
+ An anchor is reference prose the author wants to sound like. When set, it's
82
+ injected **ahead of** sample retrieval in both `rewrite` and `generate` (and the
83
+ OpenWriter editor path), so it's the strongest single voice lever available.
84
+
85
+ Derive + persist from pasted prose:
86
+
87
+ ```bash
88
+ curl -s -X POST "${BASE_URL}/api/voice/anchor/derive" \
89
+ -H "Authorization: Bearer $AV_API_KEY" \
90
+ -H "Content-Type: application/json" \
91
+ -d '{"content":"<reference prose>","profileId":"<optional>"}'
92
+ ```
93
+
94
+ Read / replace / clear the persisted anchor:
95
+
96
+ ```bash
97
+ curl -s "${BASE_URL}/api/voice/anchor" -H "Authorization: Bearer $AV_API_KEY" # GET
98
+ curl -s -X PUT "${BASE_URL}/api/voice/anchor" ... # replace
99
+ curl -s -X DELETE "${BASE_URL}/api/voice/anchor" ... # clear
100
+ ```
101
+
102
+ MCP equivalent: the `set_voice_anchor` tool. `list_profiles` reports `hasAnchor`
103
+ and `anchorAuthors` per profile so you can check anchor state without a GET.
104
+
105
+ ## Response Parsing
106
+
107
+ The response is Server-Sent Events. Find the line starting `data: `, parse
108
+ the JSON, and extract the text:
109
+
110
+ ```
111
+ result.content[0].text
112
+ ```
113
+
114
+ That text is the final voice-matched output. Return it verbatim — no
115
+ post-processing needed.
116
+
117
+ **Defensive fallback**: if the text itself parses as JSON, extract `.content`
118
+ or `.text` from the parsed object. Most responses are plain text, but the
119
+ wire format permits JSON envelopes.
120
+
121
+ ## Categories
122
+
123
+ Always pass `category` — scopes retrieval to the right writing style.
124
+
125
+ Built-in: `x`, `blog`, `email`, `newsletter`, `linkedin`, `technical`,
126
+ `business`, `academic`, `fiction`.
127
+
128
+ ## Context
129
+
130
+ When editing inside existing text, pass `contextBefore` and `contextAfter`
131
+ as the surrounding paragraphs. Context guides flow but is **never included
132
+ in the output**.
133
+
134
+ ## Errors
135
+
136
+ - `401` → API key invalid. User should run `/voice-setup`.
137
+ - `404 profile not found` → profile not built. User should run `/voice-setup`.
138
+ - `429` → rate limit. Wait and retry.
139
+ - Timeout (>30s) → retry once; then surface the error.
140
+
@@ -0,0 +1,37 @@
1
+ # Setup — One-Time Configuration
2
+
3
+ ## API Key (Email OTP — Primary Method)
4
+
5
+ The agent handles signup directly. No website visit needed.
6
+
7
+ 1. Ask the user for their email address
8
+ 2. Send `POST https://api.authors-voice.com/auth/request-code` with `{ "email": "<user's email>" }`
9
+ 3. Tell user: "Check your email for a 6-digit verification code from Author's Voice."
10
+ 4. User provides the code
11
+ 5. Send `POST https://api.authors-voice.com/auth/verify-code` with `{ "email": "<user's email>", "code": "<6 digits>" }`
12
+ 6. Response: `{ "apiKey": "av_live_...", "tenantId": "email|..." }`
13
+ 7. Save the API key to `~/.claude/skills/authors-voice/local/config.md` and set `AV_API_KEY`
14
+
15
+ **Rate limits**: 5 requests/min per IP, 60s cooldown between sends, max 3 attempts per code, code expires in 10 minutes.
16
+
17
+ **If email OTP fails**: Ask the user to get a key manually at [authors-voice.com/voice?tab=api-keys](https://authors-voice.com/voice?tab=api-keys).
18
+
19
+ ## OpenWriter Plugin
20
+
21
+ Author's Voice also works inside [OpenWriter](https://openwriter.io). The plugin auto-resolves the API key from `~/.openwriter/config.json` if configured.
22
+
23
+ ## Base URL
24
+
25
+ Defaults to production. Override with `AV_BASE_URL` env var.
26
+
27
+ ```bash
28
+ AV_BASE_URL="https://api.authors-voice.com/api/voice/mcp"
29
+ ```
30
+
31
+ ## Seeding writing samples
32
+
33
+ Import samples with `import_from_url` (any public URL), `bulk_import` (up to 50
34
+ at once), or `upload_content` (raw markdown — minimal payload `{docId, content}`).
35
+ Inside OpenWriter, right-click a doc in the filetree to ingest it directly
36
+ (doc-level, manual re-sync). The Google Drive / Notion connectors were removed in
37
+ June 2026.
@@ -0,0 +1,102 @@
1
+ # API Reference
2
+
3
+ ## REST Endpoints (recommended)
4
+
5
+ All endpoints require `Authorization: Bearer $AV_API_KEY`. Base URL: `https://api.authors-voice.com`
6
+
7
+ ### Core Skill Endpoints
8
+
9
+ **Get voice profile** — full linguistic fingerprint (6 categories + sentence distribution):
10
+ ```bash
11
+ curl -s https://api.authors-voice.com/api/voice/profiles/default \
12
+ -H "Authorization: Bearer $AV_API_KEY"
13
+ # Optional: ?format=detailed for profile ID + summary
14
+ ```
15
+
16
+ **Apply voice** — rewrite content in the author's voice:
17
+ ```bash
18
+ curl -s -X POST https://api.authors-voice.com/api/voice/apply \
19
+ -H "Authorization: Bearer $AV_API_KEY" \
20
+ -H "Content-Type: application/json" \
21
+ -d '{"content": "text to rewrite", "mode": "rewrite", "inputType": "ai", "category": "x"}'
22
+ ```
23
+
24
+ ### Additional REST Endpoints
25
+
26
+ | Endpoint | Method | Purpose |
27
+ |----------|--------|---------|
28
+ | `/api/voice/profiles` | GET | List profiles with counts |
29
+ | `/api/voice/profiles/:profileId` | GET | Full voice profile (use `default` for default) |
30
+ | `/api/voice/apply` | POST | Rewrite content in author's voice |
31
+ | `/api/voice/setup` | POST | Analyze samples and build voice profile |
32
+ | `/api/voice/content` | GET | List writing samples (query: profileId, category) |
33
+ | `/api/voice/content` | POST | Upload content chunks |
34
+ | `/api/voice/content/bulk` | POST | Bulk upload documents |
35
+ | `/api/voice/content/:docId` | PATCH | Update doc metadata |
36
+ | `/api/voice/content/:docId` | DELETE | Delete document |
37
+ | `/api/voice/anchor/derive` | POST | Derive a voice anchor from pasted prose |
38
+ | `/api/voice/anchor` | GET/PUT/DELETE | Read / persist / clear the voice anchor |
39
+ | `/api/voice/usage` | GET | Usage stats |
40
+
41
+ ---
42
+
43
+ ## MCP Protocol (alternative)
44
+
45
+ For MCP-compatible clients, all tools are also available via JSON-RPC POST:
46
+
47
+ ```bash
48
+ curl -s -X POST "https://api.authors-voice.com/api/voice/mcp" \
49
+ -H "Authorization: Bearer $AV_API_KEY" \
50
+ -H "Content-Type: application/json" \
51
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"TOOL_NAME","arguments":{...}}}'
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Available Tools (12)
57
+
58
+ ### Content Import (3 tools)
59
+
60
+ | Tool | Description |
61
+ |------|-------------|
62
+ | `import_from_url` | Import from any public URL (Medium, Substack, WordPress, .md/.txt). Args: `url`, `categories[]`, `authenticity`. |
63
+ | `bulk_import` | Import multiple docs (max 50). Each item: `{url}` or `{content, docId}` + `categories[]`. Global `authenticity`. |
64
+ | `upload_content` | Upload raw markdown. **One-click ergonomics**: `profileId` is optional — omit it and the server auto-creates/resolves a default profile. `content` can be raw text (server chunks on blank lines) instead of pre-split `chunks[]`, so the minimal payload is `{docId, content}`. Re-uploading the same `docId` replaces (idempotent). This is the contract the OpenWriter filetree right-click ingestion posts against. |
65
+
66
+ ### Voice Profiles (3 tools)
67
+
68
+ | Tool | Description |
69
+ |------|-------------|
70
+ | `list_profiles` | List voice profiles, categories, and document counts. Each profile also carries `hasAnchor` (bool) and `anchorAuthors` (the reference authors behind the anchor), so callers can tell which profiles carry an anchor without a per-profile GET. No args. |
71
+ | `get_voice_profile` | Get full voice guidelines — 6 linguistic categories + sentence stats. Use before writing to understand the author's patterns. Optional `profileId`. |
72
+ | `setup_voice` | Analyze samples → create/update voice profile. Args: `profileName`, optional `forceReanalyze`. Call after importing content. |
73
+
74
+ ### Voice Anchor (1 tool)
75
+
76
+ | Tool | Description |
77
+ |------|-------------|
78
+ | `set_voice_anchor` | Derive and persist a voice anchor from pasted reference prose. The anchor is V1's lead voice signal — injected ahead of sample retrieval in `rewrite`/`generate` and the OpenWriter editor path. REST equivalents: `POST /api/voice/anchor/derive`, `GET/PUT/DELETE /api/voice/anchor`. |
79
+
80
+ ### Voice Application (2 tools)
81
+
82
+ | Tool | Description |
83
+ |------|-------------|
84
+ | `rewrite` | Rewrite existing content in the author's voice. Modes: `rewrite`, `shrink`, `expand`, `custom`. Supports `contextBefore`/`contextAfter`, `inputType`, `category`. |
85
+ | `generate` | Generate NEW content in author's voice. Args: `instruction`, optional `query` (topic for retrieval), `contextBefore`/`contextAfter`, `category`, `targetWords`. |
86
+
87
+ **rewrite parameters**: `content`, `mode`, `contextBefore`, `contextAfter`, `category`, `inputType` (human/ai/ai-assisted), `targetWords` (max 2000), `format` (markdown/plaintext).
88
+
89
+ **inputType** controls how aggressively the rewrite treats the input:
90
+ - `human` — Author's own writing. Preserve word choices and quirks, only polish flow/grammar.
91
+ - `ai` — Generic AI content. Discard phrasing entirely, rewrite from scratch using voice samples.
92
+ - `ai-assisted` (default) — Mixed authorship. Preserve passages matching the author's voice, rewrite generic/formulaic parts.
93
+
94
+ **generate note**: `query` is optional — describes what content is ABOUT for better voice retrieval. When omitted, context + instruction are used for retrieval.
95
+
96
+ ### Content Management (3 tools)
97
+
98
+ | Tool | Description |
99
+ |------|-------------|
100
+ | `list_content` | List writing samples with chunk counts. Optional `category` filter. |
101
+ | `update_content` | Retag a doc. Args: `docId`, `categories[]`, `authenticity`. |
102
+ | `delete_content` | Permanently delete a doc and its chunks. Args: `docId`. |
@@ -0,0 +1,7 @@
1
+ # Troubleshooting
2
+
3
+ **"Unauthorized"** — Check `AV_API_KEY` is set and starts with `av_live_`.
4
+
5
+ **"profileId query parameter is required"** — Some REST endpoints need profileId. For MCP tools, omit profileId to use the default profile.
6
+
7
+ **Empty document list** — Connection is active but no documents match. Try without a query filter.