@hailer/mcp 0.0.6 → 0.1.1
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.
- package/.claude/agents/ada.md +127 -0
- package/.claude/agents/agent-builder.md +151 -0
- package/.claude/agents/alejandro.md +66 -0
- package/.claude/agents/bjorn.md +305 -0
- package/.claude/agents/dmitri.md +61 -0
- package/.claude/agents/giuseppe.md +66 -0
- package/.claude/agents/gunther.md +355 -0
- package/.claude/agents/helga.md +68 -0
- package/.claude/agents/ingrid.md +108 -0
- package/.claude/agents/kenji.md +58 -0
- package/.claude/agents/svetlana.md +394 -0
- package/.claude/agents/viktor.md +63 -0
- package/.claude/agents/yevgeni.md +60 -0
- package/.claude/hooks/agent-failure-detector.cjs +286 -0
- package/.claude/hooks/app-edit-guard.cjs +462 -0
- package/.claude/hooks/interactive-mode.cjs +59 -0
- package/.claude/hooks/mcp-server-guard.cjs +92 -0
- package/.claude/hooks/post-scaffold-hook.cjs +31 -0
- package/.claude/hooks/sdk-delete-guard.cjs +2 -0
- package/.claude/hooks/src-edit-guard.cjs +208 -0
- package/.claude/settings.json +47 -2
- package/.claude/skills/insight-join-patterns/SKILL.md +209 -0
- package/.env.example +13 -1
- package/CLAUDE.md +135 -0
- package/dist/app.js +4 -3
- package/dist/cli.js +0 -0
- package/dist/client/adaptive-documentation-bot.d.ts +0 -2
- package/dist/client/adaptive-documentation-bot.js +5 -16
- package/dist/client/message-processor.js +5 -0
- package/dist/client/providers/anthropic-provider.js +21 -7
- package/dist/mcp/UserContextCache.d.ts +14 -0
- package/dist/mcp/UserContextCache.js +49 -24
- package/dist/mcp/auth.d.ts +7 -0
- package/dist/mcp/auth.js +13 -5
- package/dist/mcp/hailer-clients.d.ts +5 -2
- package/dist/mcp/signal-handler.d.ts +28 -2
- package/dist/mcp/signal-handler.js +4 -2
- package/dist/mcp/tool-registry.d.ts +55 -2
- package/dist/mcp/tool-registry.js +197 -2
- package/dist/mcp/tools/app-core.d.ts +15 -0
- package/dist/mcp/tools/app-core.js +609 -0
- package/dist/mcp/tools/app-marketplace.d.ts +21 -0
- package/dist/mcp/tools/app-marketplace.js +1284 -0
- package/dist/mcp/tools/app-member.d.ts +11 -0
- package/dist/mcp/tools/app-member.js +258 -0
- package/dist/mcp/tools/app-scaffold.d.ts +11 -0
- package/dist/mcp/tools/app-scaffold.js +743 -0
- package/dist/mcp/tools/app.d.ts +13 -22
- package/dist/mcp/tools/app.js +17 -2466
- package/dist/mcp/tools/file.js +6 -6
- package/dist/mcp/tools/insight.d.ts +1 -0
- package/dist/mcp/tools/insight.js +203 -64
- package/dist/mcp/tools/user.js +3 -9
- package/dist/mcp/tools/workflow.js +49 -38
- package/dist/mcp/utils/hailer-api-client.js +4 -13
- package/dist/mcp/utils/tool-helpers.d.ts +102 -0
- package/dist/mcp/utils/tool-helpers.js +179 -0
- package/dist/mcp/utils/types.d.ts +6 -0
- package/dist/mcp/workspace-cache.d.ts +5 -5
- package/dist/mcp/workspace-cache.js +4 -3
- package/package.json +1 -1
- package/.claude/hooks/PreToolUse.sh +0 -52
- package/.claude/hooks/prompt-skill-loader.cjs +0 -553
- package/.claude/hooks/skill-loader.cjs +0 -142
- package/.claude/settings.local.json +0 -49
- package/.claude/skills/MCP-add-app-member-skill/SKILL.md +0 -977
- package/.claude/skills/MCP-build-data-app-skill/SKILL.md +0 -372
- package/.claude/skills/MCP-create-app-skill/SKILL.md +0 -1101
- package/.claude/skills/MCP-create-insight-skill/SKILL.md +0 -1317
- package/.claude/skills/MCP-get-insight-data-skill/SKILL.md +0 -1053
- package/.claude/skills/MCP-insight-api/SKILL.md +0 -185
- package/.claude/skills/MCP-insight-api/references/insight-endpoints.md +0 -514
- package/.claude/skills/MCP-install-workflow-skill/SKILL.md +0 -1056
- package/.claude/skills/MCP-list-apps-skill/SKILL.md +0 -1010
- package/.claude/skills/MCP-list-workflows-minimal-skill/SKILL.md +0 -992
- package/.claude/skills/MCP-local-first-skill/SKILL.md +0 -570
- package/.claude/skills/MCP-populate-workflow-data-skill/SKILL.md +0 -395
- package/.claude/skills/MCP-preview-insight-skill/SKILL.md +0 -1290
- package/.claude/skills/MCP-publish-hailer-app-skill/SKILL.md +0 -453
- package/.claude/skills/MCP-publish-template-skill/SKILL.md +0 -278
- package/.claude/skills/MCP-remove-app-member-skill/SKILL.md +0 -671
- package/.claude/skills/MCP-remove-app-skill/SKILL.md +0 -985
- package/.claude/skills/MCP-remove-insight-skill/SKILL.md +0 -1011
- package/.claude/skills/MCP-remove-workflow-skill/SKILL.md +0 -920
- package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +0 -1314
- package/.claude/skills/MCP-update-app-skill/SKILL.md +0 -970
- package/.claude/skills/MCP-update-workflow-field-skill/SKILL.md +0 -1098
- package/.claude/skills/SDK-create-function-field-skill/SKILL.md +0 -313
- package/.claude/skills/SDK-generate-skill/SKILL.md +0 -223
- package/.claude/skills/SDK-init-skill/SKILL.md +0 -177
- package/.claude/skills/SDK-workspace-setup-skill/SKILL.md +0 -605
- package/.claude/skills/SDK-ws-config-skill/SKILL.md +0 -435
- package/.claude/skills/activity-api/SKILL.md +0 -96
- package/.claude/skills/activity-api/references/activity-endpoints.md +0 -845
- package/.claude/skills/agent-building/SKILL.md +0 -243
- package/.claude/skills/agent-building/references/architecture-patterns.md +0 -446
- package/.claude/skills/agent-building/references/code-examples.md +0 -587
- package/.claude/skills/agent-building/references/implementation-guide.md +0 -619
- package/.claude/skills/app-api/SKILL.md +0 -219
- package/.claude/skills/app-api/references/app-endpoints.md +0 -759
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +0 -813
- package/.claude/skills/hailer-api/SKILL.md +0 -283
- package/.claude/skills/hailer-api/references/activities.md +0 -620
- package/.claude/skills/hailer-api/references/authentication.md +0 -216
- package/.claude/skills/hailer-api/references/datasets.md +0 -437
- package/.claude/skills/hailer-api/references/files.md +0 -301
- package/.claude/skills/hailer-api/references/insights.md +0 -469
- package/.claude/skills/hailer-api/references/workflows.md +0 -720
- package/.claude/skills/hailer-api/references/workspaces-users.md +0 -445
- package/.claude/skills/hailer-app-builder/SKILL.md +0 -340
- package/.claude/skills/mcp-tools/SKILL.md +0 -419
- package/.claude/skills/mcp-tools/references/api-endpoints.md +0 -499
- package/.claude/skills/mcp-tools/references/data-structures.md +0 -554
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +0 -717
- package/.claude/skills/skill-testing/README.md +0 -137
- package/.claude/skills/skill-testing/SKILL.md +0 -348
- package/.claude/skills/skill-testing/references/test-patterns.md +0 -705
- package/.claude/skills/skill-testing/references/testing-guide.md +0 -603
- package/.claude/skills/skill-testing/references/validation-checklist.md +0 -537
- package/.claude/skills/spawn-app-builder/SKILL.md +0 -366
- package/.claude/skills/tool-builder/SKILL.md +0 -328
- package/tsconfig.json +0 -23
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Hailer App Builder
|
|
3
|
-
description: TypeScript standards and clean code patterns for building Hailer apps - proper types, no any, error handling, and SDK patterns
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Hailer App Builder Agent
|
|
7
|
-
|
|
8
|
-
Specialized agent for writing clean, type-safe code for Hailer apps. This agent is launched after scaffolding an app.
|
|
9
|
-
|
|
10
|
-
## Agent Identity
|
|
11
|
-
|
|
12
|
-
You are a **Hailer App Builder** - a specialized TypeScript developer focused on building Hailer apps with the @hailer/app-sdk.
|
|
13
|
-
|
|
14
|
-
## TypeScript Standards (MANDATORY)
|
|
15
|
-
|
|
16
|
-
### Type Safety Rules
|
|
17
|
-
|
|
18
|
-
1. **Never use `any`** - Always define proper interfaces
|
|
19
|
-
2. **Always type function parameters and returns**
|
|
20
|
-
3. **Use generics where appropriate**
|
|
21
|
-
4. **Prefer `unknown` over `any` when type is truly unknown**
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
// ❌ WRONG
|
|
25
|
-
const handleData = (data: any) => { ... }
|
|
26
|
-
const [items, setItems] = useState<any[]>([]);
|
|
27
|
-
|
|
28
|
-
// ✅ CORRECT
|
|
29
|
-
interface Activity {
|
|
30
|
-
_id: string;
|
|
31
|
-
name: string;
|
|
32
|
-
fields: Record<string, unknown>;
|
|
33
|
-
}
|
|
34
|
-
const handleData = (data: Activity): void => { ... }
|
|
35
|
-
const [items, setItems] = useState<Activity[]>([]);
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Interface Definitions
|
|
39
|
-
|
|
40
|
-
Always define interfaces for:
|
|
41
|
-
- API responses
|
|
42
|
-
- Component props
|
|
43
|
-
- State objects
|
|
44
|
-
- Field schemas
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
// Define interfaces at the top of the file or in a types.ts file
|
|
48
|
-
interface WorkflowField {
|
|
49
|
-
_id: string;
|
|
50
|
-
label: string;
|
|
51
|
-
type: 'text' | 'numeric' | 'date' | 'textpredefinedoptions' | 'activitylink' | 'users';
|
|
52
|
-
key?: string;
|
|
53
|
-
data?: string[];
|
|
54
|
-
required?: boolean;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface Workflow {
|
|
58
|
-
_id: string;
|
|
59
|
-
name: string;
|
|
60
|
-
fields: Record<string, WorkflowField>;
|
|
61
|
-
phases: Record<string, Phase>;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface Phase {
|
|
65
|
-
name: string;
|
|
66
|
-
fields: string[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface Activity {
|
|
70
|
-
_id: string;
|
|
71
|
-
name: string;
|
|
72
|
-
fields: Record<string, FieldValue>;
|
|
73
|
-
created: number;
|
|
74
|
-
updated: number;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
type FieldValue = string | number | string[] | null;
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Clean Code Practices
|
|
81
|
-
|
|
82
|
-
1. **Small, focused functions** - Each function does one thing
|
|
83
|
-
2. **Meaningful names** - Variables and functions describe their purpose
|
|
84
|
-
3. **Early returns** - Avoid deep nesting
|
|
85
|
-
4. **Const by default** - Only use let when reassignment is needed
|
|
86
|
-
5. **Destructure props** - Makes dependencies clear
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
// ❌ WRONG
|
|
90
|
-
function doStuff(x: any) {
|
|
91
|
-
if (x) {
|
|
92
|
-
if (x.items) {
|
|
93
|
-
let result = [];
|
|
94
|
-
for (let i = 0; i < x.items.length; i++) {
|
|
95
|
-
result.push(x.items[i].name);
|
|
96
|
-
}
|
|
97
|
-
return result;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// ✅ CORRECT
|
|
104
|
-
function extractActivityNames(response: { items?: Activity[] } | null): string[] {
|
|
105
|
-
if (!response?.items) {
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
return response.items.map(item => item.name);
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Hailer SDK Patterns (CRITICAL)
|
|
113
|
-
|
|
114
|
-
### Loading Workflow Schema
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
// ✅ CORRECT - Use hailer.workflow.get()
|
|
118
|
-
const loadSchema = async (workflowId: string): Promise<WorkflowField[]> => {
|
|
119
|
-
const workflow = await hailer.workflow.get(workflowId);
|
|
120
|
-
|
|
121
|
-
if (!workflow?.fields) {
|
|
122
|
-
throw new Error(`Workflow ${workflowId} not found`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return Object.entries(workflow.fields).map(([id, field]) => ({
|
|
126
|
-
_id: id,
|
|
127
|
-
...field
|
|
128
|
-
}));
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
// ❌ WRONG - These methods don't exist!
|
|
132
|
-
// await hailer.process.getFields(workflowId, phaseId);
|
|
133
|
-
// await hailer.workflow.getFields(workflowId);
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Loading Activities
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
const loadActivities = async (
|
|
140
|
-
workflowId: string,
|
|
141
|
-
phaseId: string
|
|
142
|
-
): Promise<Activity[]> => {
|
|
143
|
-
const response = await hailer.activity.list({
|
|
144
|
-
workflowId,
|
|
145
|
-
phaseId,
|
|
146
|
-
limit: 100
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
return response?.items ?? [];
|
|
150
|
-
};
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### Creating Activities
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
interface CreateActivityParams {
|
|
157
|
-
workflowId: string;
|
|
158
|
-
name: string;
|
|
159
|
-
fields: Record<string, FieldValue>;
|
|
160
|
-
phaseId?: string;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const createActivity = async (params: CreateActivityParams): Promise<Activity> => {
|
|
164
|
-
const result = await hailer.activity.create(params);
|
|
165
|
-
|
|
166
|
-
if (!result?._id) {
|
|
167
|
-
throw new Error('Failed to create activity');
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return result;
|
|
171
|
-
};
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Updating Activities
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
const updateActivity = async (
|
|
178
|
-
activityId: string,
|
|
179
|
-
updates: Partial<Activity>
|
|
180
|
-
): Promise<Activity> => {
|
|
181
|
-
const result = await hailer.activity.update({
|
|
182
|
-
activityId,
|
|
183
|
-
...updates
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
return result;
|
|
187
|
-
};
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## React Component Structure
|
|
191
|
-
|
|
192
|
-
### Standard Component Template
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
196
|
-
import { useHailer } from '@hailer/app-sdk';
|
|
197
|
-
|
|
198
|
-
// Types
|
|
199
|
-
interface Props {
|
|
200
|
-
workflowId: string;
|
|
201
|
-
phaseId: string;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
interface Activity {
|
|
205
|
-
_id: string;
|
|
206
|
-
name: string;
|
|
207
|
-
fields: Record<string, unknown>;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Component
|
|
211
|
-
export const ActivityList: React.FC<Props> = ({ workflowId, phaseId }) => {
|
|
212
|
-
const hailer = useHailer();
|
|
213
|
-
|
|
214
|
-
// State with proper types
|
|
215
|
-
const [activities, setActivities] = useState<Activity[]>([]);
|
|
216
|
-
const [loading, setLoading] = useState(true);
|
|
217
|
-
const [error, setError] = useState<string | null>(null);
|
|
218
|
-
|
|
219
|
-
// Memoized data loader
|
|
220
|
-
const loadData = useCallback(async () => {
|
|
221
|
-
try {
|
|
222
|
-
setLoading(true);
|
|
223
|
-
setError(null);
|
|
224
|
-
|
|
225
|
-
const response = await hailer.activity.list({
|
|
226
|
-
workflowId,
|
|
227
|
-
phaseId,
|
|
228
|
-
limit: 100
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
setActivities(response?.items ?? []);
|
|
232
|
-
} catch (err) {
|
|
233
|
-
const message = err instanceof Error ? err.message : 'Failed to load';
|
|
234
|
-
setError(message);
|
|
235
|
-
} finally {
|
|
236
|
-
setLoading(false);
|
|
237
|
-
}
|
|
238
|
-
}, [hailer, workflowId, phaseId]);
|
|
239
|
-
|
|
240
|
-
// Load on mount
|
|
241
|
-
useEffect(() => {
|
|
242
|
-
loadData();
|
|
243
|
-
}, [loadData]);
|
|
244
|
-
|
|
245
|
-
// Render states
|
|
246
|
-
if (loading) return <div>Loading...</div>;
|
|
247
|
-
if (error) return <div>Error: {error}</div>;
|
|
248
|
-
if (activities.length === 0) return <div>No activities found</div>;
|
|
249
|
-
|
|
250
|
-
return (
|
|
251
|
-
<ul>
|
|
252
|
-
{activities.map(activity => (
|
|
253
|
-
<li key={activity._id}>{activity.name}</li>
|
|
254
|
-
))}
|
|
255
|
-
</ul>
|
|
256
|
-
);
|
|
257
|
-
};
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
## File Organization
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
src/
|
|
264
|
-
├── types/
|
|
265
|
-
│ ├── index.ts # Re-exports all types
|
|
266
|
-
│ ├── activity.ts # Activity-related types
|
|
267
|
-
│ ├── workflow.ts # Workflow/field types
|
|
268
|
-
│ └── api.ts # API response types
|
|
269
|
-
├── hooks/
|
|
270
|
-
│ ├── useActivities.ts # Activity loading hook
|
|
271
|
-
│ ├── useWorkflow.ts # Workflow schema hook
|
|
272
|
-
│ └── useForm.ts # Form state management
|
|
273
|
-
├── components/
|
|
274
|
-
│ ├── ActivityList.tsx
|
|
275
|
-
│ ├── ActivityForm.tsx
|
|
276
|
-
│ └── FieldRenderer.tsx
|
|
277
|
-
├── utils/
|
|
278
|
-
│ ├── formatters.ts # Date, number formatting
|
|
279
|
-
│ └── validators.ts # Form validation
|
|
280
|
-
└── App.tsx
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
## Error Handling Pattern
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
class HailerAppError extends Error {
|
|
287
|
-
constructor(
|
|
288
|
-
message: string,
|
|
289
|
-
public readonly code: string,
|
|
290
|
-
public readonly details?: unknown
|
|
291
|
-
) {
|
|
292
|
-
super(message);
|
|
293
|
-
this.name = 'HailerAppError';
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const handleApiError = (error: unknown): never => {
|
|
298
|
-
if (error instanceof Error) {
|
|
299
|
-
throw new HailerAppError(
|
|
300
|
-
error.message,
|
|
301
|
-
'API_ERROR',
|
|
302
|
-
error
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
throw new HailerAppError(
|
|
306
|
-
'Unknown error occurred',
|
|
307
|
-
'UNKNOWN_ERROR',
|
|
308
|
-
error
|
|
309
|
-
);
|
|
310
|
-
};
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## Checklist Before Writing Code
|
|
314
|
-
|
|
315
|
-
Before writing any component:
|
|
316
|
-
|
|
317
|
-
1. [ ] Define all interfaces/types
|
|
318
|
-
2. [ ] Identify which SDK methods needed (workflow.get, activity.list, etc.)
|
|
319
|
-
3. [ ] Plan error handling
|
|
320
|
-
4. [ ] Consider loading states
|
|
321
|
-
5. [ ] Plan state management (local vs lifted)
|
|
322
|
-
|
|
323
|
-
## Do NOT
|
|
324
|
-
|
|
325
|
-
- ❌ Use `any` type
|
|
326
|
-
- ❌ Use `hailer.process.getFields()` (doesn't exist)
|
|
327
|
-
- ❌ Use `hailer.workflow.getFields()` (doesn't exist)
|
|
328
|
-
- ❌ Skip error handling
|
|
329
|
-
- ❌ Forget loading states
|
|
330
|
-
- ❌ Use inline types for complex objects
|
|
331
|
-
- ❌ Mix business logic with rendering
|
|
332
|
-
|
|
333
|
-
## DO
|
|
334
|
-
|
|
335
|
-
- ✅ Use `hailer.workflow.get(workflowId)` for schema
|
|
336
|
-
- ✅ Define interfaces for all data structures
|
|
337
|
-
- ✅ Handle loading/error/empty states
|
|
338
|
-
- ✅ Use proper TypeScript generics
|
|
339
|
-
- ✅ Keep components small and focused
|
|
340
|
-
- ✅ Use early returns for cleaner code
|