@hailer/mcp 1.1.12 → 1.1.13

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 (271) hide show
  1. package/CHANGELOG.md +0 -7
  2. package/{.claude → dist}/CLAUDE.md +2 -2
  3. package/dist/app.js +18 -5
  4. package/dist/bot/bot-config.d.ts +10 -1
  5. package/dist/bot/bot-config.js +64 -3
  6. package/dist/bot/bot-manager.d.ts +2 -0
  7. package/dist/bot/bot-manager.js +9 -2
  8. package/dist/bot/bot.d.ts +33 -0
  9. package/dist/bot/bot.js +461 -160
  10. package/dist/bot/services/message-classifier.js +17 -0
  11. package/dist/bot/services/permission-guard.d.ts +52 -0
  12. package/dist/bot/services/permission-guard.js +149 -0
  13. package/dist/bot/services/types.d.ts +5 -0
  14. package/dist/bot/services/typing-indicator.d.ts +6 -1
  15. package/dist/bot/services/typing-indicator.js +19 -3
  16. package/dist/cli.js +0 -0
  17. package/dist/config.d.ts +6 -1
  18. package/dist/config.js +43 -0
  19. package/dist/core.js +3 -6
  20. package/dist/lib/discussion-lock.d.ts +42 -0
  21. package/dist/lib/discussion-lock.js +110 -0
  22. package/dist/mcp/UserContextCache.d.ts +5 -0
  23. package/dist/mcp/UserContextCache.js +51 -19
  24. package/dist/mcp/hailer-clients.d.ts +19 -1
  25. package/dist/mcp/hailer-clients.js +158 -24
  26. package/dist/mcp/session-store.d.ts +68 -0
  27. package/dist/mcp/session-store.js +169 -0
  28. package/dist/mcp/signal-handler.js +2 -0
  29. package/dist/mcp/tool-registry.d.ts +17 -4
  30. package/dist/mcp/tool-registry.js +37 -7
  31. package/dist/mcp/tools/activity.js +99 -7
  32. package/dist/mcp/tools/app-scaffold.js +304 -336
  33. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  34. package/dist/mcp/tools/bot-config/constants.js +94 -0
  35. package/dist/mcp/tools/bot-config/core.d.ts +253 -0
  36. package/dist/mcp/tools/bot-config/core.js +2456 -0
  37. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  38. package/dist/mcp/tools/bot-config/index.js +59 -0
  39. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  40. package/dist/mcp/tools/bot-config/tools.js +15 -0
  41. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  42. package/dist/mcp/tools/bot-config/types.js +6 -0
  43. package/dist/mcp/tools/bug-fixer-tools.d.ts +45 -0
  44. package/dist/mcp/tools/bug-fixer-tools.js +1096 -0
  45. package/dist/mcp/tools/company.d.ts +9 -0
  46. package/dist/mcp/tools/company.js +88 -0
  47. package/dist/mcp/tools/discussion.js +68 -0
  48. package/dist/mcp/tools/document.d.ts +11 -0
  49. package/dist/mcp/tools/document.js +741 -0
  50. package/dist/mcp/tools/investigate.d.ts +9 -0
  51. package/dist/mcp/tools/investigate.js +254 -0
  52. package/dist/mcp/tools/workflow-permissions.d.ts +15 -0
  53. package/dist/mcp/tools/workflow-permissions.js +204 -0
  54. package/dist/mcp/tools/workflow.js +57 -18
  55. package/dist/mcp/utils/index.d.ts +2 -0
  56. package/dist/mcp/utils/index.js +12 -1
  57. package/dist/mcp/utils/role-utils.d.ts +74 -0
  58. package/dist/mcp/utils/role-utils.js +151 -0
  59. package/dist/mcp/utils/types.d.ts +43 -1
  60. package/dist/mcp/utils/types.js +14 -0
  61. package/dist/mcp/webhook-handler.d.ts +4 -0
  62. package/dist/mcp/webhook-handler.js +8 -0
  63. package/dist/mcp-server.d.ts +23 -2
  64. package/dist/mcp-server.js +639 -127
  65. package/dist/plugins/vipunen/client.d.ts +150 -0
  66. package/dist/plugins/vipunen/client.js +535 -0
  67. package/dist/plugins/vipunen/config/schema-config.json +19 -0
  68. package/dist/plugins/vipunen/config/schema-doc.json +22 -0
  69. package/dist/plugins/vipunen/index.d.ts +41 -0
  70. package/dist/plugins/vipunen/index.js +88 -0
  71. package/dist/plugins/vipunen/tools.d.ts +26 -0
  72. package/dist/plugins/vipunen/tools.js +501 -0
  73. package/dist/stdio-server.d.ts +14 -0
  74. package/dist/stdio-server.js +101 -0
  75. package/package.json +2 -1
  76. package/.claude/agents/agent-ada-skill-builder.md +0 -94
  77. package/.claude/agents/agent-alejandro-function-fields.md +0 -342
  78. package/.claude/agents/agent-bjorn-config-audit.md +0 -103
  79. package/.claude/agents/agent-builder-agent-creator.md +0 -130
  80. package/.claude/agents/agent-code-simplifier.md +0 -53
  81. package/.claude/agents/agent-dmitri-activity-crud.md +0 -159
  82. package/.claude/agents/agent-giuseppe-app-builder.md +0 -247
  83. package/.claude/agents/agent-gunther-mcp-tools.md +0 -39
  84. package/.claude/agents/agent-helga-workflow-config.md +0 -204
  85. package/.claude/agents/agent-igor-activity-mover-automation.md +0 -125
  86. package/.claude/agents/agent-ingrid-doc-templates.md +0 -261
  87. package/.claude/agents/agent-ivan-monolith.md +0 -154
  88. package/.claude/agents/agent-kenji-data-reader.md +0 -86
  89. package/.claude/agents/agent-lars-code-inspector.md +0 -102
  90. package/.claude/agents/agent-marco-mockup-builder.md +0 -110
  91. package/.claude/agents/agent-marcus-api-documenter.md +0 -323
  92. package/.claude/agents/agent-marketplace-publisher.md +0 -280
  93. package/.claude/agents/agent-marketplace-reviewer.md +0 -309
  94. package/.claude/agents/agent-permissions-handler.md +0 -208
  95. package/.claude/agents/agent-simple-writer.md +0 -48
  96. package/.claude/agents/agent-svetlana-code-review.md +0 -171
  97. package/.claude/agents/agent-tanya-test-runner.md +0 -333
  98. package/.claude/agents/agent-ui-designer.md +0 -100
  99. package/.claude/agents/agent-viktor-sql-insights.md +0 -212
  100. package/.claude/agents/agent-web-search.md +0 -55
  101. package/.claude/agents/agent-yevgeni-discussions.md +0 -45
  102. package/.claude/agents/agent-zara-zapier.md +0 -159
  103. package/.claude/commands/app-squad.md +0 -135
  104. package/.claude/commands/audit-squad.md +0 -158
  105. package/.claude/commands/autoplan.md +0 -563
  106. package/.claude/commands/cleanup-squad.md +0 -98
  107. package/.claude/commands/config-squad.md +0 -106
  108. package/.claude/commands/crud-squad.md +0 -87
  109. package/.claude/commands/data-squad.md +0 -97
  110. package/.claude/commands/debug-squad.md +0 -303
  111. package/.claude/commands/doc-squad.md +0 -65
  112. package/.claude/commands/handoff.md +0 -137
  113. package/.claude/commands/health.md +0 -49
  114. package/.claude/commands/help.md +0 -29
  115. package/.claude/commands/help:agents.md +0 -151
  116. package/.claude/commands/help:commands.md +0 -78
  117. package/.claude/commands/help:faq.md +0 -79
  118. package/.claude/commands/help:plugins.md +0 -50
  119. package/.claude/commands/help:skills.md +0 -93
  120. package/.claude/commands/help:tools.md +0 -75
  121. package/.claude/commands/hotfix-squad.md +0 -112
  122. package/.claude/commands/integration-squad.md +0 -82
  123. package/.claude/commands/janitor-squad.md +0 -167
  124. package/.claude/commands/learn-auto.md +0 -120
  125. package/.claude/commands/learn.md +0 -120
  126. package/.claude/commands/mcp-list.md +0 -27
  127. package/.claude/commands/onboard-squad.md +0 -140
  128. package/.claude/commands/plan-workspace.md +0 -732
  129. package/.claude/commands/prd.md +0 -130
  130. package/.claude/commands/project-status.md +0 -82
  131. package/.claude/commands/publish.md +0 -138
  132. package/.claude/commands/recap.md +0 -69
  133. package/.claude/commands/restore.md +0 -64
  134. package/.claude/commands/review-squad.md +0 -152
  135. package/.claude/commands/save.md +0 -24
  136. package/.claude/commands/stats.md +0 -19
  137. package/.claude/commands/swarm.md +0 -210
  138. package/.claude/commands/tool-builder.md +0 -39
  139. package/.claude/commands/ws-pull.md +0 -44
  140. package/.claude/hooks/_shared-memory.cjs +0 -305
  141. package/.claude/hooks/_utils.cjs +0 -108
  142. package/.claude/hooks/agent-failure-detector.cjs +0 -383
  143. package/.claude/hooks/agent-usage-logger.cjs +0 -204
  144. package/.claude/hooks/app-edit-guard.cjs +0 -494
  145. package/.claude/hooks/auto-learn.cjs +0 -304
  146. package/.claude/hooks/bash-guard.cjs +0 -272
  147. package/.claude/hooks/builder-mode-manager.cjs +0 -354
  148. package/.claude/hooks/bulk-activity-guard.cjs +0 -271
  149. package/.claude/hooks/context-watchdog.cjs +0 -230
  150. package/.claude/hooks/delegation-reminder.cjs +0 -465
  151. package/.claude/hooks/design-system-lint.cjs +0 -271
  152. package/.claude/hooks/post-scaffold-hook.cjs +0 -181
  153. package/.claude/hooks/prompt-guard.cjs +0 -354
  154. package/.claude/hooks/publish-template-guard.cjs +0 -147
  155. package/.claude/hooks/session-start.cjs +0 -35
  156. package/.claude/hooks/shared-memory-writer.cjs +0 -147
  157. package/.claude/hooks/skill-injector.cjs +0 -140
  158. package/.claude/hooks/skill-usage-logger.cjs +0 -258
  159. package/.claude/hooks/src-edit-guard.cjs +0 -240
  160. package/.claude/hooks/sync-marketplace-agents.cjs +0 -346
  161. package/.claude/settings.json +0 -257
  162. package/.claude/skills/SDK-activity-patterns/SKILL.md +0 -428
  163. package/.claude/skills/SDK-document-templates/SKILL.md +0 -1033
  164. package/.claude/skills/SDK-function-fields/SKILL.md +0 -542
  165. package/.claude/skills/SDK-generate-skill/SKILL.md +0 -92
  166. package/.claude/skills/SDK-init-skill/SKILL.md +0 -127
  167. package/.claude/skills/SDK-insight-queries/SKILL.md +0 -787
  168. package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -1139
  169. package/.claude/skills/agent-structure/SKILL.md +0 -98
  170. package/.claude/skills/api-documentation-patterns/SKILL.md +0 -474
  171. package/.claude/skills/chrome-mcp-reference/SKILL.md +0 -370
  172. package/.claude/skills/delegation-routing/SKILL.md +0 -202
  173. package/.claude/skills/frontend-design/SKILL.md +0 -254
  174. package/.claude/skills/hailer-activity-mover/SKILL.md +0 -213
  175. package/.claude/skills/hailer-api-client/SKILL.md +0 -518
  176. package/.claude/skills/hailer-app-builder/SKILL.md +0 -1434
  177. package/.claude/skills/hailer-apps-pictures/SKILL.md +0 -269
  178. package/.claude/skills/hailer-design-system/SKILL.md +0 -235
  179. package/.claude/skills/hailer-monolith-automations/SKILL.md +0 -686
  180. package/.claude/skills/hailer-permissions-system/SKILL.md +0 -121
  181. package/.claude/skills/hailer-project-protocol/SKILL.md +0 -488
  182. package/.claude/skills/hailer-rest-api/SKILL.md +0 -61
  183. package/.claude/skills/hailer-rest-api/hailer-activities.md +0 -184
  184. package/.claude/skills/hailer-rest-api/hailer-admin.md +0 -473
  185. package/.claude/skills/hailer-rest-api/hailer-calendar.md +0 -256
  186. package/.claude/skills/hailer-rest-api/hailer-feed.md +0 -249
  187. package/.claude/skills/hailer-rest-api/hailer-insights.md +0 -195
  188. package/.claude/skills/hailer-rest-api/hailer-messaging.md +0 -276
  189. package/.claude/skills/hailer-rest-api/hailer-workflows.md +0 -283
  190. package/.claude/skills/insight-join-patterns/SKILL.md +0 -174
  191. package/.claude/skills/integration-patterns/SKILL.md +0 -421
  192. package/.claude/skills/json-only-output/SKILL.md +0 -72
  193. package/.claude/skills/lsp-setup/SKILL.md +0 -160
  194. package/.claude/skills/mcp-direct-tools/SKILL.md +0 -153
  195. package/.claude/skills/optional-parameters/SKILL.md +0 -72
  196. package/.claude/skills/publish-hailer-app/SKILL.md +0 -244
  197. package/.claude/skills/testing-patterns/SKILL.md +0 -630
  198. package/.claude/skills/tool-builder/SKILL.md +0 -250
  199. package/.claude/skills/tool-parameter-usage/SKILL.md +0 -126
  200. package/.claude/skills/tool-response-verification/SKILL.md +0 -92
  201. package/.claude/skills/zapier-hailer-patterns/SKILL.md +0 -581
  202. package/.mcp.json +0 -13
  203. package/.opencode/agent/agent-ada-skill-builder.md +0 -35
  204. package/.opencode/agent/agent-alejandro-function-fields.md +0 -39
  205. package/.opencode/agent/agent-bjorn-config-audit.md +0 -36
  206. package/.opencode/agent/agent-builder-agent-creator.md +0 -39
  207. package/.opencode/agent/agent-code-simplifier.md +0 -31
  208. package/.opencode/agent/agent-dmitri-activity-crud.md +0 -40
  209. package/.opencode/agent/agent-giuseppe-app-builder.md +0 -37
  210. package/.opencode/agent/agent-gunther-mcp-tools.md +0 -39
  211. package/.opencode/agent/agent-helga-workflow-config.md +0 -203
  212. package/.opencode/agent/agent-igor-activity-mover-automation.md +0 -46
  213. package/.opencode/agent/agent-ingrid-doc-templates.md +0 -39
  214. package/.opencode/agent/agent-ivan-monolith.md +0 -46
  215. package/.opencode/agent/agent-kenji-data-reader.md +0 -53
  216. package/.opencode/agent/agent-lars-code-inspector.md +0 -28
  217. package/.opencode/agent/agent-marco-mockup-builder.md +0 -42
  218. package/.opencode/agent/agent-marcus-api-documenter.md +0 -53
  219. package/.opencode/agent/agent-marketplace-publisher.md +0 -44
  220. package/.opencode/agent/agent-marketplace-reviewer.md +0 -42
  221. package/.opencode/agent/agent-permissions-handler.md +0 -50
  222. package/.opencode/agent/agent-simple-writer.md +0 -45
  223. package/.opencode/agent/agent-svetlana-code-review.md +0 -39
  224. package/.opencode/agent/agent-tanya-test-runner.md +0 -57
  225. package/.opencode/agent/agent-ui-designer.md +0 -56
  226. package/.opencode/agent/agent-viktor-sql-insights.md +0 -34
  227. package/.opencode/agent/agent-web-search.md +0 -42
  228. package/.opencode/agent/agent-yevgeni-discussions.md +0 -37
  229. package/.opencode/agent/agent-zara-zapier.md +0 -53
  230. package/.opencode/commands/app-squad.md +0 -135
  231. package/.opencode/commands/audit-squad.md +0 -158
  232. package/.opencode/commands/autoplan.md +0 -563
  233. package/.opencode/commands/cleanup-squad.md +0 -98
  234. package/.opencode/commands/config-squad.md +0 -106
  235. package/.opencode/commands/crud-squad.md +0 -87
  236. package/.opencode/commands/data-squad.md +0 -97
  237. package/.opencode/commands/debug-squad.md +0 -303
  238. package/.opencode/commands/doc-squad.md +0 -65
  239. package/.opencode/commands/handoff.md +0 -137
  240. package/.opencode/commands/health.md +0 -49
  241. package/.opencode/commands/help-agents.md +0 -151
  242. package/.opencode/commands/help-commands.md +0 -32
  243. package/.opencode/commands/help-faq.md +0 -29
  244. package/.opencode/commands/help-plugins.md +0 -28
  245. package/.opencode/commands/help-skills.md +0 -7
  246. package/.opencode/commands/help-tools.md +0 -40
  247. package/.opencode/commands/help.md +0 -28
  248. package/.opencode/commands/hotfix-squad.md +0 -112
  249. package/.opencode/commands/integration-squad.md +0 -82
  250. package/.opencode/commands/janitor-squad.md +0 -167
  251. package/.opencode/commands/learn-auto.md +0 -120
  252. package/.opencode/commands/learn.md +0 -120
  253. package/.opencode/commands/mcp-list.md +0 -27
  254. package/.opencode/commands/onboard-squad.md +0 -140
  255. package/.opencode/commands/plan-workspace.md +0 -732
  256. package/.opencode/commands/prd.md +0 -131
  257. package/.opencode/commands/project-status.md +0 -82
  258. package/.opencode/commands/publish.md +0 -138
  259. package/.opencode/commands/recap.md +0 -69
  260. package/.opencode/commands/restore.md +0 -64
  261. package/.opencode/commands/review-squad.md +0 -152
  262. package/.opencode/commands/save.md +0 -24
  263. package/.opencode/commands/stats.md +0 -19
  264. package/.opencode/commands/swarm.md +0 -210
  265. package/.opencode/commands/tool-builder.md +0 -39
  266. package/.opencode/commands/ws-pull.md +0 -44
  267. package/.opencode/opencode.json +0 -28
  268. package/SESSION-HANDOFF.md +0 -68
  269. package/inbox/2026-03-04-bot-config-patterns.md +0 -24
  270. package/scripts/postinstall.cjs +0 -64
  271. package/scripts/test-hal-tools.ts +0 -154
@@ -1,383 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * <hook-name>agent-failure-detector</hook-name>
4
- *
5
- * <purpose>
6
- * Detects repeated agent failures, categorizes error types, and suggests fixes.
7
- * Tracks failures per agent and prompts for improvement after threshold.
8
- * </purpose>
9
- *
10
- * <triggers>
11
- * - PostToolUse on Task tool
12
- * - Only when agent response contains error indicators
13
- * </triggers>
14
- *
15
- * <error-categories>
16
- * - skill: API/schema errors → Create skill documenting correct pattern
17
- * - agent: Behavioral errors → Update agent definition
18
- * - user_issue: Permission errors → Ignore (user problem)
19
- * - transient: Connection/timeout → Ignore (retry may work)
20
- * </error-categories>
21
- *
22
- * <behavior>
23
- * 1. Detects failure patterns in agent response
24
- * 2. Categorizes error type
25
- * 3. Logs to global failures.log
26
- * 4. Auto-spawns Ada on first actionable failure to create skill or update agent
27
- * </behavior>
28
- *
29
- * <tracker-file>/tmp/.claude-agent-failures.json</tracker-file>
30
- * <log-file>$CLAUDE_PROJECT_DIR/inbox/failures.log</log-file>
31
- */
32
-
33
- const fs = require('fs');
34
- const path = require('path');
35
- const os = require('os');
36
-
37
- const TEMP_DIR = os.tmpdir();
38
- const TRACKER_FILE = path.join(TEMP_DIR, '.claude-agent-failures.json');
39
- const GLOBAL_LOG_FILE = path.join(
40
- process.env.HAILER_INBOX_DIR || path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), 'inbox'),
41
- 'failures.log'
42
- );
43
- const FAILURE_THRESHOLD = 1; // Auto-spawn Ada on first failure
44
-
45
- // Skip if stdin is TTY (no piped input)
46
- if (process.stdin.isTTY) {
47
- process.exit(0);
48
- }
49
-
50
- let input = '';
51
- process.stdin.setEncoding('utf8');
52
- process.stdin.on('data', chunk => input += chunk);
53
- process.stdin.on('end', () => {
54
- try {
55
- const data = JSON.parse(input);
56
- processHook(data);
57
- } catch (e) {
58
- console.error(`[agent-failure-detector] Failed to parse input: ${e.message}`);
59
- process.exit(0);
60
- }
61
- });
62
-
63
- function loadTracker() {
64
- try {
65
- if (fs.existsSync(TRACKER_FILE)) {
66
- return JSON.parse(fs.readFileSync(TRACKER_FILE, 'utf8'));
67
- }
68
- } catch (e) {
69
- console.error(`[agent-failure-detector] Warning: ${e.message}`);
70
- }
71
- return { failures: {}, prompted: {}, errorTypes: {} };
72
- }
73
-
74
- function saveTracker(tracker) {
75
- fs.writeFileSync(TRACKER_FILE, JSON.stringify(tracker, null, 2));
76
- }
77
-
78
- /**
79
- * Log failure to global file for persistent tracking
80
- */
81
- function logFailureToGlobal(agentName, errorInfo, errorMessage, projectDir) {
82
- try {
83
- const timestamp = new Date().toISOString();
84
- const project = projectDir ? path.basename(projectDir) : 'unknown';
85
- const logEntry = `[${timestamp}] ${agentName} | ${errorInfo.category} | ${project} | ${errorMessage}\n`;
86
-
87
- // Ensure ~/.claude directory exists
88
- const claudeDir = path.dirname(GLOBAL_LOG_FILE);
89
- if (!fs.existsSync(claudeDir)) {
90
- fs.mkdirSync(claudeDir, { recursive: true });
91
- }
92
-
93
- fs.appendFileSync(GLOBAL_LOG_FILE, logEntry);
94
- } catch (err) {
95
- // Don't fail the hook if logging fails
96
- console.error(`[agent-failure-detector] Could not write to log: ${err.message}`);
97
- }
98
- }
99
-
100
- // Error categorization - determines fix type
101
- const ERROR_CATEGORIES = {
102
- // API/Schema errors -> Create skill (reusable knowledge)
103
- skill: {
104
- patterns: [
105
- 'validation error',
106
- 'invalid field',
107
- 'schema',
108
- 'required parameter',
109
- 'type mismatch',
110
- 'format error',
111
- 'join syntax',
112
- 'sql error',
113
- 'query error',
114
- 'activitylink',
115
- 'workflow.*not found',
116
- 'phase.*not found',
117
- 'field.*not found',
118
- 'functionvariables',
119
- 'functionfield',
120
- 'namefunction',
121
- 'wrong.*type',
122
- 'expected.*got',
123
- 'cannot read prop',
124
- 'undefined.*null',
125
- 'processid',
126
- 'phaseid',
127
- 'fieldid',
128
- 'workflowid',
129
- 'insight.*error',
130
- 'template.*error',
131
- 'pdfmake',
132
- 'mcp.*error',
133
- 'tool.*failed'
134
- ],
135
- suggestion: 'Create a skill documenting the correct pattern',
136
- action: 'create_skill'
137
- },
138
- // Agent behavior errors -> Update agent
139
- agent: {
140
- patterns: [
141
- 'wrong approach',
142
- 'misunderstood',
143
- 'incorrect assumption',
144
- 'should have',
145
- 'forgot to',
146
- 'didn\'t check',
147
- 'missing context',
148
- 'needs to first',
149
- 'order of operations',
150
- 'wrong agent',
151
- 'not my responsibility',
152
- 'outside.*scope',
153
- 'cannot handle',
154
- 'don\'t have.*tool',
155
- 'need.*first',
156
- 'pull.*before',
157
- 'push.*after',
158
- 'didn\'t read',
159
- 'assumed',
160
- 'skipped'
161
- ],
162
- suggestion: 'Update agent definition with better instructions',
163
- action: 'update_agent'
164
- },
165
- // Permission/Auth errors -> Neither (user issue)
166
- user_issue: {
167
- patterns: [
168
- 'permission denied',
169
- 'unauthorized',
170
- 'access denied',
171
- 'not allowed',
172
- 'admin required',
173
- '401',
174
- '403',
175
- 'oauth',
176
- 'token.*expired',
177
- 'token.*invalid',
178
- 'authentication_error',
179
- 'credentials',
180
- 'login failed',
181
- 'session expired'
182
- ],
183
- suggestion: 'User permission issue - not an agent problem',
184
- action: 'ignore'
185
- },
186
- // Connection/Transient errors -> Neither (retry)
187
- transient: {
188
- patterns: [
189
- 'timeout',
190
- 'connection',
191
- 'network',
192
- 'unavailable',
193
- 'try again',
194
- 'rate limit',
195
- 'econnrefused',
196
- 'enotfound',
197
- 'socket',
198
- '500',
199
- '502',
200
- '503',
201
- '504',
202
- 'server error',
203
- 'temporarily',
204
- 'overloaded',
205
- 'busy'
206
- ],
207
- suggestion: 'Transient error - retry may work',
208
- action: 'ignore'
209
- }
210
- };
211
-
212
- function categorizeError(responseText) {
213
- const lower = responseText.toLowerCase();
214
-
215
- for (const [category, config] of Object.entries(ERROR_CATEGORIES)) {
216
- for (const pattern of config.patterns) {
217
- const regex = new RegExp(pattern, 'i');
218
- if (regex.test(lower)) {
219
- return {
220
- category,
221
- ...config,
222
- matchedPattern: pattern
223
- };
224
- }
225
- }
226
- }
227
-
228
- // Default: likely needs skill (documentation)
229
- return {
230
- category: 'unknown',
231
- suggestion: 'Analyze error to determine fix type',
232
- action: 'analyze'
233
- };
234
- }
235
-
236
- function detectFailure(responseText) {
237
- const lower = responseText.toLowerCase();
238
- const failurePatterns = [
239
- '"status":"error"',
240
- '"status": "error"',
241
- 'failed to',
242
- 'error:',
243
- 'could not',
244
- 'unable to',
245
- 'invalid',
246
- 'not found',
247
- 'exception'
248
- ];
249
-
250
- for (const pattern of failurePatterns) {
251
- if (lower.includes(pattern)) {
252
- return true;
253
- }
254
- }
255
- return false;
256
- }
257
-
258
- function extractErrorMessage(responseText) {
259
- // Try to extract meaningful error message - more patterns
260
- const patterns = [
261
- /"error":\s*"([^"]+)"/i,
262
- /"message":\s*"([^"]+)"/i,
263
- /"summary":\s*"([^"]+)"/i,
264
- /"reason":\s*"([^"]+)"/i,
265
- /Error:\s*([^\n]+)/i,
266
- /failed to ([^\n.]+)/i,
267
- /could not ([^\n.]+)/i,
268
- /unable to ([^\n.]+)/i,
269
- /invalid ([^\n.]+)/i,
270
- /missing ([^\n.]+)/i,
271
- /\d{3}\s*[{"]([^"}\n]+)/i, // HTTP status followed by message
272
- /"status":\s*"error"[^}]*"([^"]+)"/i
273
- ];
274
-
275
- for (const pattern of patterns) {
276
- const match = responseText.match(pattern);
277
- if (match && match[1] && match[1].trim().length > 3) {
278
- return match[1].trim().substring(0, 150); // Limit length
279
- }
280
- }
281
-
282
- // Last resort: grab first 100 chars of anything that looks like an error
283
- const errorSnippet = responseText.match(/error[^a-z]*(.{10,100})/i);
284
- if (errorSnippet) {
285
- return errorSnippet[1].trim().substring(0, 100);
286
- }
287
-
288
- return 'Unknown error - check agent output';
289
- }
290
-
291
- function processHook(data) {
292
- const { tool_name, tool_input, tool_response } = data;
293
-
294
- if (tool_name !== 'Task') {
295
- process.exit(0);
296
- }
297
-
298
- const agentName = tool_input?.subagent_type;
299
- if (!agentName || agentName === 'ada') {
300
- process.exit(0);
301
- }
302
-
303
- const responseText = typeof tool_response === 'string'
304
- ? tool_response
305
- : JSON.stringify(tool_response || '');
306
-
307
- if (!detectFailure(responseText)) {
308
- process.exit(0);
309
- }
310
-
311
- // Categorize the error
312
- const errorInfo = categorizeError(responseText);
313
- const errorMessage = extractErrorMessage(responseText);
314
-
315
- // Skip if it's a user issue or transient
316
- if (errorInfo.action === 'ignore') {
317
- process.exit(0);
318
- }
319
-
320
- // Log to global file for persistent tracking
321
- const projectDir = process.env.CLAUDE_PROJECT_DIR;
322
- logFailureToGlobal(agentName, errorInfo, errorMessage, projectDir);
323
-
324
- // Track the failure with category (session-level tracking for prompts)
325
- const tracker = loadTracker();
326
- const key = `${agentName}:${errorInfo.category}`;
327
- tracker.failures[key] = (tracker.failures[key] || 0) + 1;
328
- tracker.errorTypes[key] = errorInfo;
329
- saveTracker(tracker);
330
-
331
- const failureCount = tracker.failures[key];
332
-
333
- if (failureCount >= FAILURE_THRESHOLD && !tracker.prompted[key]) {
334
- tracker.prompted[key] = true;
335
- saveTracker(tracker);
336
-
337
- // Determine action type
338
- let actionType = errorInfo.action;
339
- if (actionType === 'analyze') {
340
- actionType = 'create_skill'; // Default to skill creation
341
- }
342
-
343
- // Sanitize error message to prevent injection via temp file
344
- const safeErrorMessage = errorMessage
345
- .replace(/[`$\\]/g, '')
346
- .substring(0, 500);
347
-
348
- // Build the Ada task prompt
349
- const adaPromptObj = {
350
- task: actionType,
351
- agent: agentName,
352
- error: safeErrorMessage,
353
- category: errorInfo.category,
354
- pattern: errorInfo.matchedPattern || 'unknown'
355
- };
356
-
357
- // SECURITY: Write prompt to temp file to avoid shell injection
358
- // Never embed user-controlled strings directly in shell commands
359
- const tmpDir = os.tmpdir();
360
- const tmpFile = path.join(tmpDir, `ada-prompt-${Date.now()}-${process.pid}.json`);
361
- fs.writeFileSync(tmpFile, JSON.stringify(adaPromptObj, null, 2));
362
-
363
- // AUTO-SPAWN Ada on first actionable failure
364
- // The orchestrator reads the temp file path and handles the Task call safely
365
- const output = `
366
- <user-prompt-submit-hook>
367
- 🤖 AUTO-SPAWNING ADA - ${errorInfo.category} failure detected
368
-
369
- Agent: ${agentName}
370
- Action: ${actionType === 'create_skill' ? 'Creating skill' : 'Updating agent'}
371
-
372
- Ada prompt saved to: ${tmpFile}
373
-
374
- ORCHESTRATOR: Read the JSON file above and call:
375
- Task(subagent_type="agent-ada-skill-builder", prompt=<contents of ${tmpFile}>)
376
- </user-prompt-submit-hook>
377
- `;
378
-
379
- console.log(output);
380
- }
381
-
382
- process.exit(0);
383
- }
@@ -1,204 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * <hook-name>agent-usage-logger</hook-name>
4
- *
5
- * <purpose>
6
- * Logs every agent call for analytics - which agents are used, success/fail rates, duration.
7
- * </purpose>
8
- *
9
- * <triggers>
10
- * - PostToolUse on Task
11
- * </triggers>
12
- *
13
- * <log-file>$CLAUDE_PROJECT_DIR/inbox/usage.jsonl</log-file>
14
- */
15
-
16
- const fs = require('fs');
17
- const path = require('path');
18
- const os = require('os');
19
-
20
- const LOG_FILE = path.join(
21
- process.env.HAILER_INBOX_DIR || path.join(process.env.CLAUDE_PROJECT_DIR || process.cwd(), 'inbox'),
22
- 'usage.jsonl'
23
- );
24
-
25
- // Read hook input from stdin
26
- let input = '';
27
- process.stdin.setEncoding('utf8');
28
- process.stdin.on('data', chunk => input += chunk);
29
- process.stdin.on('end', () => {
30
- try {
31
- const data = JSON.parse(input);
32
- processHook(data);
33
- } catch (e) {
34
- console.error(`[agent-usage-logger] Failed to parse input: ${e.message}`);
35
- process.exit(0);
36
- }
37
- });
38
-
39
- // Cache directory creation state to avoid repeated mkdirSync calls
40
- let _dirCreated = false;
41
-
42
- function detectStatus(responseText) {
43
- // Try to parse as JSON first for reliable status detection
44
- try {
45
- const parsed = JSON.parse(responseText);
46
- if (parsed.status === 'success' || parsed.status === 'ready_to_push') {
47
- return 'success';
48
- }
49
- if (parsed.status === 'error') {
50
- return 'error';
51
- }
52
- } catch (e) {
53
- // Not valid JSON, fall back to string matching
54
- }
55
-
56
- // Fallback: string matching for non-JSON responses
57
- const lower = responseText.toLowerCase();
58
-
59
- if (lower.includes('"status":"success"') || lower.includes('"status": "success"')) {
60
- return 'success';
61
- }
62
- if (lower.includes('"status":"ready_to_push"') || lower.includes('"status": "ready_to_push"')) {
63
- return 'success';
64
- }
65
- if (lower.includes('"status":"error"') || lower.includes('"status": "error"')) {
66
- return 'error';
67
- }
68
- if (lower.includes('failed') || lower.includes('error:') || lower.includes('could not')) {
69
- return 'error';
70
- }
71
-
72
- return 'unknown';
73
- }
74
-
75
- function processHook(data) {
76
- const { tool_name, tool_input, tool_response } = data;
77
-
78
- if (tool_name !== 'Task') {
79
- process.exit(0);
80
- }
81
-
82
- const agentName = tool_input?.subagent_type || 'unknown';
83
- const description = tool_input?.description || '';
84
- const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
85
- const project = path.basename(projectDir);
86
-
87
- const responseText = typeof tool_response === 'string'
88
- ? tool_response
89
- : JSON.stringify(tool_response || '');
90
-
91
- const status = detectStatus(responseText);
92
-
93
- const entry = {
94
- ts: new Date().toISOString(),
95
- agent: agentName,
96
- status,
97
- project,
98
- description: (description || '').substring(0, 50)
99
- };
100
-
101
- try {
102
- // Ensure directory exists (recursive: true is idempotent, no TOCTOU race)
103
- if (!_dirCreated) {
104
- const claudeDir = path.dirname(LOG_FILE);
105
- fs.mkdirSync(claudeDir, { recursive: true });
106
- _dirCreated = true;
107
- }
108
-
109
- fs.appendFileSync(LOG_FILE, JSON.stringify(entry) + '\n');
110
- } catch (err) {
111
- // Don't fail the hook if logging fails
112
- console.error(`[agent-usage-logger] Could not write: ${err.message}`);
113
- }
114
-
115
- process.exit(0);
116
- }
117
-
118
- // CLI: Show recent usage
119
- if (process.argv[2] === '--recent' || process.argv[2] === '-r') {
120
- const limit = parseInt(process.argv[3]) || 20;
121
-
122
- if (!fs.existsSync(LOG_FILE)) {
123
- console.log('No usage data yet');
124
- process.exit(0);
125
- }
126
-
127
- const lines = fs.readFileSync(LOG_FILE, 'utf8').trim().split('\n').filter(Boolean);
128
- const recent = lines.slice(-limit);
129
-
130
- console.log(`Last ${recent.length} agent calls:\n`);
131
- for (const line of recent) {
132
- try {
133
- const entry = JSON.parse(line);
134
- const status = entry.status === 'success' ? '✓' : entry.status === 'error' ? '✗' : '?';
135
- const time = entry.ts.split('T')[1].split('.')[0];
136
- console.log(`${time} ${status} ${entry.agent.padEnd(20)} ${entry.project}`);
137
- } catch {}
138
- }
139
- process.exit(0);
140
- }
141
-
142
- // CLI: Show stats
143
- if (process.argv[2] === '--stats' || process.argv[2] === '-s') {
144
- if (!fs.existsSync(LOG_FILE)) {
145
- console.log('No usage data yet');
146
- process.exit(0);
147
- }
148
-
149
- const lines = fs.readFileSync(LOG_FILE, 'utf8').trim().split('\n').filter(Boolean);
150
- const stats = {};
151
-
152
- for (const line of lines) {
153
- try {
154
- const entry = JSON.parse(line);
155
- if (!stats[entry.agent]) {
156
- stats[entry.agent] = { total: 0, success: 0, error: 0 };
157
- }
158
- stats[entry.agent].total++;
159
- if (entry.status === 'success') stats[entry.agent].success++;
160
- if (entry.status === 'error') stats[entry.agent].error++;
161
- } catch {}
162
- }
163
-
164
- console.log('Agent Usage Stats:\n');
165
- console.log('Agent'.padEnd(25) + 'Total'.padEnd(8) + 'Success'.padEnd(10) + 'Errors');
166
- console.log('-'.repeat(50));
167
-
168
- const sorted = Object.entries(stats).sort((a, b) => b[1].total - a[1].total);
169
- for (const [agent, s] of sorted) {
170
- const rate = s.total > 0 ? Math.round((s.success / s.total) * 100) : 0;
171
- console.log(`${agent.padEnd(25)}${String(s.total).padEnd(8)}${(s.success + ' (' + rate + '%)').padEnd(10)}${s.error}`);
172
- }
173
-
174
- console.log('-'.repeat(50));
175
- console.log(`Total: ${lines.length} calls`);
176
- process.exit(0);
177
- }
178
-
179
- // CLI: Clear log
180
- if (process.argv[2] === '--clear') {
181
- if (fs.existsSync(LOG_FILE)) {
182
- fs.unlinkSync(LOG_FILE);
183
- console.log('✓ Usage log cleared');
184
- } else {
185
- console.log('No log file to clear');
186
- }
187
- process.exit(0);
188
- }
189
-
190
- // CLI: Help
191
- if (process.argv[2] === '--help' || process.argv[2] === '-h') {
192
- console.log(`
193
- Agent Usage Logger - Track agent calls
194
-
195
- Usage:
196
- node agent-usage-logger.cjs --recent [N] Show last N calls (default 20)
197
- node agent-usage-logger.cjs --stats Show usage statistics
198
- node agent-usage-logger.cjs --clear Clear the log
199
- node agent-usage-logger.cjs --help Show this help
200
-
201
- Log file: ${LOG_FILE}
202
- `);
203
- process.exit(0);
204
- }