@gethmy/mcp 2.3.1 → 2.3.3

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 (34) hide show
  1. package/dist/lib/api-client.js +2099 -648
  2. package/dist/lib/config.js +217 -201
  3. package/package.json +9 -5
  4. package/src/memory-cleanup.ts +2 -4
  5. package/dist/lib/__tests__/active-learning.test.js +0 -386
  6. package/dist/lib/__tests__/agent-performance-profiles.test.js +0 -325
  7. package/dist/lib/__tests__/auto-session.test.js +0 -661
  8. package/dist/lib/__tests__/context-assembly.test.js +0 -362
  9. package/dist/lib/__tests__/graph-expansion.test.js +0 -150
  10. package/dist/lib/__tests__/integration-memory-crud.test.js +0 -797
  11. package/dist/lib/__tests__/integration-memory-system.test.js +0 -281
  12. package/dist/lib/__tests__/lifecycle-maintenance.test.js +0 -207
  13. package/dist/lib/__tests__/pattern-detection.test.js +0 -295
  14. package/dist/lib/__tests__/prompt-builder.test.js +0 -418
  15. package/dist/lib/active-learning.js +0 -822
  16. package/dist/lib/auto-session.js +0 -214
  17. package/dist/lib/cli.js +0 -138
  18. package/dist/lib/consolidation.js +0 -303
  19. package/dist/lib/context-assembly.js +0 -884
  20. package/dist/lib/graph-expansion.js +0 -163
  21. package/dist/lib/http.js +0 -175
  22. package/dist/lib/index.js +0 -7
  23. package/dist/lib/lifecycle-maintenance.js +0 -88
  24. package/dist/lib/memory-cleanup.js +0 -455
  25. package/dist/lib/onboard.js +0 -36
  26. package/dist/lib/prompt-builder.js +0 -488
  27. package/dist/lib/remote.js +0 -166
  28. package/dist/lib/server.js +0 -3365
  29. package/dist/lib/skills.js +0 -593
  30. package/dist/lib/tui/agents.js +0 -116
  31. package/dist/lib/tui/docs.js +0 -744
  32. package/dist/lib/tui/setup.js +0 -934
  33. package/dist/lib/tui/theme.js +0 -95
  34. package/dist/lib/tui/writer.js +0 -200
@@ -1,593 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { dirname } from "node:path";
3
- import { areSkillsInstalled } from "./config.js";
4
- export const SKILLS_VERSION = "4";
5
- const VERSION_MARKER_PREFIX = "<!-- skills-version:";
6
- /**
7
- * Legacy workflow prompt used by Codex, Cursor agents.
8
- * Claude Code skills use the newer SKILL_DEFINITIONS content instead.
9
- */
10
- export const HARMONY_WORKFLOW_PROMPT = `# Harmony Card Workflow
11
-
12
- Start work on a Harmony card. Card reference: $ARGUMENTS
13
-
14
- ## 1. Find & Fetch Card
15
-
16
- Parse the reference and fetch the card:
17
- - \`#42\` or \`42\` → \`harmony_get_card_by_short_id\` with \`shortId: 42\`
18
- - UUID → \`harmony_get_card\` with \`cardId\`
19
- - Name/text → \`harmony_search_cards\` with \`query\`
20
-
21
- ## 2. Get Board State
22
-
23
- Call \`harmony_get_board\` to get columns and labels. From the response:
24
- - Find the "In Progress" (or "Progress") column ID
25
- - Find the "agent" label ID
26
-
27
- ## 3. Setup Card for Work
28
-
29
- Execute these in sequence:
30
- 1. \`harmony_move_card\` → Move to "In Progress" column
31
- 2. \`harmony_add_label_to_card\` → Add "agent" label
32
- 3. \`harmony_start_agent_session\`:
33
- - \`cardId\`: Card UUID
34
- - \`agentIdentifier\`: Your agent identifier
35
- - \`agentName\`: Your agent name
36
- - \`currentTask\`: "Analyzing card requirements"
37
-
38
- ## 4. Generate Work Prompt
39
-
40
- Call \`harmony_generate_prompt\` with:
41
- - \`cardId\` or \`shortId\` (+ \`projectId\` if using shortId)
42
- - \`variant\`: Select based on task:
43
- - \`"execute"\` (default) → Clear tasks, bug fixes, well-defined work
44
- - \`"analysis"\` → Complex features, unclear requirements
45
- - \`"draft"\` → Medium complexity, want feedback first
46
-
47
- The generated prompt provides role framing, focus areas, subtasks, linked cards, and suggested outputs.
48
-
49
- ## 5. Display Card Summary
50
-
51
- Show the user: Card title, short ID, role, priority, labels, due date, description, and subtasks.
52
-
53
- ## 6. Implement Solution
54
-
55
- Work on the card following the generated prompt's guidance. Update progress at milestones:
56
- - \`harmony_update_agent_progress\` with \`progressPercent\` (0-100), \`currentTask\`, \`status\`, \`blockers\`
57
-
58
- **Progress checkpoints:** 20% (exploration), 50% (implementation), 80% (testing), 100% (done)
59
-
60
- ## 7. Complete Work
61
-
62
- When finished:
63
- 1. \`harmony_end_agent_session\` with \`status: "completed"\`, \`progressPercent: 100\`
64
- 2. \`harmony_move_card\` to "Review" column
65
- 3. Summarize accomplishments
66
-
67
- If pausing: \`harmony_end_agent_session\` with \`status: "paused"\`
68
-
69
- ## Key Tools Reference
70
-
71
- **Cards:** \`harmony_get_card\`, \`harmony_get_card_by_short_id\`, \`harmony_search_cards\`, \`harmony_create_card\`, \`harmony_update_card\`, \`harmony_move_card\`, \`harmony_delete_card\`, \`harmony_assign_card\`
72
-
73
- **Subtasks:** \`harmony_create_subtask\`, \`harmony_toggle_subtask\`, \`harmony_delete_subtask\`
74
-
75
- **Labels:** \`harmony_add_label_to_card\`, \`harmony_remove_label_from_card\`, \`harmony_create_label\`
76
-
77
- **Links:** \`harmony_add_link_to_card\`, \`harmony_remove_link_from_card\`, \`harmony_get_card_links\`
78
-
79
- **Board:** \`harmony_get_board\`, \`harmony_list_projects\`, \`harmony_get_context\`, \`harmony_set_project_context\`
80
-
81
- **Sessions:** \`harmony_start_agent_session\`, \`harmony_update_agent_progress\`, \`harmony_end_agent_session\`, \`harmony_get_agent_session\`
82
-
83
- **AI:** \`harmony_generate_prompt\`, \`harmony_process_command\`
84
- `;
85
- /**
86
- * New Claude Code skill content with intent detection.
87
- */
88
- const HMY_SKILL_CONTENT = `# Harmony Card Workflow
89
-
90
- User input: $ARGUMENTS
91
-
92
- ## 0. Detect Intent
93
-
94
- Parse \`$ARGUMENTS\` to determine what the user wants:
95
-
96
- | Pattern | Intent | Go to |
97
- |---|---|---|
98
- | \`create ...\` or \`new ...\` | **Create** a new card | Step A |
99
- | \`#42\`, \`42\`, UUID, or card name (no action verb) | **Work on** an existing card | Step B |
100
- | \`move #42 to Done\`, \`update #42 ...\`, \`assign #42 ...\` | **Quick action** on a card | Step C |
101
- | \`show #42\`, \`view #42\`, \`status #42\` | **View** card details | Step D |
102
-
103
- If ambiguous, ask the user what they'd like to do.
104
-
105
- ---
106
-
107
- ## Step A: Create Card
108
-
109
- Create a card without starting work on it.
110
-
111
- 1. Parse the title and any details from the arguments (e.g., \`create Add dark mode toggle\` → title: "Add dark mode toggle")
112
- 2. Call \`harmony_create_card\` with:
113
- - \`title\`: extracted title
114
- - \`description\`: if the user provided details beyond the title
115
- - \`priority\`, \`columnId\`, \`assigneeId\`: only if explicitly specified
116
- 3. Show the created card: title, short ID, column, and a link if available.
117
- 4. **Stop here.** Do not start an agent session or begin implementation.
118
-
119
- ---
120
-
121
- ## Step B: Work on Existing Card
122
-
123
- Start work on a Harmony card.
124
-
125
- ### B1. Find & Fetch Card
126
-
127
- Parse the reference and fetch the card:
128
- - \`#42\` or \`42\` → \`harmony_get_card_by_short_id\` with \`shortId: 42\`
129
- - UUID → \`harmony_get_card\` with \`cardId\`
130
- - Name/text → \`harmony_search_cards\` with \`query\`
131
-
132
- ### B2. Start Agent Session
133
-
134
- Call \`harmony_start_agent_session\` with:
135
- - \`cardId\`: Card UUID
136
- - \`agentIdentifier\`: Your agent identifier
137
- - \`agentName\`: Your agent name
138
- - \`currentTask\`: A specific description of the first thing you'll do (e.g., "Exploring codebase to understand auth flow"), NOT a generic phrase like "Analyzing card requirements"
139
- - \`moveToColumn\`: "In Progress"
140
- - \`addLabels\`: ["agent"]
141
-
142
- This single call moves the card, adds the label, auto-assigns, and starts the session.
143
-
144
- ### B3. Generate Work Prompt
145
-
146
- Call \`harmony_generate_prompt\` with:
147
- - \`cardId\` or \`shortId\` (+ \`projectId\` if using shortId)
148
- - \`variant\`: Select based on task:
149
- - \`"execute"\` (default) → Clear tasks, bug fixes, well-defined work
150
- - \`"analysis"\` → Complex features, unclear requirements
151
- - \`"draft"\` → Medium complexity, want feedback first
152
-
153
- The generated prompt provides role framing, focus areas, subtasks, linked cards, and suggested outputs.
154
-
155
- ### B4. Display Card Summary
156
-
157
- Show the user: Card title, short ID, role, priority, labels, due date, description, and subtasks.
158
-
159
- ### B5. Implement Solution
160
-
161
- Work on the card following the generated prompt's guidance.
162
-
163
- **REQUIRED: Update progress at each milestone** by calling \`harmony_update_agent_progress\`. This is not optional — the card's live status badge depends on these updates.
164
-
165
- | Milestone | \`progressPercent\` | Example \`currentTask\` |
166
- |---|---|---|
167
- | After exploring codebase & understanding requirements | 20 | "Reading auth middleware and identifying affected routes" |
168
- | When starting implementation | 50 | "Refactoring token validation in auth.ts" |
169
- | When moving to testing/verification | 80 | "Running build and verifying changes compile" |
170
- | When done, before ending session | 100 | "All changes complete, ready for review" |
171
-
172
- Always set \`currentTask\` to a specific description of what you're actually doing — never leave it as "Analyzing card requirements" or other generic text.
173
-
174
- ### B6. Complete Work
175
-
176
- When finished:
177
- 1. \`harmony_end_agent_session\` with \`status: "completed"\`, \`progressPercent: 100\`, \`moveToColumn: "Review"\`
178
- 2. Summarize accomplishments
179
-
180
- If pausing: \`harmony_end_agent_session\` with \`status: "paused"\`
181
-
182
- ---
183
-
184
- ## Step C: Quick Action
185
-
186
- Fetch the card first (same as B1), then perform the requested action:
187
- - **Move:** \`harmony_move_card\` with target column
188
- - **Update:** \`harmony_update_card\` with changed fields
189
- - **Assign:** \`harmony_assign_card\`
190
- - **Label:** \`harmony_add_label_to_card\` / \`harmony_remove_label_from_card\`
191
- - **Archive:** \`harmony_archive_card\`
192
-
193
- Show confirmation and stop. Do not start an agent session.
194
-
195
- ---
196
-
197
- ## Step D: View Card
198
-
199
- Fetch the card (same as B1) and display: title, short ID, column, priority, labels, assignee, due date, description, subtasks, and links.
200
-
201
- Do not start an agent session.
202
-
203
- ---
204
-
205
- ## Step E: Auto-Detect Card for Implementation Tasks
206
-
207
- **IMPORTANT:** This step applies when you are about to implement a plan, feature, or fix
208
- that was NOT started via /hmy. Before writing any code, check if the work maps to an
209
- existing Harmony card.
210
-
211
- ### When to run this check
212
- - User says "implement this plan", "build this feature", "fix this bug" (without /hmy)
213
- - You are about to execute a plan file
214
- - Skip if: the user already started with /hmy, or no Harmony MCP tools are available
215
-
216
- ### Detection steps
217
- 1. Call \`harmony_search_cards\` with keywords from the plan title or task description
218
- 2. If a card matches (same feature/fix described), tell the user:
219
- "This maps to card #N — starting a session to track progress."
220
- 3. Call \`harmony_start_agent_session\` with \`moveToColumn: "In Progress"\`, \`addLabels: ["agent"]\`
221
- 4. Track progress with \`harmony_update_agent_progress\` at milestones
222
- 5. When done, call \`harmony_end_agent_session\` with \`status: "completed"\`, \`moveToColumn: "Review"\`
223
-
224
- ### If no match
225
- Proceed normally without a session. No action needed.
226
-
227
- ---
228
-
229
- ## Key Tools Reference
230
-
231
- **Cards:** \`harmony_get_card\`, \`harmony_get_card_by_short_id\`, \`harmony_search_cards\`, \`harmony_create_card\`, \`harmony_update_card\`, \`harmony_move_card\`, \`harmony_delete_card\`, \`harmony_assign_card\`
232
-
233
- **Subtasks:** \`harmony_create_subtask\`, \`harmony_toggle_subtask\`, \`harmony_delete_subtask\`
234
-
235
- **Labels:** \`harmony_add_label_to_card\`, \`harmony_remove_label_from_card\`, \`harmony_create_label\`
236
-
237
- **Links:** \`harmony_add_link_to_card\`, \`harmony_remove_link_from_card\`, \`harmony_get_card_links\`
238
-
239
- **Board:** \`harmony_get_board\`, \`harmony_list_projects\`, \`harmony_get_context\`, \`harmony_set_project_context\`
240
-
241
- **Sessions:** \`harmony_start_agent_session\`, \`harmony_update_agent_progress\`, \`harmony_end_agent_session\`, \`harmony_get_agent_session\`
242
-
243
- **AI:** \`harmony_generate_prompt\`, \`harmony_process_command\`
244
- `;
245
- const HMY_PLAN_CONTENT = `# Harmony Plan Workflow
246
-
247
- Create a new plan or work on an existing one. Argument: $ARGUMENTS
248
-
249
- ## Step 1 — Detect Intent
250
-
251
- Parse \`$ARGUMENTS\` to determine the workflow:
252
-
253
- - **UUID** (contains dashes, 36 chars) → call \`harmony_get_plan\` with \`planId\` directly → **Step 2A**
254
- - **\`#N\`** (short ID) → call \`harmony_get_card_by_short_id\` to get the card, then \`harmony_get_plan\` with \`cardId\` → **Step 2A**
255
- - **Text** (anything else) → call \`harmony_list_plans\` with \`search\` set to the text
256
- - If **one match** → use it → **Step 2A**
257
- - If **multiple matches** → list them with title, status, phase, and updated date. Ask the user to pick one using \`AskUserQuestion\` → **Step 2A**
258
- - If **no matches** → ask user: "No existing plans found for '$ARGUMENTS'. Would you like to create a new plan on this topic?" → **Step 2B**
259
- - **Empty / vague topic** → **Step 2B** (create new plan)
260
-
261
- ---
262
-
263
- ## Step 2A — Work on Existing Plan
264
-
265
- ### 2A.1 — Analyze & Display
266
-
267
- Once you have the plan ID, call \`harmony_get_plan\` to fetch the full plan with tasks. Show a structured summary:
268
-
269
- \\\`\\\`\\\`
270
- ## [Plan Title]
271
- **Status:** draft/active/archived | **Phase:** plan/execute/verify/done
272
- **Tasks:** N total (X pending, Y in_progress, Z completed)
273
- **URL:** https://app.gethmy.com/plans/{id}
274
- \\\`\\\`\\\`
275
-
276
- If plan is in execute phase and tasks already have linked cards, note which tasks have cards and which don't.
277
-
278
- ### 2A.2 — Recall Context
279
-
280
- Call \`harmony_memory_search\` with the plan title to find related knowledge, patterns, or decisions that may inform execution.
281
-
282
- ### 2A.3 — Present Options
283
-
284
- Use \`AskUserQuestion\` to offer execution choices. Adapt options based on plan state:
285
-
286
- #### Default options (plan in \`plan\` phase):
287
-
288
- **(A) Single card** — Create one card with plan summary + link to plan. Best for simple plans.
289
- **(B) Multiple cards** — Create one card per task via \`harmony_advance_plan\`. Best for complex plans with independent tasks.
290
- **(C) Analyze only** — Review the plan and design an implementation approach. Create cards later.
291
- **(D) Skip** — Do nothing.
292
-
293
- #### If plan has no tasks:
294
- Only offer **(A) Single card**, **(C) Analyze only**, or **(D) Skip**.
295
-
296
- #### If plan is already in \`execute\` phase with existing cards:
297
- **(A) Work on existing cards** — List cards with short IDs, suggest \`/hmy #N\` to start
298
- **(B) Create cards for remaining tasks** — Only create cards for tasks without linked cards
299
- **(C) Analyze progress** — Review what's done vs remaining
300
- **(D) Skip**
301
-
302
- ### 2A.4 — Execute Choice
303
-
304
- #### Option A — Single card
305
- 1. Call \`harmony_create_card\` with:
306
- - \`title\`: Plan title
307
- - \`description\`: Brief 2-3 sentence summary of the plan + \`\\n\\n[View plan](https://app.gethmy.com/plans/{planId})\`
308
- - \`priority\`: based on plan task priorities (use highest)
309
- 2. Call \`harmony_update_plan\` to set \`status: "active"\`, \`workflowPhase: "execute"\`
310
-
311
- #### Option B — Multiple cards (advance plan)
312
- 1. Call \`harmony_advance_plan\` with:
313
- - \`planId\`: the plan ID
314
- - \`phase\`: \`"execute"\`
315
- - \`summary\`: Brief summary of the plan scope
316
- 2. Display the created cards with their short IDs
317
-
318
- #### Option C — Analyze only
319
- 1. Present a structured implementation analysis:
320
- - Suggested order of tasks
321
- - Dependencies between tasks
322
- - Key technical considerations from memory search
323
- - Estimated complexity
324
- 2. Suggest creating cards when ready
325
-
326
- #### Option D — Skip
327
- Acknowledge and stop.
328
-
329
- ### 2A.5 — Summary
330
-
331
- After execution, show:
332
- - Created card(s) with short IDs
333
- - Current plan phase
334
- - Suggest next step: \`/hmy #N\` to start working on a card
335
-
336
- ---
337
-
338
- ## Step 2B — Create New Plan
339
-
340
- ### 2B.1 — Context Gathering
341
-
342
- Before interviewing, gather existing context:
343
-
344
- 1. Call \`harmony_get_board\` for board state (columns, cards, labels)
345
- 2. Call \`harmony_recall\` with relevant tags to find existing knowledge on the topic
346
- 3. Call \`harmony_memory_search\` with the topic to find related patterns/decisions/lessons
347
-
348
- Note what you learn — reference it during the interview to ask smarter questions.
349
-
350
- ### 2B.2 — Structured Interview (3-5 questions)
351
-
352
- Interview the user with **3-5 focused questions** using AskUserQuestion. Adapt based on complexity.
353
-
354
- #### Core Questions
355
- 1. **Problem & Audience**: What problem are we solving? Who benefits?
356
- 2. **Scope**: What's in v1, what's deferred?
357
- 3. **Technical Constraints**: Any technical preferences, constraints, or existing patterns to follow?
358
-
359
- #### Adaptive Follow-ups (if needed)
360
- - Key user flows or interactions?
361
- - Integration points with existing systems?
362
- - Performance, security, or accessibility requirements?
363
-
364
- #### Interview Rules
365
- - Reference what you found in Step 2B.1 (board state, memories) to ask informed questions
366
- - Skip questions that aren't relevant — simple features need fewer questions
367
- - Tell the user when you have enough information to draft
368
-
369
- ### 2B.3 — Plan Document
370
-
371
- Create a structured markdown document:
372
-
373
- \\\`\\\`\\\`markdown
374
- # [Title]
375
-
376
- ## Problem
377
- [What problem we're solving and why]
378
-
379
- ## Scope
380
-
381
- ### In Scope
382
- - [Feature/capability 1]
383
- - [Feature/capability 2]
384
-
385
- ### Out of Scope
386
- - [Deferred items]
387
-
388
- ## Approach
389
- [Technical design, architecture decisions, key patterns]
390
-
391
- ### Key Decisions
392
- | Decision | Choice | Rationale |
393
- |----------|--------|-----------|
394
- | ... | ... | ... |
395
-
396
- ## Tasks
397
- 1. **[Task title]** — priority: high
398
- [Brief description]
399
-
400
- 2. **[Task title]** — priority: medium
401
- [Brief description]
402
-
403
- [Continue for all tasks...]
404
-
405
- ## Risks & Mitigations
406
- | Risk | Mitigation |
407
- |------|------------|
408
- | ... | ... |
409
-
410
- ## Success Criteria
411
- - [ ] [Measurable criterion]
412
- \\\`\\\`\\\`
413
-
414
- ### 2B.4 — Create Plan
415
-
416
- Call \`harmony_create_plan\` with:
417
- - \`title\`: The plan title
418
- - \`content\`: Full markdown document from Step 2B.3
419
- - \`source\`: \`"agent"\`
420
- - \`workflowPhase\`: \`"plan"\`
421
- - \`tasks\`: Array of tasks from the Tasks section, each with:
422
- - \`content\`: Task title + brief description
423
- - \`priority\`: \`"high"\`, \`"medium"\`, or \`"low"\`
424
- - \`status\`: \`"pending"\`
425
-
426
- ### 2B.5 — User Approval
427
-
428
- Show the user:
429
- - Plan URL: \`https://app.gethmy.com/plans/{id}\`
430
- - Number of tasks created
431
- - Brief summary
432
-
433
- Then ask: **"Ready to execute? I'll create board cards from these tasks and start the execution phase."**
434
-
435
- Options:
436
- 1. **Yes, advance to Execute** — proceed to Step 2B.6
437
- 2. **Let me review first** — end here, they can advance later from the UI
438
- 3. **Make changes** — iterate on the plan
439
-
440
- ### 2B.6 — Advance to Execute
441
-
442
- Call \`harmony_advance_plan\` with:
443
- - \`planId\`: The plan ID from Step 2B.4
444
- - \`phase\`: \`"execute"\`
445
- - \`summary\`: A 2-3 sentence summary of the key decisions made during planning
446
-
447
- Report the result:
448
- - "Created N cards in 'To Do'. Use \`/hmy #<id>\` to start working on any card."
449
- - List the created cards with their short IDs
450
-
451
- ## Key Tools Reference
452
-
453
- **Discovery:** \`harmony_list_plans\`, \`harmony_get_plan\`, \`harmony_get_card_by_short_id\`
454
- **Context:** \`harmony_get_board\`, \`harmony_recall\`, \`harmony_memory_search\`
455
- **Planning:** \`harmony_create_plan\`, \`harmony_advance_plan\`, \`harmony_update_plan\`
456
- **Execution:** \`harmony_create_card\`, \`harmony_update_card\`
457
- `;
458
- export const SKILL_DEFINITIONS = {
459
- hmy: {
460
- name: "hmy",
461
- description: "Work with Harmony cards — create, view, update, or start working on them. Use when given a card reference like #42, or commands like create, move, update.",
462
- argumentHint: "<command or card-reference>",
463
- content: HMY_SKILL_CONTENT,
464
- },
465
- "hmy-plan": {
466
- name: "hmy-plan",
467
- description: "Create a new plan or work on an existing one. Use when asked to plan a feature, execute a plan, review a plan, or given a plan reference.",
468
- argumentHint: "[plan name, ID, or topic to plan]",
469
- content: HMY_PLAN_CONTENT,
470
- },
471
- };
472
- /**
473
- * Build a complete skill file with frontmatter and version marker.
474
- * Optionally substitutes agent identifier/name for agent-specific builds.
475
- */
476
- export function buildSkillFile(skillId, agentId) {
477
- const skill = SKILL_DEFINITIONS[skillId];
478
- if (!skill) {
479
- throw new Error(`Unknown skill: ${skillId}`);
480
- }
481
- let content = skill.content;
482
- // Apply agent-specific substitutions
483
- if (agentId === "claude") {
484
- content = content
485
- .replace("Your agent identifier", "claude-code")
486
- .replace("Your agent name", "Claude Code");
487
- }
488
- const frontmatter = `---
489
- name: ${skill.name}
490
- description: ${skill.description}
491
- argument-hint: ${skill.argumentHint}
492
- ---`;
493
- return `${frontmatter}\n\n${content}\n${VERSION_MARKER_PREFIX}${SKILLS_VERSION} -->`;
494
- }
495
- /**
496
- * Parse the skills version from a skill file's content.
497
- * Returns null if no version marker is found.
498
- */
499
- function parseSkillVersion(content) {
500
- const match = content.match(/<!-- skills-version:(\d+) -->/);
501
- return match ? match[1] : null;
502
- }
503
- /**
504
- * Find all skill files in a given directory (global or local).
505
- * Returns an array of { skillId, filePath } for each found skill.
506
- */
507
- function findSkillFiles(paths) {
508
- const results = [];
509
- for (const filePath of paths) {
510
- if (!existsSync(filePath))
511
- continue;
512
- // Determine skill ID from path
513
- for (const skillId of Object.keys(SKILL_DEFINITIONS)) {
514
- if (filePath.includes(`/${skillId}/`) ||
515
- filePath.includes(`/${skillId}.md`)) {
516
- results.push({ skillId, filePath });
517
- break;
518
- }
519
- }
520
- }
521
- return results;
522
- }
523
- /**
524
- * Silently refresh installed skill files if they are outdated.
525
- * Called at MCP server startup. Non-blocking — errors are caught and logged.
526
- */
527
- export async function refreshSkills() {
528
- try {
529
- const status = areSkillsInstalled();
530
- if (!status.installed) {
531
- // User hasn't run setup yet — don't install skills
532
- return;
533
- }
534
- // Find skill files from the detected paths
535
- const skillFiles = findSkillFiles(status.paths);
536
- // Also check for sibling skills in the same directory
537
- // e.g., if hmy is installed at ~/.agents/skills/hmy/SKILL.md,
538
- // check for hmy-plan at ~/.agents/skills/hmy-plan/SKILL.md
539
- if (skillFiles.length > 0) {
540
- const samplePath = skillFiles[0].filePath;
541
- for (const skillId of Object.keys(SKILL_DEFINITIONS)) {
542
- const alreadyFound = skillFiles.some((sf) => sf.skillId === skillId);
543
- if (alreadyFound)
544
- continue;
545
- // Try to find sibling skill file
546
- let siblingPath;
547
- if (samplePath.endsWith("SKILL.md")) {
548
- // ~/.agents/skills/hmy/SKILL.md -> ~/.agents/skills/hmy-plan/SKILL.md
549
- const parentDir = dirname(dirname(samplePath));
550
- siblingPath = `${parentDir}/${skillId}/SKILL.md`;
551
- }
552
- else {
553
- // ~/.claude/skills/hmy.md -> ~/.claude/skills/hmy-plan.md
554
- const parentDir = dirname(samplePath);
555
- siblingPath = `${parentDir}/${skillId}.md`;
556
- }
557
- if (existsSync(siblingPath)) {
558
- skillFiles.push({ skillId, filePath: siblingPath });
559
- }
560
- }
561
- }
562
- if (skillFiles.length === 0) {
563
- return;
564
- }
565
- let updated = false;
566
- for (const { skillId, filePath } of skillFiles) {
567
- try {
568
- const currentContent = readFileSync(filePath, "utf-8");
569
- const currentVersion = parseSkillVersion(currentContent);
570
- // Update if no version marker or version is older
571
- if (currentVersion === null ||
572
- Number(currentVersion) < Number(SKILLS_VERSION)) {
573
- const newContent = buildSkillFile(skillId, "claude");
574
- const dir = dirname(filePath);
575
- if (!existsSync(dir)) {
576
- mkdirSync(dir, { recursive: true });
577
- }
578
- writeFileSync(filePath, newContent);
579
- updated = true;
580
- }
581
- }
582
- catch {
583
- // Silently skip files we can't read/write
584
- }
585
- }
586
- if (updated) {
587
- console.error(`Harmony: Updated skills to v${SKILLS_VERSION}`);
588
- }
589
- }
590
- catch {
591
- // Non-blocking — if anything fails, continue silently
592
- }
593
- }