kevlar-4u 1.0.0

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 (238) hide show
  1. package/README.md +357 -0
  2. package/config/mcp-config.json +9 -0
  3. package/dist/__tests__/configureWizard.test.d.ts +2 -0
  4. package/dist/__tests__/configureWizard.test.d.ts.map +1 -0
  5. package/dist/__tests__/configureWizard.test.js +89 -0
  6. package/dist/__tests__/configureWizard.test.js.map +1 -0
  7. package/dist/__tests__/createPersonaTool.test.d.ts +2 -0
  8. package/dist/__tests__/createPersonaTool.test.d.ts.map +1 -0
  9. package/dist/__tests__/createPersonaTool.test.js +292 -0
  10. package/dist/__tests__/createPersonaTool.test.js.map +1 -0
  11. package/dist/__tests__/createPersonaWizard.test.d.ts +2 -0
  12. package/dist/__tests__/createPersonaWizard.test.d.ts.map +1 -0
  13. package/dist/__tests__/createPersonaWizard.test.js +138 -0
  14. package/dist/__tests__/createPersonaWizard.test.js.map +1 -0
  15. package/dist/__tests__/deletePersonaWizard.test.d.ts +2 -0
  16. package/dist/__tests__/deletePersonaWizard.test.d.ts.map +1 -0
  17. package/dist/__tests__/deletePersonaWizard.test.js +78 -0
  18. package/dist/__tests__/deletePersonaWizard.test.js.map +1 -0
  19. package/dist/__tests__/e2e.test.d.ts +2 -0
  20. package/dist/__tests__/e2e.test.d.ts.map +1 -0
  21. package/dist/__tests__/e2e.test.js +121 -0
  22. package/dist/__tests__/e2e.test.js.map +1 -0
  23. package/dist/__tests__/errors.test.d.ts +2 -0
  24. package/dist/__tests__/errors.test.d.ts.map +1 -0
  25. package/dist/__tests__/errors.test.js +86 -0
  26. package/dist/__tests__/errors.test.js.map +1 -0
  27. package/dist/__tests__/execution.test.d.ts +2 -0
  28. package/dist/__tests__/execution.test.d.ts.map +1 -0
  29. package/dist/__tests__/execution.test.js +792 -0
  30. package/dist/__tests__/execution.test.js.map +1 -0
  31. package/dist/__tests__/getModesTool.test.d.ts +2 -0
  32. package/dist/__tests__/getModesTool.test.d.ts.map +1 -0
  33. package/dist/__tests__/getModesTool.test.js +47 -0
  34. package/dist/__tests__/getModesTool.test.js.map +1 -0
  35. package/dist/__tests__/helpTool.test.d.ts +2 -0
  36. package/dist/__tests__/helpTool.test.d.ts.map +1 -0
  37. package/dist/__tests__/helpTool.test.js +18 -0
  38. package/dist/__tests__/helpTool.test.js.map +1 -0
  39. package/dist/__tests__/listPersonasTool.test.d.ts +2 -0
  40. package/dist/__tests__/listPersonasTool.test.d.ts.map +1 -0
  41. package/dist/__tests__/listPersonasTool.test.js +110 -0
  42. package/dist/__tests__/listPersonasTool.test.js.map +1 -0
  43. package/dist/__tests__/logger.test.d.ts +2 -0
  44. package/dist/__tests__/logger.test.d.ts.map +1 -0
  45. package/dist/__tests__/logger.test.js +56 -0
  46. package/dist/__tests__/logger.test.js.map +1 -0
  47. package/dist/__tests__/observability.test.d.ts +2 -0
  48. package/dist/__tests__/observability.test.d.ts.map +1 -0
  49. package/dist/__tests__/observability.test.js +60 -0
  50. package/dist/__tests__/observability.test.js.map +1 -0
  51. package/dist/__tests__/parser.test.d.ts +2 -0
  52. package/dist/__tests__/parser.test.d.ts.map +1 -0
  53. package/dist/__tests__/parser.test.js +259 -0
  54. package/dist/__tests__/parser.test.js.map +1 -0
  55. package/dist/__tests__/persona_creation_debug.test.d.ts +2 -0
  56. package/dist/__tests__/persona_creation_debug.test.d.ts.map +1 -0
  57. package/dist/__tests__/persona_creation_debug.test.js +56 -0
  58. package/dist/__tests__/persona_creation_debug.test.js.map +1 -0
  59. package/dist/__tests__/resetPersonasWizard.test.d.ts +2 -0
  60. package/dist/__tests__/resetPersonasWizard.test.d.ts.map +1 -0
  61. package/dist/__tests__/resetPersonasWizard.test.js +74 -0
  62. package/dist/__tests__/resetPersonasWizard.test.js.map +1 -0
  63. package/dist/__tests__/reviewContentWizard.test.d.ts +2 -0
  64. package/dist/__tests__/reviewContentWizard.test.d.ts.map +1 -0
  65. package/dist/__tests__/reviewContentWizard.test.js +148 -0
  66. package/dist/__tests__/reviewContentWizard.test.js.map +1 -0
  67. package/dist/__tests__/sanitize.test.d.ts +2 -0
  68. package/dist/__tests__/sanitize.test.d.ts.map +1 -0
  69. package/dist/__tests__/sanitize.test.js +138 -0
  70. package/dist/__tests__/sanitize.test.js.map +1 -0
  71. package/dist/__tests__/server.test.d.ts +2 -0
  72. package/dist/__tests__/server.test.d.ts.map +1 -0
  73. package/dist/__tests__/server.test.js +49 -0
  74. package/dist/__tests__/server.test.js.map +1 -0
  75. package/dist/execution/aggregator.d.ts +43 -0
  76. package/dist/execution/aggregator.d.ts.map +1 -0
  77. package/dist/execution/aggregator.js +132 -0
  78. package/dist/execution/aggregator.js.map +1 -0
  79. package/dist/execution/base.d.ts +62 -0
  80. package/dist/execution/base.d.ts.map +1 -0
  81. package/dist/execution/base.js +5 -0
  82. package/dist/execution/base.js.map +1 -0
  83. package/dist/execution/client.d.ts +9 -0
  84. package/dist/execution/client.d.ts.map +1 -0
  85. package/dist/execution/client.js +30 -0
  86. package/dist/execution/client.js.map +1 -0
  87. package/dist/execution/config.d.ts +30 -0
  88. package/dist/execution/config.d.ts.map +1 -0
  89. package/dist/execution/config.js +95 -0
  90. package/dist/execution/config.js.map +1 -0
  91. package/dist/execution/index.d.ts +19 -0
  92. package/dist/execution/index.d.ts.map +1 -0
  93. package/dist/execution/index.js +151 -0
  94. package/dist/execution/index.js.map +1 -0
  95. package/dist/execution/limiter.d.ts +32 -0
  96. package/dist/execution/limiter.d.ts.map +1 -0
  97. package/dist/execution/limiter.js +147 -0
  98. package/dist/execution/limiter.js.map +1 -0
  99. package/dist/execution/lock.d.ts +17 -0
  100. package/dist/execution/lock.d.ts.map +1 -0
  101. package/dist/execution/lock.js +37 -0
  102. package/dist/execution/lock.js.map +1 -0
  103. package/dist/execution/modes/direct_api.d.ts +11 -0
  104. package/dist/execution/modes/direct_api.d.ts.map +1 -0
  105. package/dist/execution/modes/direct_api.js +213 -0
  106. package/dist/execution/modes/direct_api.js.map +1 -0
  107. package/dist/execution/modes/index.d.ts +7 -0
  108. package/dist/execution/modes/index.d.ts.map +1 -0
  109. package/dist/execution/modes/index.js +7 -0
  110. package/dist/execution/modes/index.js.map +1 -0
  111. package/dist/execution/modes/orchestration.d.ts +11 -0
  112. package/dist/execution/modes/orchestration.d.ts.map +1 -0
  113. package/dist/execution/modes/orchestration.js +110 -0
  114. package/dist/execution/modes/orchestration.js.map +1 -0
  115. package/dist/execution/modes/sampling.d.ts +9 -0
  116. package/dist/execution/modes/sampling.d.ts.map +1 -0
  117. package/dist/execution/modes/sampling.js +66 -0
  118. package/dist/execution/modes/sampling.js.map +1 -0
  119. package/dist/execution/parallel.d.ts +16 -0
  120. package/dist/execution/parallel.d.ts.map +1 -0
  121. package/dist/execution/parallel.js +90 -0
  122. package/dist/execution/parallel.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +17 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/prompts/reviewDispatcherPrompt.d.ts +2 -0
  128. package/dist/prompts/reviewDispatcherPrompt.d.ts.map +1 -0
  129. package/dist/prompts/reviewDispatcherPrompt.js +67 -0
  130. package/dist/prompts/reviewDispatcherPrompt.js.map +1 -0
  131. package/dist/server.d.ts +3 -0
  132. package/dist/server.d.ts.map +1 -0
  133. package/dist/server.js +156 -0
  134. package/dist/server.js.map +1 -0
  135. package/dist/tools/configureTool.d.ts +17 -0
  136. package/dist/tools/configureTool.d.ts.map +1 -0
  137. package/dist/tools/configureTool.js +104 -0
  138. package/dist/tools/configureTool.js.map +1 -0
  139. package/dist/tools/configureWizardTool.d.ts +11 -0
  140. package/dist/tools/configureWizardTool.d.ts.map +1 -0
  141. package/dist/tools/configureWizardTool.js +205 -0
  142. package/dist/tools/configureWizardTool.js.map +1 -0
  143. package/dist/tools/createPersonaTool.d.ts +37 -0
  144. package/dist/tools/createPersonaTool.d.ts.map +1 -0
  145. package/dist/tools/createPersonaTool.js +353 -0
  146. package/dist/tools/createPersonaTool.js.map +1 -0
  147. package/dist/tools/createPersonaWizardTool.d.ts +13 -0
  148. package/dist/tools/createPersonaWizardTool.d.ts.map +1 -0
  149. package/dist/tools/createPersonaWizardTool.js +713 -0
  150. package/dist/tools/createPersonaWizardTool.js.map +1 -0
  151. package/dist/tools/deletePersonaTool.d.ts +10 -0
  152. package/dist/tools/deletePersonaTool.d.ts.map +1 -0
  153. package/dist/tools/deletePersonaTool.js +75 -0
  154. package/dist/tools/deletePersonaTool.js.map +1 -0
  155. package/dist/tools/deletePersonaWizardTool.d.ts +11 -0
  156. package/dist/tools/deletePersonaWizardTool.d.ts.map +1 -0
  157. package/dist/tools/deletePersonaWizardTool.js +184 -0
  158. package/dist/tools/deletePersonaWizardTool.js.map +1 -0
  159. package/dist/tools/getModesTool.d.ts +12 -0
  160. package/dist/tools/getModesTool.d.ts.map +1 -0
  161. package/dist/tools/getModesTool.js +78 -0
  162. package/dist/tools/getModesTool.js.map +1 -0
  163. package/dist/tools/helpTool.d.ts +7 -0
  164. package/dist/tools/helpTool.d.ts.map +1 -0
  165. package/dist/tools/helpTool.js +65 -0
  166. package/dist/tools/helpTool.js.map +1 -0
  167. package/dist/tools/index.d.ts +9 -0
  168. package/dist/tools/index.d.ts.map +1 -0
  169. package/dist/tools/index.js +30 -0
  170. package/dist/tools/index.js.map +1 -0
  171. package/dist/tools/listPersonasTool.d.ts +7 -0
  172. package/dist/tools/listPersonasTool.d.ts.map +1 -0
  173. package/dist/tools/listPersonasTool.js +118 -0
  174. package/dist/tools/listPersonasTool.js.map +1 -0
  175. package/dist/tools/resetPersonasTool.d.ts +7 -0
  176. package/dist/tools/resetPersonasTool.d.ts.map +1 -0
  177. package/dist/tools/resetPersonasTool.js +447 -0
  178. package/dist/tools/resetPersonasTool.js.map +1 -0
  179. package/dist/tools/resetPersonasWizardTool.d.ts +9 -0
  180. package/dist/tools/resetPersonasWizardTool.d.ts.map +1 -0
  181. package/dist/tools/resetPersonasWizardTool.js +125 -0
  182. package/dist/tools/resetPersonasWizardTool.js.map +1 -0
  183. package/dist/tools/reviewContentWizardTool.d.ts +13 -0
  184. package/dist/tools/reviewContentWizardTool.d.ts.map +1 -0
  185. package/dist/tools/reviewContentWizardTool.js +411 -0
  186. package/dist/tools/reviewContentWizardTool.js.map +1 -0
  187. package/dist/tools/reviewTool.d.ts +10 -0
  188. package/dist/tools/reviewTool.d.ts.map +1 -0
  189. package/dist/tools/reviewTool.js +133 -0
  190. package/dist/tools/reviewTool.js.map +1 -0
  191. package/dist/tools/types.d.ts +14 -0
  192. package/dist/tools/types.d.ts.map +1 -0
  193. package/dist/tools/types.js +2 -0
  194. package/dist/tools/types.js.map +1 -0
  195. package/dist/utils/errors.d.ts +30 -0
  196. package/dist/utils/errors.d.ts.map +1 -0
  197. package/dist/utils/errors.js +47 -0
  198. package/dist/utils/errors.js.map +1 -0
  199. package/dist/utils/logger.d.ts +18 -0
  200. package/dist/utils/logger.d.ts.map +1 -0
  201. package/dist/utils/logger.js +52 -0
  202. package/dist/utils/logger.js.map +1 -0
  203. package/dist/utils/observability.d.ts +61 -0
  204. package/dist/utils/observability.d.ts.map +1 -0
  205. package/dist/utils/observability.js +69 -0
  206. package/dist/utils/observability.js.map +1 -0
  207. package/dist/utils/parser.d.ts +27 -0
  208. package/dist/utils/parser.d.ts.map +1 -0
  209. package/dist/utils/parser.js +178 -0
  210. package/dist/utils/parser.js.map +1 -0
  211. package/dist/utils/personaIdMaps.d.ts +7 -0
  212. package/dist/utils/personaIdMaps.d.ts.map +1 -0
  213. package/dist/utils/personaIdMaps.js +51 -0
  214. package/dist/utils/personaIdMaps.js.map +1 -0
  215. package/dist/utils/sanitize.d.ts +4 -0
  216. package/dist/utils/sanitize.d.ts.map +1 -0
  217. package/dist/utils/sanitize.js +49 -0
  218. package/dist/utils/sanitize.js.map +1 -0
  219. package/dist/utils/types.d.ts +8 -0
  220. package/dist/utils/types.d.ts.map +1 -0
  221. package/dist/utils/types.js +2 -0
  222. package/dist/utils/types.js.map +1 -0
  223. package/package.json +42 -0
  224. package/skills/_template.md +66 -0
  225. package/skills/tmp/wizard-create-cwzrrpim_draft.json +26 -0
  226. package/skills/tmp/wizard-create-cwzrrpim_wizard.json +26 -0
  227. package/skills/tmp/wizard-create-d81intme_draft.json +26 -0
  228. package/skills/tmp/wizard-create-d81intme_wizard.json +26 -0
  229. package/skills/tmp/wizard-create-g50jqzmh_draft.json +8 -0
  230. package/skills/tmp/wizard-create-g50jqzmh_wizard.json +8 -0
  231. package/skills/tmp/wizard-create-onupu9wb_draft.json +8 -0
  232. package/skills/tmp/wizard-create-onupu9wb_wizard.json +8 -0
  233. package/skills/tmp/wizard-review-fwbxe3d2_review_wizard.json +9 -0
  234. package/skills/tmp/wizard-review-sypg5e9d_review_wizard.json +9 -0
  235. package/skills/wechat_official/wechat_official.md +26 -0
  236. package/skills/wechat_official/wechat_official_1.md +31 -0
  237. package/skills/xiaohongshu/xiaohongshu.md +26 -0
  238. package/skills/xiaohongshu/xiaohongshu_1.md +29 -0
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # Kevlar — Feedback Simulator Before You Hit Publish
2
+
3
+ ![Release](https://img.shields.io/github/actions/workflow/status/9Churze/Kevlar-MCP/release.yml?label=Release&logo=github)
4
+ ![License](https://img.shields.io/badge/license-ISC-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.0.0-blue)
6
+ ![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen)
7
+
8
+ 🌐 [English](README.md) · [中文](docs/README.zh.md) · [日本語](docs/README.ja.md) · [한국어](docs/README.ko.md)
9
+
10
+ ---
11
+
12
+ > **It simulates real reactions from different audiences — casual users, picky netizens, technical users, media perspectives — helping you spot expression issues, misunderstandings, and communication risks before you publish.**
13
+
14
+ ---
15
+
16
+ Drop any content you're about to publish — **articles, tweets, video scripts, product intros, press releases, announcements, Reddit posts, V2EX posts, Hacker News headlines** — directly into Kevlar. It won't just say "looks good." Instead, it'll **question, misinterpret, roast, nitpick, and comprehension-test** your content, just like the real internet.
17
+
18
+ Writers often suffer from the **"curse of knowledge"**:
19
+ You think you've made it clear, but others don't get it.
20
+ You think the key point stands out, but readers can't tell what you're trying to say.
21
+
22
+ And most platforms don't offer a real **A/B test**. Once content goes live, by the time the **first wave of organic traffic** passes, it's usually too late to revise.
23
+
24
+ **Kevlar helps you surface these problems before you hit publish.**
25
+
26
+ ## Who needs Kevlar
27
+
28
+ **Indie developers** / **Content creators** / **Product teams** / **PR teams** / Heavy users of X, Reddit, V2EX, Hacker News / Anyone who wants to improve content quality and reach
29
+
30
+ ---
31
+
32
+ ## Core Features
33
+
34
+ ### 1. Highly Customizable Virtual Commentators (Persona Customization)
35
+
36
+ Break out of the single-AI perspective with comprehensive persona customization:
37
+
38
+ - **Core attributes**: Age, interests, personality, stance.
39
+ - **Cognition & relationship**: Define blind spots (e.g., domain-specific biases) and social relationship with the author (e.g., a strict mentor, a radical opponent).
40
+ - **Cultural adaptation**: The system automatically detects the language of input content and infers a matching localized cultural context.
41
+
42
+ ### 2. Fully Automated Feedback Pipeline
43
+
44
+ - **Smart dispatch**: Paste your work and the AI dispatcher automatically analyzes the content's characteristics.
45
+ - **Precise matching**: Dynamically filters and schedules the most relevant virtual commentators.
46
+ - **Multi-dimensional collision**: Triggers differentiated comments and feedback from diverse stances and professional perspectives.
47
+
48
+ ---
49
+
50
+ ## Quick Start
51
+
52
+ Requires **Node.js 20+**.
53
+
54
+ ```bash
55
+ npm install # Install dependencies
56
+ npm run build # Compile TypeScript
57
+ npm run setup # Zero-config setup (auto-detect MCP client and write config)
58
+ npm run kevlar-mcp # Interactive install CLI (manually select client)
59
+ ```
60
+
61
+ Once installed, restart your AI client to start using Kevlar. Supports auto-configuration for:
62
+
63
+ **Claude Desktop** / **Cursor** / **Windsurf** / **OpenCode** / **Codex** / **Antigravity** / **CodeBuddy CN** / **WorkBuddy**
64
+
65
+ Local development:
66
+
67
+ ```bash
68
+ npm run dev
69
+ ```
70
+
71
+ Production start:
72
+
73
+ ```bash
74
+ npm start
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Usage Guide
80
+
81
+ ### Core Workflow
82
+
83
+ All core operations in Kevlar are handled through Wizard tools — just tell the AI what you want in natural language, and Kevlar takes care of the rest.
84
+
85
+ ### Recommended Tool Flow
86
+
87
+ | Wizard Tool | Purpose | Key Behavior |
88
+ | --- | --- | --- |
89
+ | `review_content_wizard` | Review content | Submit content → Select platform → Pick commentators → Confirm → Multi-dimensional feedback |
90
+ | `create_persona_wizard` | Create a persona | Describe the role → Fill 6 attributes (age/interests/traits/tone/platform/relation) → Preview → Confirm → Save persona |
91
+ | `delete_persona_wizard` | Delete a persona | Select target → Reply `确认删除{persona name}` → Done |
92
+ | `configure_wizard` | Modify config | Preview changes → Reply `确认修改配置` → Write |
93
+
94
+ Low-level direct tools (suitable for automation scripts):
95
+
96
+ | Tool | Purpose |
97
+ | --- | --- |
98
+ | `delete_persona` | Delete persona directly (requires `confirm: true`) |
99
+ | `configure` | Write config directly |
100
+ | `get_execution_modes` | Check current mode and availability |
101
+ | `list_personas` | List local personas |
102
+ | `kevlar_help` | View help |
103
+
104
+ ### Content Review Flow
105
+
106
+ `review_content_wizard` chains "save content, select commentators, confirm execution" into a stable flow.
107
+
108
+ ```mermaid
109
+ flowchart TD
110
+ A["Submit content for review"] --> B{"Any personas?"}
111
+ B -->|No| C["Prompt to create persona, save state"]
112
+ C -.->|"Same sessionId"| B
113
+ B -->|Yes| D["Collect target platform"]
114
+ D --> E["Filter personas by platform"]
115
+ E --> F{"Count matched"}
116
+ F -->|"≤2"| G["Show matched personas"]
117
+ F -->|"3+"| H["AI recommend 1-3 personas"]
118
+ G --> I["Confirm selection"]
119
+ H --> I
120
+ I --> J["Token cost estimate"]
121
+ J --> K{"Confirm?"}
122
+ K -->|Yes| L["Execute review"]
123
+ K -->|No| I
124
+ ```
125
+
126
+ ### Creating a Commentator Persona
127
+
128
+ `create_persona_wizard` guides you through persona creation step by step.
129
+
130
+ ```mermaid
131
+ flowchart LR
132
+ A["Age range"] --> B["Interests"]
133
+ B --> C["Personality traits"]
134
+ C --> D["Tone of voice"]
135
+ D --> E["Platforms"]
136
+ E --> F["Author relation"]
137
+ F --> G["Final confirmation & preview"]
138
+ G -->|Confirm| H["Save persona"]
139
+ G -->|Edit| G
140
+ ```
141
+
142
+ After creation, Kevlar automatically infers the cultural background, relationship with author, stance, and blind spots, saving them to `skills/*.md`.
143
+
144
+ ---
145
+
146
+ ## Execution Modes
147
+
148
+ Kevlar supports three execution modes. The default `auto` selects the best mode based on your environment.
149
+
150
+ | Mode | Identifier | Description | Best for |
151
+ | --- | --- | --- | --- |
152
+ | MCP Sampling | `mcp_sampling` | Each commentator gets an independent sampling request, maximum isolation | Clients that support Sampling, pursuing authentic multi-perspective review |
153
+ | Direct API | `direct_api` | Directly calls external model API | Clients without Sampling, or script automation |
154
+ | Orchestration (Host-assisted fallback) | `orchestration` | Host AI assists completion, low-isolation fallback | Last resort when neither Sampling nor API Key is available |
155
+
156
+ `auto` mode resolution order:
157
+
158
+ 1. Uses the mode specified in `skills/kevlar-config.json` (if set)
159
+ 2. Otherwise reads the `KEVLAR_MODE` environment variable
160
+ 3. Otherwise auto-selects by availability: `mcp_sampling` → `direct_api` → `orchestration`
161
+
162
+ ---
163
+
164
+ ## Configuration
165
+
166
+ ### Runtime Configuration
167
+
168
+ Use `configure_wizard` to modify runtime preferences. Configuration is written to `skills/kevlar-config.json` (local only, not committed to the repository).
169
+
170
+ ```json
171
+ {
172
+ "mode": "auto",
173
+ "multiAgent": {
174
+ "maxConcurrency": 3
175
+ }
176
+ }
177
+ ```
178
+
179
+ ### Environment Variables
180
+
181
+ | Variable | Default | Description |
182
+ | --- | --- | --- |
183
+ | `KEVLAR_MODE` | `auto` | `auto`, `orchestration`, `mcp_sampling`, `direct_api` |
184
+ | `KEVLAR_MAX_CONCURRENT` | `3` | Max concurrent commentators |
185
+ | `KEVLAR_TOKEN_BUDGET_PER_TASK` | `50000` | Token budget per review task |
186
+ | `KEVLAR_MIN_DELAY_MS` | `1000` | Minimum delay between requests |
187
+ | `KEVLAR_SKILLS_DIR` | `<repo>/skills` | Custom persona and config directory |
188
+ | `KEVLAR_API_KEY` | — | Preferred Direct API key |
189
+ | `ANTHROPIC_API_KEY` | — | Anthropic API key |
190
+ | `OPENAI_API_KEY` | — | OpenAI API key |
191
+ | `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` |
192
+
193
+ > API keys are read from environment variables only — they are never written to config files.
194
+
195
+ ### Manual MCP Client Configuration
196
+
197
+ Claude Desktop example:
198
+
199
+ ```json
200
+ {
201
+ "mcpServers": {
202
+ "kevlar": {
203
+ "command": "node",
204
+ "args": ["/ABSOLUTE/PATH/TO/kevlar/dist/index.js"],
205
+ "env": {
206
+ "KEVLAR_MODE": "auto",
207
+ "KEVLAR_MAX_CONCURRENT": "3"
208
+ }
209
+ }
210
+ }
211
+ }
212
+ ```
213
+
214
+ Custom persona directory:
215
+
216
+ ```json
217
+ {
218
+ "env": {
219
+ "KEVLAR_SKILLS_DIR": "/ABSOLUTE/PATH/TO/skills"
220
+ }
221
+ }
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Security Boundaries
227
+
228
+ - `sessionId` only allows `[a-z0-9-]`.
229
+ - Persona write and delete operations are restricted to the `skills/` directory via path validation.
230
+ - Runtime drafts and wizard states are stored in `skills/tmp/`, with expired drafts cleaned up on startup.
231
+ - Deleting a persona requires selecting a target and replying with the full confirmation phrase.
232
+ - Config changes require preview before confirmation.
233
+ - API keys are never passed via tool parameters or written to local config.
234
+ - Non-`orchestration` modes use a review lock to prevent resource contention between multiple external model tasks.
235
+
236
+ ---
237
+
238
+ ## Architecture Overview
239
+
240
+ Kevlar uses a **Server-side Workflow + Execution Layer** architecture.
241
+
242
+ ```mermaid
243
+ flowchart TD
244
+ User["User"] --> Client["MCP Client / Host AI"]
245
+ Client --> Tools["Kevlar MCP Tools"]
246
+ Tools --> Wizards["Server-side State Machine Wizards"]
247
+ Tools --> Execution["Multi-mode Execution Layer"]
248
+ Wizards --> Tmp["skills/tmp Session State"]
249
+ Execution --> Personas["skills/*.md Commentator Personas"]
250
+ Execution --> Report["Structured Review Report"]
251
+ ```
252
+
253
+ Design principles:
254
+
255
+ - **State machine-driven workflows**: Key flows are maintained by tool state machines, not dependent on the host AI remembering long prompts.
256
+ - **AI handles understanding & expression**: AI handles natural language extraction, refinement, and recommendations, while results are written to Kevlar-verifiable state.
257
+ - **Adaptive execution**: When MCP Sampling is available, use it for field extraction and commentator recommendations; otherwise, fall back to heuristic logic or host-assisted orchestration.
258
+ - **Safe confirmation**: High-risk operations like deletion, reset, and config writes all go through confirmation wizards.
259
+
260
+ ### Directory Structure
261
+
262
+ ```text
263
+ kevlar/
264
+ ├── config/
265
+ │ └── mcp-config.json # MCP client config template
266
+ ├── docs/ # Architecture design, audit reports
267
+ ├── scripts/ # Install & config scripts
268
+ │ ├── cli.ts # Interactive install CLI
269
+ │ ├── registry.ts # MCP client detection
270
+ │ └── setup.ts # Zero-config setup script
271
+ ├── skills/ # Commentator persona library
272
+ │ ├── _template.md # Persona template
273
+ │ └── tmp/ # Runtime wizard session state
274
+ ├── src/
275
+ │ ├── index.ts # stdio server entry
276
+ │ ├── server.ts # MCP server, DI, tool registration
277
+ │ ├── __tests__/ # Test suite
278
+ │ ├── execution/ # Multi-mode execution layer
279
+ │ │ ├── index.ts # Execution entry, mode resolution
280
+ │ │ ├── base.ts # Type definitions & interfaces
281
+ │ │ ├── client.ts # Client capability detection
282
+ │ │ ├── config.ts # Config read/write
283
+ │ │ ├── aggregator.ts # Review report aggregation
284
+ │ │ ├── limiter.ts # Concurrency limiting & retry
285
+ │ │ ├── lock.ts # Review lock
286
+ │ │ ├── parallel.ts # Shared parallel execution
287
+ │ │ └── modes/
288
+ │ │ ├── orchestration.ts
289
+ │ │ ├── sampling.ts
290
+ │ │ └── direct_api.ts
291
+ │ ├── tools/ # MCP tools
292
+ │ │ ├── index.ts # Tool registry
293
+ │ │ ├── listPersonasTool.ts
294
+ │ │ ├── createPersonaTool.ts # Create persona + draft management
295
+ │ │ ├── createPersonaWizardTool.ts
296
+ │ │ ├── deletePersonaTool.ts
297
+ │ │ ├── deletePersonaWizardTool.ts
298
+ │ │ ├── reviewTool.ts
299
+ │ │ ├── reviewContentWizardTool.ts
300
+ │ │ ├── configureTool.ts
301
+ │ │ ├── configureWizardTool.ts
302
+ │ │ ├── getModesTool.ts
303
+ │ │ └── helpTool.ts
304
+ │ ├── prompts/
305
+ │ │ └── reviewDispatcherPrompt.ts # Internal design reference
306
+ │ └── utils/
307
+ │ ├── errors.ts # Error codes & formatting
308
+ │ ├── logger.ts # Structured logging
309
+ │ ├── parser.ts # Persona file parsing & writing
310
+ │ ├── sanitize.ts # Credential scanning, prompt boundary handling
311
+ │ └── ...
312
+ └── package.json
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Contributing Commentator Personas
318
+
319
+ Add a subdirectory and `.md` file under `skills/` by platform (or place it directly in the `skills/` root). Custom persona files are excluded by `.gitignore` by default and will not be committed to the repository.
320
+
321
+ Refer to the template `skills/_template.md`:
322
+
323
+ ```markdown
324
+ ---
325
+ id: your_persona_id
326
+ name: Display name
327
+ description: One-line description of what this commentator focuses on
328
+ tags:
329
+ - Platform
330
+ - Interest
331
+ author: custom
332
+ ---
333
+
334
+ Age range:
335
+ Interests:
336
+ Platforms:
337
+ Personality traits:
338
+ - Trait → Behavior
339
+
340
+ Cultural background:
341
+ Relationship with author:
342
+ Stance:
343
+ Blind spots:
344
+ ```
345
+
346
+ Custom personas undergo field completeness validation before participating in reviews. At minimum, platforms, personality traits, blind spots, and similar information must be parseable or present in the description.
347
+
348
+ ---
349
+
350
+ ## Pre-Release Checklist
351
+
352
+ ```bash
353
+ npm run build
354
+ npm test
355
+ ```
356
+
357
+ Before release, it is recommended to hand [docs/PRE_RELEASE_AUDIT_REQUEST.md](docs/PRE_RELEASE_AUDIT_REQUEST.md) to your local AI for an independent audit.
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "kevlar": {
4
+ "command": "node",
5
+ "args": ["/Users/churze/Documents/MCP-Service/kevlar/dist/index.js"],
6
+ "env": {}
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=configureWizard.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configureWizard.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/configureWizard.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ import { describe, it, beforeEach, afterEach } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import * as fs from "fs";
4
+ import * as os from "os";
5
+ import * as path from "path";
6
+ import { setConfigPath, readConfig } from "../execution/config.js";
7
+ import { handleConfigureWizard } from "../tools/configureWizardTool.js";
8
+ import { handleConfigure } from "../tools/configureTool.js";
9
+ let skillsDir;
10
+ let tmpDir;
11
+ beforeEach(() => {
12
+ skillsDir = fs.mkdtempSync(path.join(os.tmpdir(), "kevlar-config-wizard-"));
13
+ tmpDir = path.join(skillsDir, "tmp");
14
+ setConfigPath(skillsDir);
15
+ });
16
+ afterEach(() => {
17
+ fs.rmSync(skillsDir, { recursive: true, force: true });
18
+ });
19
+ function textOf(result) {
20
+ return result.content.map((c) => c.text).join("\n");
21
+ }
22
+ function extractSessionId(text) {
23
+ const match = text.match(/sessionId:\s*([a-z0-9-]+)/);
24
+ assert.ok(match, `expected sessionId in response: ${text}`);
25
+ return match[1];
26
+ }
27
+ describe("handleConfigureWizard", () => {
28
+ it("previews config changes without writing until confirmation", async () => {
29
+ const result = await handleConfigureWizard(tmpDir, {
30
+ userMessage: "切换到 direct api,并发 4",
31
+ });
32
+ const text = textOf(result);
33
+ assert.ok(text.includes("准备修改配置"));
34
+ assert.ok(text.includes("执行模式:直接 API 模式"));
35
+ assert.ok(text.includes("并发数:4"));
36
+ assert.ok(text.includes("currentStep: confirmConfigure"));
37
+ const config = readConfig();
38
+ assert.equal(config.mode, "auto");
39
+ assert.equal(config.multiAgent.maxConcurrency, 3);
40
+ });
41
+ it("writes config only after exact confirmation phrase", async () => {
42
+ const started = await handleConfigureWizard(tmpDir, {
43
+ userMessage: "切换到 mcp sampling,并发 5",
44
+ });
45
+ const sessionId = extractSessionId(textOf(started));
46
+ const wrong = await handleConfigureWizard(tmpDir, {
47
+ sessionId,
48
+ userMessage: "确认",
49
+ });
50
+ assert.ok(textOf(wrong).includes("请回复完整确认语"));
51
+ assert.equal(readConfig().mode, "auto");
52
+ const applied = await handleConfigureWizard(tmpDir, {
53
+ sessionId,
54
+ userMessage: "确认修改配置",
55
+ });
56
+ assert.ok(textOf(applied).includes("配置已更新"));
57
+ assert.equal(readConfig().mode, "mcp_sampling");
58
+ assert.equal(readConfig().multiAgent.maxConcurrency, 5);
59
+ });
60
+ });
61
+ describe("handleConfigure (direct tool)", () => {
62
+ it("rejects invalid mode", async () => {
63
+ const result = await handleConfigure({ mode: "invalid_mode" });
64
+ assert.ok(result.isError);
65
+ assert.ok(result.content[0]?.text.includes("无效的执行模式"));
66
+ });
67
+ it("rejects invalid concurrency out of range", async () => {
68
+ const resultLow = await handleConfigure({ maxConcurrency: 0 });
69
+ assert.ok(resultLow.isError);
70
+ assert.ok(resultLow.content[0]?.text.includes("并发数必须在 1-10"));
71
+ const resultHigh = await handleConfigure({ maxConcurrency: 11 });
72
+ assert.ok(resultHigh.isError);
73
+ assert.ok(resultHigh.content[0]?.text.includes("并发数必须在 1-10"));
74
+ });
75
+ it("writes mode and preserves existing config", async () => {
76
+ await handleConfigure({ mode: "orchestration" });
77
+ assert.equal(readConfig().mode, "orchestration");
78
+ // Partial update preserves previous value
79
+ await handleConfigure({ maxConcurrency: 7 });
80
+ assert.equal(readConfig().mode, "orchestration");
81
+ assert.equal(readConfig().multiAgent.maxConcurrency, 7);
82
+ });
83
+ it("returns success message for valid config", async () => {
84
+ const result = await handleConfigure({ mode: "mcp_sampling", maxConcurrency: 5 });
85
+ assert.ok(!result.isError);
86
+ assert.ok(result.content[0]?.text.includes("配置已更新"));
87
+ });
88
+ });
89
+ //# sourceMappingURL=configureWizard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configureWizard.test.js","sourceRoot":"","sources":["../../src/__tests__/configureWizard.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createPersonaTool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPersonaTool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/createPersonaTool.test.ts"],"names":[],"mappings":""}