lunaarc-mcp 1.2.6 → 1.2.8
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/dist/api/client.d.ts +25 -3
- package/dist/api/client.js +14 -0
- package/dist/server.js +6 -2
- package/dist/tools/agents.d.ts +50 -0
- package/dist/tools/agents.js +354 -0
- package/dist/tools/kanban.d.ts +26 -0
- package/dist/tools/kanban.js +155 -26
- package/package.json +1 -1
package/dist/api/client.d.ts
CHANGED
|
@@ -52,10 +52,24 @@ interface AIAssignedCard {
|
|
|
52
52
|
due_date: string | null;
|
|
53
53
|
created_at: string;
|
|
54
54
|
updated_at: string;
|
|
55
|
-
agent_id: string | null;
|
|
56
55
|
agent_name: string | null;
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
}
|
|
57
|
+
interface ProjectAgent {
|
|
58
|
+
id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
description: string | null;
|
|
61
|
+
tools: string[];
|
|
62
|
+
model: string;
|
|
63
|
+
synced_at: string;
|
|
64
|
+
usage_count: number;
|
|
65
|
+
}
|
|
66
|
+
interface PredefinedAgent {
|
|
67
|
+
id: string;
|
|
68
|
+
name: string;
|
|
69
|
+
slug: string;
|
|
70
|
+
description: string | null;
|
|
71
|
+
content: string;
|
|
72
|
+
icon: string | null;
|
|
59
73
|
}
|
|
60
74
|
interface KanbanColumn {
|
|
61
75
|
id: string;
|
|
@@ -175,6 +189,14 @@ export declare class LunaArcApiClient {
|
|
|
175
189
|
id: string;
|
|
176
190
|
message: string;
|
|
177
191
|
}>;
|
|
192
|
+
syncAgents(agents: Array<{
|
|
193
|
+
name: string;
|
|
194
|
+
description: string;
|
|
195
|
+
tools: string[];
|
|
196
|
+
model: string;
|
|
197
|
+
}>): Promise<number>;
|
|
198
|
+
listAgents(): Promise<ProjectAgent[]>;
|
|
199
|
+
getPredefinedAgents(): Promise<PredefinedAgent[]>;
|
|
178
200
|
}
|
|
179
201
|
export declare function createApiClient(): LunaArcApiClient;
|
|
180
202
|
export {};
|
package/dist/api/client.js
CHANGED
|
@@ -108,6 +108,20 @@ class LunaArcApiClient {
|
|
|
108
108
|
body: JSON.stringify(params),
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
+
// Agent API methods
|
|
112
|
+
async syncAgents(agents) {
|
|
113
|
+
const result = await this.request('/agents/sync', {
|
|
114
|
+
method: 'POST',
|
|
115
|
+
body: JSON.stringify({ agents }),
|
|
116
|
+
});
|
|
117
|
+
return result.count;
|
|
118
|
+
}
|
|
119
|
+
async listAgents() {
|
|
120
|
+
return this.request('/agents');
|
|
121
|
+
}
|
|
122
|
+
async getPredefinedAgents() {
|
|
123
|
+
return this.request('/agents/predefined');
|
|
124
|
+
}
|
|
111
125
|
}
|
|
112
126
|
exports.LunaArcApiClient = LunaArcApiClient;
|
|
113
127
|
// Create client instance from environment variables
|
package/dist/server.js
CHANGED
|
@@ -8,8 +8,9 @@ const client_js_1 = require("./api/client.js");
|
|
|
8
8
|
const wiki_js_1 = require("./tools/wiki.js");
|
|
9
9
|
const kanban_js_1 = require("./tools/kanban.js");
|
|
10
10
|
const todos_js_1 = require("./tools/todos.js");
|
|
11
|
+
const agents_js_1 = require("./tools/agents.js");
|
|
11
12
|
// All available tools
|
|
12
|
-
const allTools = [...wiki_js_1.wikiTools, ...kanban_js_1.kanbanTools, ...todos_js_1.todosTools];
|
|
13
|
+
const allTools = [...wiki_js_1.wikiTools, ...kanban_js_1.kanbanTools, ...todos_js_1.todosTools, ...agents_js_1.agentTools];
|
|
13
14
|
// Create API client
|
|
14
15
|
let apiClient;
|
|
15
16
|
try {
|
|
@@ -26,7 +27,7 @@ catch (error) {
|
|
|
26
27
|
// Create MCP server
|
|
27
28
|
const server = new index_js_1.Server({
|
|
28
29
|
name: 'lunaarc-mcp',
|
|
29
|
-
version: '1.2.
|
|
30
|
+
version: '1.2.8',
|
|
30
31
|
}, {
|
|
31
32
|
capabilities: {
|
|
32
33
|
tools: {},
|
|
@@ -52,6 +53,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
52
53
|
else if (name.startsWith('todos_')) {
|
|
53
54
|
return await (0, todos_js_1.handleTodosTool)(apiClient, name, args || {});
|
|
54
55
|
}
|
|
56
|
+
else if (name.startsWith('agents_')) {
|
|
57
|
+
return await (0, agents_js_1.handleAgentTool)(apiClient, name, args || {});
|
|
58
|
+
}
|
|
55
59
|
else {
|
|
56
60
|
throw new Error(`Unknown tool: ${name}`);
|
|
57
61
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { LunaArcApiClient } from '../api/client.js';
|
|
2
|
+
export declare const agentTools: ({
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object";
|
|
7
|
+
properties: {
|
|
8
|
+
agents_dir: {
|
|
9
|
+
type: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
overwrite?: undefined;
|
|
13
|
+
};
|
|
14
|
+
required: never[];
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: "object";
|
|
21
|
+
properties: {
|
|
22
|
+
agents_dir?: undefined;
|
|
23
|
+
overwrite?: undefined;
|
|
24
|
+
};
|
|
25
|
+
required: never[];
|
|
26
|
+
};
|
|
27
|
+
} | {
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: "object";
|
|
32
|
+
properties: {
|
|
33
|
+
agents_dir: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
overwrite: {
|
|
38
|
+
type: string;
|
|
39
|
+
description: string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
required: never[];
|
|
43
|
+
};
|
|
44
|
+
})[];
|
|
45
|
+
export declare function handleAgentTool(client: LunaArcApiClient, toolName: string, args: Record<string, unknown>): Promise<{
|
|
46
|
+
content: {
|
|
47
|
+
type: 'text';
|
|
48
|
+
text: string;
|
|
49
|
+
}[];
|
|
50
|
+
}>;
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.agentTools = void 0;
|
|
37
|
+
exports.handleAgentTool = handleAgentTool;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
// Tool definitions for agent operations
|
|
41
|
+
exports.agentTools = [
|
|
42
|
+
{
|
|
43
|
+
name: 'agents_sync',
|
|
44
|
+
description: `Sync local Claude Code agents to LunaArc project.
|
|
45
|
+
|
|
46
|
+
Reads all agent files from .claude/agents/ directory and syncs them to the project.
|
|
47
|
+
Agent files must be Markdown with YAML frontmatter containing: name, description, tools, model.
|
|
48
|
+
|
|
49
|
+
Example agent file:
|
|
50
|
+
\`\`\`markdown
|
|
51
|
+
---
|
|
52
|
+
name: layout-designer
|
|
53
|
+
description: Layout design specialist...
|
|
54
|
+
tools: Read, Grep, Glob, Edit
|
|
55
|
+
model: haiku
|
|
56
|
+
---
|
|
57
|
+
System prompt here...
|
|
58
|
+
\`\`\`
|
|
59
|
+
|
|
60
|
+
This allows the project to know which agents are available for card assignment.`,
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
agents_dir: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Path to agents directory (default: .claude/agents/)',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: [],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'agents_list',
|
|
74
|
+
description: 'List all AI agents synced to this project. Shows agent names, descriptions, tools, and usage count.',
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {},
|
|
78
|
+
required: [],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'agents_download',
|
|
83
|
+
description: `Download predefined LunaArc agents to your local project.
|
|
84
|
+
|
|
85
|
+
Downloads optimized, ready-to-use agent files from LunaArc to your .claude/agents/ directory.
|
|
86
|
+
These agents are maintained by LunaArc and include best practices for common development tasks.
|
|
87
|
+
|
|
88
|
+
Perfect for users who want to get started quickly without creating custom agents.
|
|
89
|
+
After download, you can customize the agents or use them as-is.`,
|
|
90
|
+
inputSchema: {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
agents_dir: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
description: 'Target directory for agent files (default: .claude/agents/)',
|
|
96
|
+
},
|
|
97
|
+
overwrite: {
|
|
98
|
+
type: 'boolean',
|
|
99
|
+
description: 'Overwrite existing agent files (default: false)',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
required: [],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
// Parse agent frontmatter from markdown file
|
|
107
|
+
function parseAgentFile(filePath) {
|
|
108
|
+
try {
|
|
109
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
110
|
+
// Extract YAML frontmatter between --- markers
|
|
111
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
112
|
+
if (!match) {
|
|
113
|
+
console.error(`No frontmatter found in ${filePath}`);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const frontmatter = match[1];
|
|
117
|
+
// Parse YAML manually (simple key: value pairs)
|
|
118
|
+
const lines = frontmatter.split('\n');
|
|
119
|
+
const data = {};
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const colonIndex = line.indexOf(':');
|
|
122
|
+
if (colonIndex > 0) {
|
|
123
|
+
const key = line.slice(0, colonIndex).trim();
|
|
124
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
125
|
+
data[key] = value;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!data.name) {
|
|
129
|
+
console.error(`Missing 'name' in ${filePath}`);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
// Parse tools (comma-separated)
|
|
133
|
+
const tools = data.tools
|
|
134
|
+
? data.tools.split(',').map((t) => t.trim()).filter(Boolean)
|
|
135
|
+
: [];
|
|
136
|
+
return {
|
|
137
|
+
name: data.name,
|
|
138
|
+
description: data.description || '',
|
|
139
|
+
tools,
|
|
140
|
+
model: data.model || 'sonnet',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(`Error parsing ${filePath}:`, error);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Tool handlers
|
|
149
|
+
async function handleAgentTool(client, toolName, args) {
|
|
150
|
+
switch (toolName) {
|
|
151
|
+
case 'agents_sync': {
|
|
152
|
+
const agentsDir = args.agents_dir || '.claude/agents';
|
|
153
|
+
// Resolve path
|
|
154
|
+
const resolvedPath = path.isAbsolute(agentsDir)
|
|
155
|
+
? agentsDir
|
|
156
|
+
: path.join(process.cwd(), agentsDir);
|
|
157
|
+
// Check if directory exists
|
|
158
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
159
|
+
return {
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: 'text',
|
|
163
|
+
text: `❌ Agents directory not found: ${resolvedPath}
|
|
164
|
+
|
|
165
|
+
Create the directory and add agent files:
|
|
166
|
+
\`\`\`
|
|
167
|
+
mkdir -p .claude/agents
|
|
168
|
+
\`\`\`
|
|
169
|
+
|
|
170
|
+
Then create agent files like \`.claude/agents/layout-designer.md\``,
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// Read all .md files
|
|
176
|
+
const files = fs.readdirSync(resolvedPath).filter((f) => f.endsWith('.md'));
|
|
177
|
+
if (files.length === 0) {
|
|
178
|
+
return {
|
|
179
|
+
content: [
|
|
180
|
+
{
|
|
181
|
+
type: 'text',
|
|
182
|
+
text: `⚠️ No agent files found in ${resolvedPath}
|
|
183
|
+
|
|
184
|
+
Agent files must be Markdown files (.md) with YAML frontmatter.`,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Parse all agent files
|
|
190
|
+
const agents = [];
|
|
191
|
+
const errors = [];
|
|
192
|
+
for (const file of files) {
|
|
193
|
+
const filePath = path.join(resolvedPath, file);
|
|
194
|
+
const agent = parseAgentFile(filePath);
|
|
195
|
+
if (agent) {
|
|
196
|
+
agents.push(agent);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
errors.push(file);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (agents.length === 0) {
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: 'text',
|
|
207
|
+
text: `❌ No valid agents found.
|
|
208
|
+
|
|
209
|
+
Parsing errors in: ${errors.join(', ')}
|
|
210
|
+
|
|
211
|
+
Ensure each file has valid YAML frontmatter with at least a 'name' field.`,
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Sync to LunaArc
|
|
217
|
+
const count = await client.syncAgents(agents);
|
|
218
|
+
let output = `✅ ${count} agent(s) synced successfully!
|
|
219
|
+
|
|
220
|
+
**Synced Agents:**
|
|
221
|
+
`;
|
|
222
|
+
for (const agent of agents) {
|
|
223
|
+
output += `- **${agent.name}** [${agent.model}]\n`;
|
|
224
|
+
if (agent.description) {
|
|
225
|
+
output += ` ${agent.description.slice(0, 60)}${agent.description.length > 60 ? '...' : ''}\n`;
|
|
226
|
+
}
|
|
227
|
+
if (agent.tools.length > 0) {
|
|
228
|
+
output += ` Tools: ${agent.tools.join(', ')}\n`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (errors.length > 0) {
|
|
232
|
+
output += `\n⚠️ Failed to parse: ${errors.join(', ')}`;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
content: [{ type: 'text', text: output }],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
case 'agents_list': {
|
|
239
|
+
const agents = await client.listAgents();
|
|
240
|
+
if (agents.length === 0) {
|
|
241
|
+
return {
|
|
242
|
+
content: [
|
|
243
|
+
{
|
|
244
|
+
type: 'text',
|
|
245
|
+
text: `# Project AI Agents
|
|
246
|
+
|
|
247
|
+
_No agents synced yet._
|
|
248
|
+
|
|
249
|
+
To sync agents, create files in \`.claude/agents/\` and run:
|
|
250
|
+
\`agents_sync\`
|
|
251
|
+
|
|
252
|
+
Or download predefined agents with:
|
|
253
|
+
\`agents_download\``,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
let output = `# Project AI Agents (${agents.length})
|
|
259
|
+
|
|
260
|
+
`;
|
|
261
|
+
for (const agent of agents) {
|
|
262
|
+
output += `## ${agent.name} [${agent.model}]\n`;
|
|
263
|
+
if (agent.description) {
|
|
264
|
+
output += `${agent.description}\n`;
|
|
265
|
+
}
|
|
266
|
+
output += `**Tools:** ${agent.tools.join(', ') || 'all'}\n`;
|
|
267
|
+
output += `**Usage:** ${agent.usage_count} card(s)\n`;
|
|
268
|
+
output += `**Last Sync:** ${new Date(agent.synced_at).toLocaleString()}\n\n`;
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
content: [{ type: 'text', text: output }],
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
case 'agents_download': {
|
|
275
|
+
const agentsDir = args.agents_dir || '.claude/agents';
|
|
276
|
+
const overwrite = args.overwrite || false;
|
|
277
|
+
// Resolve path
|
|
278
|
+
const resolvedPath = path.isAbsolute(agentsDir)
|
|
279
|
+
? agentsDir
|
|
280
|
+
: path.join(process.cwd(), agentsDir);
|
|
281
|
+
// Fetch predefined agents from LunaArc
|
|
282
|
+
const predefinedAgents = await client.getPredefinedAgents();
|
|
283
|
+
if (predefinedAgents.length === 0) {
|
|
284
|
+
return {
|
|
285
|
+
content: [
|
|
286
|
+
{
|
|
287
|
+
type: 'text',
|
|
288
|
+
text: `⚠️ No predefined agents available.
|
|
289
|
+
|
|
290
|
+
There are no predefined agents configured in LunaArc yet.
|
|
291
|
+
You can create your own agents manually in \`.claude/agents/\`.`,
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
// Create directory if it doesn't exist
|
|
297
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
298
|
+
fs.mkdirSync(resolvedPath, { recursive: true });
|
|
299
|
+
}
|
|
300
|
+
const downloaded = [];
|
|
301
|
+
const skipped = [];
|
|
302
|
+
const errors = [];
|
|
303
|
+
for (const agent of predefinedAgents) {
|
|
304
|
+
const fileName = `${agent.slug}.md`;
|
|
305
|
+
const filePath = path.join(resolvedPath, fileName);
|
|
306
|
+
// Check if file already exists
|
|
307
|
+
if (fs.existsSync(filePath) && !overwrite) {
|
|
308
|
+
skipped.push(agent.name);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
// Write agent file
|
|
313
|
+
fs.writeFileSync(filePath, agent.content, 'utf-8');
|
|
314
|
+
downloaded.push(agent.name);
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
errors.push(`${agent.name}: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
let output = '';
|
|
321
|
+
if (downloaded.length > 0) {
|
|
322
|
+
output += `✅ Downloaded ${downloaded.length} agent(s) to ${resolvedPath}\n\n`;
|
|
323
|
+
output += `**Downloaded:**\n`;
|
|
324
|
+
for (const name of downloaded) {
|
|
325
|
+
output += `- ${name}\n`;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (skipped.length > 0) {
|
|
329
|
+
output += `\n⏭️ Skipped ${skipped.length} existing agent(s):\n`;
|
|
330
|
+
for (const name of skipped) {
|
|
331
|
+
output += `- ${name}\n`;
|
|
332
|
+
}
|
|
333
|
+
output += `\n_Use \`overwrite: true\` to update existing files._`;
|
|
334
|
+
}
|
|
335
|
+
if (errors.length > 0) {
|
|
336
|
+
output += `\n\n❌ Errors:\n`;
|
|
337
|
+
for (const err of errors) {
|
|
338
|
+
output += `- ${err}\n`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (downloaded.length === 0 && skipped.length === 0) {
|
|
342
|
+
output = `❌ No agents were downloaded. Check the errors above.`;
|
|
343
|
+
}
|
|
344
|
+
if (downloaded.length > 0) {
|
|
345
|
+
output += `\n\n📌 **Next step:** Run \`agents_sync\` to sync these agents to your LunaArc project.`;
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
content: [{ type: 'text', text: output }],
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
default:
|
|
352
|
+
throw new Error(`Unknown agent tool: ${toolName}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
package/dist/tools/kanban.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const kanbanTools: ({
|
|
|
10
10
|
description?: undefined;
|
|
11
11
|
priority?: undefined;
|
|
12
12
|
labels?: undefined;
|
|
13
|
+
include_agent_content?: undefined;
|
|
13
14
|
column?: undefined;
|
|
14
15
|
content?: undefined;
|
|
15
16
|
};
|
|
@@ -29,6 +30,7 @@ export declare const kanbanTools: ({
|
|
|
29
30
|
description?: undefined;
|
|
30
31
|
priority?: undefined;
|
|
31
32
|
labels?: undefined;
|
|
33
|
+
include_agent_content?: undefined;
|
|
32
34
|
column?: undefined;
|
|
33
35
|
content?: undefined;
|
|
34
36
|
};
|
|
@@ -61,6 +63,7 @@ export declare const kanbanTools: ({
|
|
|
61
63
|
description: string;
|
|
62
64
|
};
|
|
63
65
|
card_id?: undefined;
|
|
66
|
+
include_agent_content?: undefined;
|
|
64
67
|
column?: undefined;
|
|
65
68
|
content?: undefined;
|
|
66
69
|
};
|
|
@@ -96,11 +99,32 @@ export declare const kanbanTools: ({
|
|
|
96
99
|
};
|
|
97
100
|
description: string;
|
|
98
101
|
};
|
|
102
|
+
include_agent_content?: undefined;
|
|
99
103
|
column?: undefined;
|
|
100
104
|
content?: undefined;
|
|
101
105
|
};
|
|
102
106
|
required: string[];
|
|
103
107
|
};
|
|
108
|
+
} | {
|
|
109
|
+
name: string;
|
|
110
|
+
description: string;
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object";
|
|
113
|
+
properties: {
|
|
114
|
+
include_agent_content: {
|
|
115
|
+
type: string;
|
|
116
|
+
description: string;
|
|
117
|
+
};
|
|
118
|
+
card_id?: undefined;
|
|
119
|
+
title?: undefined;
|
|
120
|
+
description?: undefined;
|
|
121
|
+
priority?: undefined;
|
|
122
|
+
labels?: undefined;
|
|
123
|
+
column?: undefined;
|
|
124
|
+
content?: undefined;
|
|
125
|
+
};
|
|
126
|
+
required: never[];
|
|
127
|
+
};
|
|
104
128
|
} | {
|
|
105
129
|
name: string;
|
|
106
130
|
description: string;
|
|
@@ -119,6 +143,7 @@ export declare const kanbanTools: ({
|
|
|
119
143
|
description?: undefined;
|
|
120
144
|
priority?: undefined;
|
|
121
145
|
labels?: undefined;
|
|
146
|
+
include_agent_content?: undefined;
|
|
122
147
|
content?: undefined;
|
|
123
148
|
};
|
|
124
149
|
required: string[];
|
|
@@ -141,6 +166,7 @@ export declare const kanbanTools: ({
|
|
|
141
166
|
description?: undefined;
|
|
142
167
|
priority?: undefined;
|
|
143
168
|
labels?: undefined;
|
|
169
|
+
include_agent_content?: undefined;
|
|
144
170
|
column?: undefined;
|
|
145
171
|
};
|
|
146
172
|
required: string[];
|
package/dist/tools/kanban.js
CHANGED
|
@@ -1,7 +1,146 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.kanbanTools = void 0;
|
|
4
37
|
exports.handleKanbanTool = handleKanbanTool;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const crypto = __importStar(require("crypto"));
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// LOCAL AGENT LOADER
|
|
43
|
+
// ============================================================================
|
|
44
|
+
const AGENT_CONTENT_HARD_LIMIT = 2000; // Max characters for full content
|
|
45
|
+
/**
|
|
46
|
+
* Load local agent file and extract metadata
|
|
47
|
+
*/
|
|
48
|
+
function loadLocalAgent(agentName, includeFullContent = false) {
|
|
49
|
+
const agentPath = path.join(process.cwd(), '.claude/agents', `${agentName}.md`);
|
|
50
|
+
const result = {
|
|
51
|
+
found: false,
|
|
52
|
+
path: agentPath,
|
|
53
|
+
hash: null,
|
|
54
|
+
summary: null,
|
|
55
|
+
content: null,
|
|
56
|
+
truncated: false,
|
|
57
|
+
};
|
|
58
|
+
if (!fs.existsSync(agentPath)) {
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const fileContent = fs.readFileSync(agentPath, 'utf-8');
|
|
63
|
+
result.found = true;
|
|
64
|
+
// Generate hash for change detection
|
|
65
|
+
result.hash = crypto.createHash('md5').update(fileContent).digest('hex').slice(0, 8);
|
|
66
|
+
// Parse YAML frontmatter
|
|
67
|
+
const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---/);
|
|
68
|
+
if (frontmatterMatch) {
|
|
69
|
+
const frontmatter = frontmatterMatch[1];
|
|
70
|
+
const lines = frontmatter.split('\n');
|
|
71
|
+
const data = {};
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const colonIndex = line.indexOf(':');
|
|
74
|
+
if (colonIndex > 0) {
|
|
75
|
+
const key = line.slice(0, colonIndex).trim();
|
|
76
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
77
|
+
data[key] = value;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
result.summary = {
|
|
81
|
+
name: data.name || agentName,
|
|
82
|
+
description: data.description || null,
|
|
83
|
+
tools: data.tools ? data.tools.split(',').map(t => t.trim()).filter(Boolean) : [],
|
|
84
|
+
model: data.model || 'sonnet',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Include full content if requested
|
|
88
|
+
if (includeFullContent) {
|
|
89
|
+
if (fileContent.length > AGENT_CONTENT_HARD_LIMIT) {
|
|
90
|
+
result.content = fileContent.slice(0, AGENT_CONTENT_HARD_LIMIT);
|
|
91
|
+
result.truncated = true;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
result.content = fileContent;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// File read error - return not found
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Format agent info for output
|
|
105
|
+
*/
|
|
106
|
+
function formatAgentOutput(agent, agentName) {
|
|
107
|
+
if (!agent.found) {
|
|
108
|
+
return `## 🤖 AI Agent: ${agentName}
|
|
109
|
+
|
|
110
|
+
⚠️ **Agent not found locally!**
|
|
111
|
+
Expected at: \`${agent.path}\`
|
|
112
|
+
|
|
113
|
+
Run \`agents_download\` to get predefined agents, or create the file manually.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
`;
|
|
118
|
+
}
|
|
119
|
+
let output = `## 🤖 AI Agent: ${agentName}
|
|
120
|
+
|
|
121
|
+
`;
|
|
122
|
+
if (agent.summary) {
|
|
123
|
+
output += `**Description:** ${agent.summary.description || '_No description_'}
|
|
124
|
+
**Model:** ${agent.summary.model}
|
|
125
|
+
**Tools:** ${agent.summary.tools.length > 0 ? agent.summary.tools.join(', ') : 'all'}
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
output += `**Hash:** \`${agent.hash}\`
|
|
129
|
+
**Path:** \`${agent.path}\`
|
|
130
|
+
`;
|
|
131
|
+
if (agent.content) {
|
|
132
|
+
output += `
|
|
133
|
+
<agent-definition>
|
|
134
|
+
${agent.content}${agent.truncated ? '\n\n... [TRUNCATED - ' + AGENT_CONTENT_HARD_LIMIT + ' char limit]' : ''}
|
|
135
|
+
</agent-definition>
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
output += `
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
`;
|
|
142
|
+
return output;
|
|
143
|
+
}
|
|
5
144
|
// Tool definitions for kanban operations
|
|
6
145
|
exports.kanbanTools = [
|
|
7
146
|
{
|
|
@@ -110,10 +249,19 @@ WORKFLOW - You MUST follow these steps:
|
|
|
110
249
|
If a card CANNOT be completed:
|
|
111
250
|
- Add a "## AI Feedback" section explaining WHY
|
|
112
251
|
- Move to "On Hold" (not Done!)
|
|
113
|
-
- Include: reason, missing prerequisites, suggestions
|
|
252
|
+
- Include: reason, missing prerequisites, suggestions
|
|
253
|
+
|
|
254
|
+
AI Agent handling:
|
|
255
|
+
- If the card has an AI agent assigned, the agent's summary (description, model, tools) is shown by default
|
|
256
|
+
- Use include_agent_content=true to include the full agent definition (max 2000 chars)`,
|
|
114
257
|
inputSchema: {
|
|
115
258
|
type: 'object',
|
|
116
|
-
properties: {
|
|
259
|
+
properties: {
|
|
260
|
+
include_agent_content: {
|
|
261
|
+
type: 'boolean',
|
|
262
|
+
description: 'Include full agent definition content (default: false, only summary shown)',
|
|
263
|
+
},
|
|
264
|
+
},
|
|
117
265
|
required: [],
|
|
118
266
|
},
|
|
119
267
|
},
|
|
@@ -379,6 +527,7 @@ ${updates.map((u) => `- ${u}`).join('\n')}`,
|
|
|
379
527
|
};
|
|
380
528
|
}
|
|
381
529
|
case 'kanban_assigned_get': {
|
|
530
|
+
const includeAgentContent = args.include_agent_content || false;
|
|
382
531
|
const cards = await client.getAIAssignedCards();
|
|
383
532
|
if (cards.length === 0) {
|
|
384
533
|
return {
|
|
@@ -445,26 +594,10 @@ ${totalCards > 1 ? `_(${totalCards - 1} weitere Karte${totalCards > 2 ? 'n' : ''
|
|
|
445
594
|
|
|
446
595
|
`;
|
|
447
596
|
}
|
|
448
|
-
//
|
|
449
|
-
if (cardToShow.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
**You MUST confirm this role BEFORE reading or working on the task!**
|
|
453
|
-
|
|
454
|
-
### Role: ${cardToShow.agent_name || 'AI Agent'}
|
|
455
|
-
|
|
456
|
-
${cardToShow.agent_content}
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
**✋ MANDATORY CONFIRMATION:**
|
|
461
|
-
Write FIRST: "I adopt the role ${cardToShow.agent_name || 'AI Agent'}" before starting the task.
|
|
462
|
-
|
|
463
|
-
**Do NOT proceed without this confirmation!**
|
|
464
|
-
|
|
465
|
-
---
|
|
466
|
-
|
|
467
|
-
`;
|
|
597
|
+
// Show agent assignment if present - load from local file
|
|
598
|
+
if (cardToShow.agent_name) {
|
|
599
|
+
const agentInfo = loadLocalAgent(cardToShow.agent_name, includeAgentContent);
|
|
600
|
+
output += formatAgentOutput(agentInfo, cardToShow.agent_name);
|
|
468
601
|
}
|
|
469
602
|
// Render the single card
|
|
470
603
|
const priority = priorityEmoji[cardToShow.priority] || '⚪';
|
|
@@ -479,10 +612,6 @@ Write FIRST: "I adopt the role ${cardToShow.agent_name || 'AI Agent'}" before st
|
|
|
479
612
|
if (cardToShow.due_date) {
|
|
480
613
|
output += `\n**Due:** ${new Date(cardToShow.due_date).toLocaleDateString()}`;
|
|
481
614
|
}
|
|
482
|
-
// Show assigned AI Agent if present
|
|
483
|
-
if (cardToShow.agent_name) {
|
|
484
|
-
output += `\n**AI Agent:** ${cardToShow.agent_name}`;
|
|
485
|
-
}
|
|
486
615
|
output += '\n\n';
|
|
487
616
|
output += cardToShow.description || '_No description_';
|
|
488
617
|
// Add workflow reminder at the end
|