@hailer/mcp 0.1.8 → 0.1.9
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/agent-dmitri-activity-crud.md +3 -1
- package/.claude/agents/agent-giuseppe-app-builder.md +11 -12
- package/.claude/agents/agent-kenji-data-reader.md +5 -3
- package/.claude/skills/hailer-app-builder/SKILL.md +506 -0
- package/.claude/skills/publish-hailer-app/SKILL.md +169 -0
- package/.claude/skills/tool-parameter-usage/SKILL.md +112 -0
- package/CLAUDE.md +6 -2
- package/REFACTOR_STATUS.md +127 -0
- package/dist/cli.js +0 -0
- package/dist/client/agents/base.d.ts +202 -0
- package/dist/client/agents/base.js +737 -0
- package/dist/client/agents/definitions.d.ts +53 -0
- package/dist/client/agents/definitions.js +178 -0
- package/dist/client/agents/orchestrator.d.ts +119 -0
- package/dist/client/agents/orchestrator.js +760 -0
- package/dist/client/agents/specialist.d.ts +86 -0
- package/dist/client/agents/specialist.js +340 -0
- package/dist/client/bot-manager.d.ts +44 -0
- package/dist/client/bot-manager.js +173 -0
- package/dist/client/chat-agent-daemon.d.ts +464 -0
- package/dist/client/chat-agent-daemon.js +1774 -0
- package/dist/client/daemon-factory.d.ts +106 -0
- package/dist/client/daemon-factory.js +301 -0
- package/dist/client/factory.d.ts +107 -0
- package/dist/client/factory.js +304 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.js +38 -0
- package/dist/client/multi-bot-manager.d.ts +18 -0
- package/dist/client/multi-bot-manager.js +88 -1
- package/dist/client/orchestrator-daemon.d.ts +87 -0
- package/dist/client/orchestrator-daemon.js +444 -0
- package/dist/client/services/agent-registry.d.ts +108 -0
- package/dist/client/services/agent-registry.js +630 -0
- package/dist/client/services/conversation-manager.d.ts +50 -0
- package/dist/client/services/conversation-manager.js +136 -0
- package/dist/client/services/mcp-client.d.ts +48 -0
- package/dist/client/services/mcp-client.js +105 -0
- package/dist/client/services/message-classifier.d.ts +37 -0
- package/dist/client/services/message-classifier.js +187 -0
- package/dist/client/services/message-formatter.d.ts +84 -0
- package/dist/client/services/message-formatter.js +353 -0
- package/dist/client/services/session-logger.d.ts +106 -0
- package/dist/client/services/session-logger.js +446 -0
- package/dist/client/services/tool-executor.d.ts +41 -0
- package/dist/client/services/tool-executor.js +169 -0
- package/dist/client/services/workspace-schema-cache.d.ts +149 -0
- package/dist/client/services/workspace-schema-cache.js +732 -0
- package/dist/client/specialist-daemon.d.ts +77 -0
- package/dist/client/specialist-daemon.js +197 -0
- package/dist/client/specialists.d.ts +53 -0
- package/dist/client/specialists.js +178 -0
- package/dist/client/tool-schema-loader.d.ts +4 -3
- package/dist/client/tool-schema-loader.js +54 -8
- package/dist/client/types.d.ts +283 -55
- package/dist/client/types.js +113 -2
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/core.d.ts +10 -2
- package/dist/core.js +43 -27
- package/dist/lib/logger.js +15 -3
- package/dist/mcp/UserContextCache.js +2 -2
- package/dist/mcp/hailer-clients.js +5 -5
- package/dist/mcp/signal-handler.js +27 -5
- package/dist/mcp/tools/activity.js +137 -65
- package/dist/mcp/tools/app-core.js +4 -140
- package/dist/mcp/tools/app-marketplace.js +15 -260
- package/dist/mcp/tools/app-member.js +2 -73
- package/dist/mcp/tools/app-scaffold.js +146 -87
- package/dist/mcp/tools/discussion.js +348 -73
- package/dist/mcp/tools/insight.js +74 -190
- package/dist/mcp/tools/workflow.js +20 -94
- package/dist/mcp/utils/hailer-api-client.d.ts +4 -2
- package/dist/mcp/utils/hailer-api-client.js +24 -10
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.js +24 -4
- package/dist/routes/agents.d.ts +44 -0
- package/dist/routes/agents.js +311 -0
- package/dist/services/agent-credential-store.d.ts +73 -0
- package/dist/services/agent-credential-store.js +212 -0
- package/lineup-manager/dist/assets/index-8ce6041d.css +1 -0
- package/lineup-manager/dist/assets/index-e168f265.js +600 -0
- package/lineup-manager/dist/index.html +15 -0
- package/lineup-manager/dist/manifest.json +17 -0
- package/lineup-manager/dist/vite.svg +1 -0
- package/package.json +1 -1
- package/dist/client/adaptive-documentation-bot.d.ts +0 -106
- package/dist/client/adaptive-documentation-bot.js +0 -464
- package/dist/client/adaptive-documentation-types.d.ts +0 -66
- package/dist/client/adaptive-documentation-types.js +0 -9
- package/dist/client/agent-activity-bot.d.ts +0 -51
- package/dist/client/agent-activity-bot.js +0 -166
- package/dist/client/agent-tracker.d.ts +0 -499
- package/dist/client/agent-tracker.js +0 -659
- package/dist/client/description-updater.d.ts +0 -56
- package/dist/client/description-updater.js +0 -259
- package/dist/client/log-parser.d.ts +0 -72
- package/dist/client/log-parser.js +0 -387
- package/dist/client/mcp-assistant.d.ts +0 -21
- package/dist/client/mcp-assistant.js +0 -58
- package/dist/client/mcp-client.d.ts +0 -50
- package/dist/client/mcp-client.js +0 -538
- package/dist/client/message-processor.d.ts +0 -35
- package/dist/client/message-processor.js +0 -357
- package/dist/client/providers/anthropic-provider.d.ts +0 -19
- package/dist/client/providers/anthropic-provider.js +0 -645
- package/dist/client/providers/assistant-provider.d.ts +0 -17
- package/dist/client/providers/assistant-provider.js +0 -51
- package/dist/client/providers/llm-provider.d.ts +0 -47
- package/dist/client/providers/llm-provider.js +0 -367
- package/dist/client/providers/openai-provider.d.ts +0 -23
- package/dist/client/providers/openai-provider.js +0 -630
- package/dist/client/simple-llm-caller.d.ts +0 -19
- package/dist/client/simple-llm-caller.js +0 -100
- package/dist/client/skill-generator.d.ts +0 -81
- package/dist/client/skill-generator.js +0 -386
- package/dist/client/test-adaptive-bot.d.ts +0 -9
- package/dist/client/test-adaptive-bot.js +0 -82
- package/dist/client/token-pricing.d.ts +0 -38
- package/dist/client/token-pricing.js +0 -127
- package/dist/client/token-tracker.d.ts +0 -232
- package/dist/client/token-tracker.js +0 -457
- package/dist/client/token-usage-bot.d.ts +0 -53
- package/dist/client/token-usage-bot.js +0 -153
- package/dist/client/tool-executor.d.ts +0 -69
- package/dist/client/tool-executor.js +0 -159
- package/dist/lib/materialize.d.ts +0 -3
- package/dist/lib/materialize.js +0 -101
- package/dist/lib/normalizedName.d.ts +0 -7
- package/dist/lib/normalizedName.js +0 -48
- package/dist/lib/terminal-prompt.d.ts +0 -9
- package/dist/lib/terminal-prompt.js +0 -108
- package/dist/mcp/tools/skill.d.ts +0 -10
- package/dist/mcp/tools/skill.js +0 -279
- package/dist/mcp/tools/workflow-template.d.ts +0 -19
- package/dist/mcp/tools/workflow-template.js +0 -822
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: publish-hailer-app
|
|
3
|
+
description: Guide for publishing Hailer apps to production
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Publish Hailer App Skill
|
|
7
|
+
|
|
8
|
+
Guide for publishing Hailer apps to production using MCP tools.
|
|
9
|
+
|
|
10
|
+
<critical>
|
|
11
|
+
## MANDATORY: Validate Before Publishing
|
|
12
|
+
|
|
13
|
+
The `publish_hailer_app` tool will SILENTLY FAIL if manifest.json is misconfigured.
|
|
14
|
+
|
|
15
|
+
**YOU MUST validate these before calling publish_hailer_app:**
|
|
16
|
+
|
|
17
|
+
1. Read `public/manifest.json` in the project
|
|
18
|
+
2. Check `appId` exists and is 24 characters
|
|
19
|
+
3. Check `version` exists and is NOT empty (e.g., "1.0.0")
|
|
20
|
+
4. Check `versionDescription` exists and is NOT empty
|
|
21
|
+
|
|
22
|
+
If ANY are missing/empty, FIX THEM FIRST before publishing.
|
|
23
|
+
</critical>
|
|
24
|
+
|
|
25
|
+
<validation-code>
|
|
26
|
+
## Validation Steps (DO THIS FIRST)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
1. Read({file_path: "{projectDir}/public/manifest.json"})
|
|
30
|
+
|
|
31
|
+
2. Verify JSON contains:
|
|
32
|
+
- "appId": "24-char-id" ← If missing: use create_app first
|
|
33
|
+
- "version": "1.0.0" ← If empty: set to "1.0.0"
|
|
34
|
+
- "versionDescription": "..." ← If empty: set to "Initial release"
|
|
35
|
+
|
|
36
|
+
3. If any field missing/empty → Edit manifest.json to fix
|
|
37
|
+
|
|
38
|
+
4. ONLY THEN call publish_hailer_app
|
|
39
|
+
```
|
|
40
|
+
</validation-code>
|
|
41
|
+
|
|
42
|
+
<workflow>
|
|
43
|
+
## Full Publishing Workflow
|
|
44
|
+
|
|
45
|
+
### Step 1: Check if Production App Exists
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
list_apps()
|
|
49
|
+
```
|
|
50
|
+
Look for your app with a `https://apps.hailer.com/...` URL (NOT localhost).
|
|
51
|
+
|
|
52
|
+
### Step 2: Create Production App (if needed)
|
|
53
|
+
|
|
54
|
+
If app doesn't exist or only has localhost URL:
|
|
55
|
+
```javascript
|
|
56
|
+
create_app({
|
|
57
|
+
name: "My App Name",
|
|
58
|
+
description: "What the app does"
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
Returns new appId with production URL.
|
|
62
|
+
|
|
63
|
+
### Step 3: Validate & Fix manifest.json
|
|
64
|
+
|
|
65
|
+
Read the manifest:
|
|
66
|
+
```javascript
|
|
67
|
+
Read({file_path: "{projectDir}/public/manifest.json"})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Required structure:
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"appId": "695816e2ba1d8bef3af7e018",
|
|
74
|
+
"version": "1.0.0",
|
|
75
|
+
"versionDescription": "Initial production release"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**If appId missing:** Add the ID from Step 2
|
|
80
|
+
**If version empty:** Set to "1.0.0"
|
|
81
|
+
**If versionDescription empty:** Set to "Initial release"
|
|
82
|
+
|
|
83
|
+
### Step 4: Publish
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
publish_hailer_app({
|
|
87
|
+
projectDirectory: "/path/to/app"
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Step 5: Verify
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
list_apps()
|
|
95
|
+
```
|
|
96
|
+
Confirm URL is `https://apps.hailer.com/...` (not localhost).
|
|
97
|
+
</workflow>
|
|
98
|
+
|
|
99
|
+
<silent-failure>
|
|
100
|
+
## Why Silent Failures Happen
|
|
101
|
+
|
|
102
|
+
The SDK publish script requires `version` and `versionDescription` in manifest.json.
|
|
103
|
+
If missing/empty, the tool returns "Success" but files are NOT uploaded.
|
|
104
|
+
|
|
105
|
+
**Symptoms of silent failure:**
|
|
106
|
+
- Tool says "App Published Successfully!"
|
|
107
|
+
- But app URL is still `http://localhost:3000`
|
|
108
|
+
- Or production URL returns 403/404
|
|
109
|
+
|
|
110
|
+
**Always validate manifest BEFORE publishing.**
|
|
111
|
+
</silent-failure>
|
|
112
|
+
|
|
113
|
+
<dev-vs-prod>
|
|
114
|
+
## Dev vs Production Apps
|
|
115
|
+
|
|
116
|
+
| Type | URL | Created By | Can Publish To |
|
|
117
|
+
|------|-----|------------|----------------|
|
|
118
|
+
| Dev | `http://localhost:3000` | `scaffold_hailer_app` | NO - stays localhost |
|
|
119
|
+
| Prod | `https://apps.hailer.com/...` | `create_app` | YES |
|
|
120
|
+
|
|
121
|
+
**Key insight:** Dev apps (scaffolded) will ALWAYS use localhost.
|
|
122
|
+
To deploy to production, create a NEW app with `create_app`.
|
|
123
|
+
</dev-vs-prod>
|
|
124
|
+
|
|
125
|
+
<updating>
|
|
126
|
+
## Updating Published Apps
|
|
127
|
+
|
|
128
|
+
1. Bump version in manifest.json:
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"version": "1.0.1",
|
|
132
|
+
"versionDescription": "Fixed data loading bug"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
2. Publish:
|
|
137
|
+
```javascript
|
|
138
|
+
publish_hailer_app({
|
|
139
|
+
projectDirectory: "/path/to/app"
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
New version replaces old at same URL.
|
|
144
|
+
</updating>
|
|
145
|
+
|
|
146
|
+
<sharing>
|
|
147
|
+
## Sharing Apps
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// Entire workspace
|
|
151
|
+
add_app_member({ appId: "...", member: "network_{workspaceId}" })
|
|
152
|
+
|
|
153
|
+
// Team
|
|
154
|
+
add_app_member({ appId: "...", member: "team_{teamId}" })
|
|
155
|
+
|
|
156
|
+
// User
|
|
157
|
+
add_app_member({ appId: "...", member: "user_{userId}" })
|
|
158
|
+
```
|
|
159
|
+
</sharing>
|
|
160
|
+
|
|
161
|
+
<checklist>
|
|
162
|
+
## Pre-Publish Checklist
|
|
163
|
+
|
|
164
|
+
- [ ] Production app exists (`create_app`, not scaffold)
|
|
165
|
+
- [ ] manifest.json `appId` is 24 chars (not empty)
|
|
166
|
+
- [ ] manifest.json `version` is set (e.g., "1.0.0")
|
|
167
|
+
- [ ] manifest.json `versionDescription` is set (not empty)
|
|
168
|
+
- [ ] node_modules exists (dependencies installed)
|
|
169
|
+
</checklist>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tool-parameter-usage
|
|
3
|
+
description: Extract IDs from context and use correct parameter formats for Hailer tools
|
|
4
|
+
triggers: Tool validation failed with "Required" error, empty receivedArgs, or field format errors
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<problem>
|
|
8
|
+
LLM calls tools with empty parameters `{}` even when context contains required IDs, or uses wrong parameter names/formats.
|
|
9
|
+
</problem>
|
|
10
|
+
|
|
11
|
+
<context-extraction>
|
|
12
|
+
The `<incoming>` tag in messages contains critical IDs. ALWAYS extract and use them:
|
|
13
|
+
|
|
14
|
+
```xml
|
|
15
|
+
<incoming activityId="69384669b7826c5d9ec4e07c" discussionId="69384669b7826c5d9ec4e07d">
|
|
16
|
+
User message here
|
|
17
|
+
</incoming>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Extract before calling tools:**
|
|
21
|
+
- `activityId` → use for `show_activity_by_id`, `update_activity`
|
|
22
|
+
- `discussionId` → use for `get_activity_from_discussion`, `add_discussion_message`
|
|
23
|
+
</context-extraction>
|
|
24
|
+
|
|
25
|
+
<correct>
|
|
26
|
+
```typescript
|
|
27
|
+
// Context: <incoming activityId="69384669b7826c5d9ec4e07c" discussionId="69384669b7826c5d9ec4e07d">
|
|
28
|
+
|
|
29
|
+
// ✅ CORRECT - Extract activityId from context
|
|
30
|
+
show_activity_by_id({
|
|
31
|
+
activityId: "69384669b7826c5d9ec4e07c"
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// ✅ CORRECT - Single update mode uses activityId
|
|
35
|
+
update_activity({
|
|
36
|
+
activityId: "69384669b7826c5d9ec4e07c",
|
|
37
|
+
fields: { "fieldId123": 78 }
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// ✅ CORRECT - Bulk update mode uses _id (NOT activityId)
|
|
41
|
+
update_activity({
|
|
42
|
+
activities: [{
|
|
43
|
+
_id: "69384669b7826c5d9ec4e07c",
|
|
44
|
+
fields: { "fieldId123": 78 }
|
|
45
|
+
}]
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// ✅ CORRECT - numericunit field = plain number
|
|
49
|
+
update_activity({
|
|
50
|
+
activityId: "69384669b7826c5d9ec4e07c",
|
|
51
|
+
fields: { "weightFieldId": 78 }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// ✅ CORRECT - Get activity from discussion
|
|
55
|
+
get_activity_from_discussion({
|
|
56
|
+
discussionId: "69384669b7826c5d9ec4e07d"
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
</correct>
|
|
60
|
+
|
|
61
|
+
<wrong>
|
|
62
|
+
```typescript
|
|
63
|
+
// ❌ WRONG - Empty parameters (ignoring context)
|
|
64
|
+
show_activity_by_id({});
|
|
65
|
+
// Error: activityId: Required, receivedArgs={}
|
|
66
|
+
|
|
67
|
+
// ❌ WRONG - Using activityId in bulk mode (should be _id)
|
|
68
|
+
update_activity({
|
|
69
|
+
activities: [{
|
|
70
|
+
activityId: "69384669b7826c5d9ec4e07c", // WRONG KEY
|
|
71
|
+
fields: { "fieldId123": 78 }
|
|
72
|
+
}]
|
|
73
|
+
});
|
|
74
|
+
// Error: activities.0._id: Required
|
|
75
|
+
|
|
76
|
+
// ❌ WRONG - Passing object for numericunit field
|
|
77
|
+
update_activity({
|
|
78
|
+
activityId: "69384669b7826c5d9ec4e07c",
|
|
79
|
+
fields: {
|
|
80
|
+
"weightFieldId": { "type": "numericunit", "value": 78 } // WRONG FORMAT
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
// Error: "Weight" must be a number
|
|
84
|
+
|
|
85
|
+
// ❌ WRONG - Empty list_activities call
|
|
86
|
+
list_activities({});
|
|
87
|
+
// Error: workflowId: Required, phaseId: Required
|
|
88
|
+
```
|
|
89
|
+
</wrong>
|
|
90
|
+
|
|
91
|
+
<fix>
|
|
92
|
+
**Before calling ANY tool:**
|
|
93
|
+
1. Check `<incoming>` tag for `activityId` and `discussionId`
|
|
94
|
+
2. Extract these values and pass them to tools
|
|
95
|
+
|
|
96
|
+
**Parameter rules:**
|
|
97
|
+
| Tool | Single mode | Bulk mode |
|
|
98
|
+
|------|-------------|-----------|
|
|
99
|
+
| `update_activity` | `activityId` | `activities[].\_id` |
|
|
100
|
+
| `show_activity_by_id` | `activityId` | N/A |
|
|
101
|
+
| `get_activity_from_discussion` | `discussionId` | N/A |
|
|
102
|
+
|
|
103
|
+
**Field value formats:**
|
|
104
|
+
| Field type | Value format |
|
|
105
|
+
|------------|--------------|
|
|
106
|
+
| `numericunit` | Plain number: `78` |
|
|
107
|
+
| `text` | Plain string: `"hello"` |
|
|
108
|
+
| `activitylink` | Activity ID string: `"abc123..."` |
|
|
109
|
+
| `select` | Option key: `"option_key"` |
|
|
110
|
+
|
|
111
|
+
**Never pass objects with `type` metadata** - Hailer API expects plain values.
|
|
112
|
+
</fix>
|
package/CLAUDE.md
CHANGED
|
@@ -163,6 +163,7 @@ Community agents are shared via the Hailer Agent Marketplace (separate git repo)
|
|
|
163
163
|
**Installed marketplace agents:**
|
|
164
164
|
No marketplace agents installed.
|
|
165
165
|
|
|
166
|
+
|
|
166
167
|
**Use plugin agents:**
|
|
167
168
|
```
|
|
168
169
|
Task(subagent_type="plugin:agent-name", prompt="...", model="haiku|sonnet")
|
|
@@ -182,11 +183,14 @@ When user asks to install plugins or set up the marketplace:
|
|
|
182
183
|
/plugin install <plugin-name>
|
|
183
184
|
```
|
|
184
185
|
|
|
185
|
-
2. Tell user: "Restart Claude Code to load the
|
|
186
|
+
2. Tell user: "Restart Claude Code to load the plugin. Use `claude -c` to keep your conversation context."
|
|
186
187
|
|
|
187
|
-
Available plugins: `permissions-handler`, `
|
|
188
|
+
Available plugins: `permissions-handler`, `voice-notifications`
|
|
188
189
|
|
|
189
190
|
After restart, sync hook updates this file automatically with installed agents.
|
|
191
|
+
|
|
192
|
+
**IMPORTANT:** After installing OR uninstalling plugins, always tell the user:
|
|
193
|
+
> "Restart required for changes to take effect. Run `claude -c` to restart while keeping your conversation context."
|
|
190
194
|
</plugin-setup>
|
|
191
195
|
|
|
192
196
|
<plugin-contributing>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Client Refactor Status
|
|
2
|
+
|
|
3
|
+
## Completed
|
|
4
|
+
|
|
5
|
+
### Services Created (src/client/services/)
|
|
6
|
+
1. **message-formatter.ts** - Tag formatting, mention resolution, activity linking
|
|
7
|
+
2. **mcp-client.ts** - MCP server communication, tool schema loading
|
|
8
|
+
3. **session-logger.ts** - Activity session tracking, idle detection, session flushing
|
|
9
|
+
4. **agent-registry.ts** - Agent Directory, Positions, Teams, Tool Registry, MCP Config
|
|
10
|
+
|
|
11
|
+
### Files Moved (src/client/agents/)
|
|
12
|
+
1. **definitions.ts** (was specialists.ts) - Specialist definitions
|
|
13
|
+
2. **orchestrator.ts** (was orchestrator-daemon.ts) - Updated imports ✓
|
|
14
|
+
3. **specialist.ts** (was specialist-daemon.ts) - Updated imports ✓
|
|
15
|
+
|
|
16
|
+
### Files Renamed (src/client/)
|
|
17
|
+
1. **factory.ts** (was daemon-factory.ts) - Needs import updates
|
|
18
|
+
2. **bot-manager.ts** (was multi-bot-manager.ts) - Needs import updates
|
|
19
|
+
|
|
20
|
+
### Types Extracted
|
|
21
|
+
- **types.ts** - Already complete with all interfaces and constants
|
|
22
|
+
|
|
23
|
+
## Remaining Work
|
|
24
|
+
|
|
25
|
+
### 1. Create agents/base.ts
|
|
26
|
+
Extract from chat-agent-daemon.ts (2109 lines):
|
|
27
|
+
- Core LLM loop (~500 lines target)
|
|
28
|
+
- Message queue management
|
|
29
|
+
- Abstract getSystemPrompt()
|
|
30
|
+
- Inject services via constructor:
|
|
31
|
+
- MessageFormatterService
|
|
32
|
+
- McpClientService
|
|
33
|
+
- SessionLoggerService
|
|
34
|
+
- AgentRegistryService
|
|
35
|
+
|
|
36
|
+
### 2. Update factory.ts imports
|
|
37
|
+
```typescript
|
|
38
|
+
// Change:
|
|
39
|
+
import { ChatAgentDaemon } from "./chat-agent-daemon";
|
|
40
|
+
import { OrchestratorDaemon } from "./orchestrator-daemon";
|
|
41
|
+
import { SpecialistDaemon } from "./specialist-daemon";
|
|
42
|
+
import { SPECIALISTS } from "./specialists";
|
|
43
|
+
import { MultiBotManager, BotClient } from "./multi-bot-manager";
|
|
44
|
+
|
|
45
|
+
// To:
|
|
46
|
+
import { ChatAgentDaemon } from "./agents/base";
|
|
47
|
+
import { OrchestratorDaemon } from "./agents/orchestrator";
|
|
48
|
+
import { SpecialistDaemon } from "./agents/specialist";
|
|
49
|
+
import { SPECIALISTS } from "./agents/definitions";
|
|
50
|
+
import { MultiBotManager, BotClient } from "./bot-manager";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Create index.ts (public exports)
|
|
54
|
+
```typescript
|
|
55
|
+
export * from "./types";
|
|
56
|
+
export * from "./bot-manager";
|
|
57
|
+
export * from "./factory";
|
|
58
|
+
export * from "./agents/base";
|
|
59
|
+
export * from "./agents/orchestrator";
|
|
60
|
+
export * from "./agents/specialist";
|
|
61
|
+
export * from "./agents/definitions";
|
|
62
|
+
export * from "./services/message-formatter";
|
|
63
|
+
export * from "./services/mcp-client";
|
|
64
|
+
export * from "./services/session-logger";
|
|
65
|
+
export * from "./services/agent-registry";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. Update all imports in codebase
|
|
69
|
+
Files that import from src/client/:
|
|
70
|
+
- src/core.ts
|
|
71
|
+
- src/config.ts
|
|
72
|
+
- Any test files
|
|
73
|
+
|
|
74
|
+
### 5. Delete old files
|
|
75
|
+
After verifying build:
|
|
76
|
+
- src/client/chat-agent-daemon.ts (replaced by agents/base.ts)
|
|
77
|
+
|
|
78
|
+
### 6. Verify build
|
|
79
|
+
```bash
|
|
80
|
+
npm run build
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Architecture
|
|
84
|
+
|
|
85
|
+
### Before
|
|
86
|
+
```
|
|
87
|
+
src/client/
|
|
88
|
+
├── chat-agent-daemon.ts (2109 lines - BLOATED)
|
|
89
|
+
├── orchestrator-daemon.ts
|
|
90
|
+
├── specialist-daemon.ts
|
|
91
|
+
├── specialists.ts
|
|
92
|
+
├── daemon-factory.ts
|
|
93
|
+
├── multi-bot-manager.ts
|
|
94
|
+
└── types.ts
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### After
|
|
98
|
+
```
|
|
99
|
+
src/client/
|
|
100
|
+
├── index.ts # Public exports
|
|
101
|
+
├── factory.ts # DaemonManager
|
|
102
|
+
├── bot-manager.ts # MultiBotManager
|
|
103
|
+
├── types.ts # All interfaces
|
|
104
|
+
│
|
|
105
|
+
├── agents/
|
|
106
|
+
│ ├── base.ts # Core LLM loop (~500 lines)
|
|
107
|
+
│ ├── orchestrator.ts # HAL orchestrator ✓
|
|
108
|
+
│ ├── specialist.ts # Domain experts ✓
|
|
109
|
+
│ └── definitions.ts # SPECIALISTS config ✓
|
|
110
|
+
│
|
|
111
|
+
└── services/
|
|
112
|
+
├── message-formatter.ts # Tags, mentions, links ✓
|
|
113
|
+
├── mcp-client.ts # Tool calling ✓
|
|
114
|
+
├── session-logger.ts # Session logging ✓
|
|
115
|
+
└── agent-registry.ts # Agent Directory registration ✓
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Next Steps
|
|
119
|
+
|
|
120
|
+
1. Create agents/base.ts with service injection
|
|
121
|
+
2. Update factory.ts imports
|
|
122
|
+
3. Update bot-manager.ts imports (if any internal references)
|
|
123
|
+
4. Create index.ts
|
|
124
|
+
5. Update imports in src/core.ts and other files
|
|
125
|
+
6. Run npm run build
|
|
126
|
+
7. Delete chat-agent-daemon.ts
|
|
127
|
+
8. Test the refactored code
|
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat Agent Daemon
|
|
3
|
+
*
|
|
4
|
+
* A persistent LLM conversation that monitors all workspace chats.
|
|
5
|
+
* The LLM maintains context across messages and decides what to respond to.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - One daemon per bot client
|
|
9
|
+
* - Subscribes to ALL messenger.new signals (not filtered)
|
|
10
|
+
* - LLM sees every message with priority markers
|
|
11
|
+
* - LLM decides: RESPOND / IGNORE / ACTION
|
|
12
|
+
*/
|
|
13
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
14
|
+
import { BotClient } from "../bot-manager";
|
|
15
|
+
import { HailerSignal } from "../../mcp/signal-handler";
|
|
16
|
+
import { Logger } from "../../lib/logger";
|
|
17
|
+
import { ToolSchemaLoader, ToolIndexEntry } from "../tool-schema-loader";
|
|
18
|
+
import { ToolInput, McpToolResult } from "../types";
|
|
19
|
+
import { AgentRegistryService } from "../services/agent-registry";
|
|
20
|
+
import { ConversationManager, ConversationMessage } from "../services/conversation-manager";
|
|
21
|
+
import { McpClientService } from "../services/mcp-client";
|
|
22
|
+
import { MessageFormatterService } from "../services/message-formatter";
|
|
23
|
+
import { MessageClassifier } from "../services/message-classifier";
|
|
24
|
+
import { SessionLoggerService } from "../services/session-logger";
|
|
25
|
+
import { ToolExecutor } from "../services/tool-executor";
|
|
26
|
+
import { WorkspaceSchemaCacheService } from "../services/workspace-schema-cache";
|
|
27
|
+
import { SessionMetrics, ActivitySession, MessagePriority, IncomingMessage, ConversationState } from "../types";
|
|
28
|
+
export type { IncomingMessage, MessagePriority, SessionMetrics, ActivitySession };
|
|
29
|
+
export interface ChatAgentDaemonConfig {
|
|
30
|
+
botClient: BotClient;
|
|
31
|
+
mcpServerUrl: string;
|
|
32
|
+
anthropicApiKey: string;
|
|
33
|
+
model?: string;
|
|
34
|
+
maxContextMessages?: number;
|
|
35
|
+
}
|
|
36
|
+
export declare class ChatAgentDaemon {
|
|
37
|
+
protected logger: Logger;
|
|
38
|
+
protected client: Anthropic;
|
|
39
|
+
protected botClient: BotClient;
|
|
40
|
+
protected config: ChatAgentDaemonConfig;
|
|
41
|
+
protected toolSchemaLoader: ToolSchemaLoader;
|
|
42
|
+
protected isProcessing: boolean;
|
|
43
|
+
protected messageQueue: IncomingMessage[];
|
|
44
|
+
protected processedMessageIds: Set<string>;
|
|
45
|
+
private typingInterval;
|
|
46
|
+
private typingDiscussionId;
|
|
47
|
+
private static TYPING_REFRESH_MS;
|
|
48
|
+
protected toolIndex: ToolIndexEntry[];
|
|
49
|
+
protected minimalTools: Anthropic.Tool[];
|
|
50
|
+
/** Message classifier - handles message extraction and priority classification */
|
|
51
|
+
protected messageClassifier: MessageClassifier | null;
|
|
52
|
+
/** Conversation manager - handles per-discussion context and LRU cache */
|
|
53
|
+
protected conversationManager: ConversationManager | null;
|
|
54
|
+
/** MCP client service - handles tool schema loading and execution */
|
|
55
|
+
protected mcpClient: McpClientService | null;
|
|
56
|
+
/** Tool executor - handles tool execution and write tracking */
|
|
57
|
+
protected toolExecutor: ToolExecutor | null;
|
|
58
|
+
/** Agent registration service - handles Agent Directory, Position, Team, etc. */
|
|
59
|
+
protected registryService: AgentRegistryService | null;
|
|
60
|
+
/** Message formatting service - handles tag resolution and formatting */
|
|
61
|
+
protected messageFormatter: MessageFormatterService | null;
|
|
62
|
+
/** Session logging service - handles activity session tracking */
|
|
63
|
+
protected sessionLogger: SessionLoggerService | null;
|
|
64
|
+
/** Workspace schema cache - dynamic workflow/field ID lookup */
|
|
65
|
+
protected schemaCache: WorkspaceSchemaCacheService | null;
|
|
66
|
+
/** Current discussion context for tracking */
|
|
67
|
+
protected currentDiscussionId: string | null;
|
|
68
|
+
protected currentLinkedActivityId: string | null;
|
|
69
|
+
constructor(config: ChatAgentDaemonConfig);
|
|
70
|
+
/**
|
|
71
|
+
* Initialize the daemon - load tools and subscribe to signals
|
|
72
|
+
*/
|
|
73
|
+
initialize(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Extract and classify incoming message from signal
|
|
76
|
+
* Can be overridden in subclasses to customize filtering
|
|
77
|
+
*/
|
|
78
|
+
protected extractIncomingMessage(signal: HailerSignal): Promise<IncomingMessage | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Handle incoming signal from Hailer
|
|
81
|
+
*/
|
|
82
|
+
private handleSignal;
|
|
83
|
+
/**
|
|
84
|
+
* Process queued messages through the LLM
|
|
85
|
+
* Note: Uses flag-first pattern to prevent race conditions
|
|
86
|
+
*/
|
|
87
|
+
private processQueue;
|
|
88
|
+
/**
|
|
89
|
+
* Process a single message through the persistent LLM conversation
|
|
90
|
+
*/
|
|
91
|
+
private processMessage;
|
|
92
|
+
/**
|
|
93
|
+
* Format incoming message for LLM consumption
|
|
94
|
+
*/
|
|
95
|
+
private formatIncomingMessage;
|
|
96
|
+
/**
|
|
97
|
+
* Load and inject memory for an activity into conversation context
|
|
98
|
+
* Called when entering a new discussion that's linked to an activity
|
|
99
|
+
*/
|
|
100
|
+
private injectMemoryForActivity;
|
|
101
|
+
/**
|
|
102
|
+
* Execute tool calls and continue the conversation
|
|
103
|
+
* Simple passthrough - just execute tools and return results to LLM
|
|
104
|
+
*/
|
|
105
|
+
protected executeToolsAndContinue(toolUseBlocks: Anthropic.ToolUseBlock[], originalMessage: IncomingMessage): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Handle LLM response
|
|
108
|
+
* Override in subclasses to customize response handling
|
|
109
|
+
*/
|
|
110
|
+
protected handleLlmResponse(response: Anthropic.Message, originalMessage: IncomingMessage): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Start typing indicator with auto-refresh interval
|
|
113
|
+
* Keeps refreshing every 3 seconds until stopTypingIndicator is called
|
|
114
|
+
*/
|
|
115
|
+
protected startTypingIndicator(discussionId: string): void;
|
|
116
|
+
/**
|
|
117
|
+
* Stop typing indicator and clear refresh interval
|
|
118
|
+
*/
|
|
119
|
+
protected stopTypingIndicator(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Send typing signal to Hailer API
|
|
122
|
+
* API: messenger.set_discussion_typing_state(discussionId, typingState)
|
|
123
|
+
*/
|
|
124
|
+
private sendTypingSignal;
|
|
125
|
+
/**
|
|
126
|
+
* Post a response to a discussion
|
|
127
|
+
* Automatically converts @mentions and #activity tags to Hailer tags
|
|
128
|
+
* Includes links metadata required for tags to work
|
|
129
|
+
*/
|
|
130
|
+
protected postResponse(discussionId: string, content: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Get the system prompt for the daemon
|
|
133
|
+
* MUST be overridden in subclasses
|
|
134
|
+
*/
|
|
135
|
+
protected getSystemPrompt(): string;
|
|
136
|
+
/**
|
|
137
|
+
* Get tool whitelist for this agent
|
|
138
|
+
* Override in subclass to limit which tools are available
|
|
139
|
+
* Return null for all tools, or array of tool names
|
|
140
|
+
*/
|
|
141
|
+
protected getToolWhitelist(): string[] | null;
|
|
142
|
+
/**
|
|
143
|
+
* Preprocess tool input before execution
|
|
144
|
+
* Override in subclass to inject context (e.g., sourceActivityId)
|
|
145
|
+
* @param toolName - Name of the tool being called
|
|
146
|
+
* @param input - Original tool input from LLM
|
|
147
|
+
* @returns Processed input (may be modified)
|
|
148
|
+
*/
|
|
149
|
+
protected preprocessToolInput(toolName: string, input: ToolInput): ToolInput;
|
|
150
|
+
/**
|
|
151
|
+
* Call MCP tool (delegates to McpClientService)
|
|
152
|
+
* Protected for subclass access
|
|
153
|
+
*/
|
|
154
|
+
protected callMcpTool(name: string, args: ToolInput): Promise<McpToolResult>;
|
|
155
|
+
/**
|
|
156
|
+
* Stop the daemon
|
|
157
|
+
* Flushes all pending activity sessions before stopping
|
|
158
|
+
*/
|
|
159
|
+
stop(): Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* Get current conversation state (for debugging)
|
|
162
|
+
*/
|
|
163
|
+
getConversationState(): ConversationState;
|
|
164
|
+
/**
|
|
165
|
+
* Get full conversation for a specific discussion (for debugging)
|
|
166
|
+
*/
|
|
167
|
+
getFullConversation(discussionId?: string): ConversationMessage[];
|
|
168
|
+
/**
|
|
169
|
+
* Get agent's display name (override in subclass for custom names)
|
|
170
|
+
* Default implementation uses the actual Hailer user name from BotClient
|
|
171
|
+
*/
|
|
172
|
+
protected getAgentName(): {
|
|
173
|
+
firstName: string;
|
|
174
|
+
lastName: string;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Get agent's description/system prompt (override in subclass)
|
|
178
|
+
*/
|
|
179
|
+
protected getAgentDescription(): string;
|
|
180
|
+
/**
|
|
181
|
+
* Get default team ID from workspace cache
|
|
182
|
+
* Returns the first available team, or undefined if no teams exist
|
|
183
|
+
*
|
|
184
|
+
* Teams structure in init is: { teams: { workspaceId: { teamId: teamData, ... } } }
|
|
185
|
+
*/
|
|
186
|
+
protected getDefaultTeamId(): string | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* Get agent's Position details (override in subclass for custom positions)
|
|
189
|
+
*/
|
|
190
|
+
protected getPositionDetails(): {
|
|
191
|
+
name: string;
|
|
192
|
+
purpose: string;
|
|
193
|
+
personaTone: string;
|
|
194
|
+
coreCapabilities: string;
|
|
195
|
+
boundaries: string;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Get agent directory ID
|
|
199
|
+
*/
|
|
200
|
+
getAgentDirectoryId(): string | null;
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=base.d.ts.map
|