@leejungkiin/awkit 1.1.6 → 1.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/README.md +51 -1
- package/bin/awk.js +2 -2
- package/core/GEMINI.md +45 -7
- package/package.json +8 -5
- package/skill-packs/neural-memory/skills/nm-memory-sync/SKILL.md +14 -1
- package/skills/ab-test-store-listing/SKILL.md +220 -0
- package/skills/android-aso/SKILL.md +197 -0
- package/skills/app-analytics/SKILL.md +210 -0
- package/skills/app-clips/SKILL.md +163 -0
- package/skills/app-icon-optimization/SKILL.md +170 -0
- package/skills/app-launch/SKILL.md +153 -0
- package/skills/app-marketing-context/SKILL.md +129 -0
- package/skills/app-store-featured/SKILL.md +213 -0
- package/skills/apple-search-ads/SKILL.md +205 -0
- package/skills/asc-metrics/SKILL.md +157 -0
- package/skills/aso-audit/SKILL.md +179 -0
- package/skills/competitor-analysis/SKILL.md +163 -0
- package/skills/competitor-tracking/SKILL.md +185 -0
- package/skills/crash-analytics/SKILL.md +181 -0
- package/skills/gitnexus-intelligence/SKILL.md +224 -0
- package/skills/in-app-events/SKILL.md +176 -0
- package/skills/keyword-research/SKILL.md +141 -0
- package/skills/localization/SKILL.md +165 -0
- package/skills/market-movers/SKILL.md +137 -0
- package/skills/market-pulse/SKILL.md +170 -0
- package/skills/metadata-optimization/SKILL.md +170 -0
- package/skills/monetization-strategy/SKILL.md +175 -0
- package/skills/onboarding-optimization/SKILL.md +194 -0
- package/skills/orchestrator/SKILL.md +306 -25
- package/skills/press-and-pr/SKILL.md +204 -0
- package/skills/rating-prompt-strategy/SKILL.md +184 -0
- package/skills/retention-optimization/SKILL.md +165 -0
- package/skills/review-management/SKILL.md +154 -0
- package/skills/screenshot-optimization/SKILL.md +167 -0
- package/skills/seasonal-aso/SKILL.md +141 -0
- package/skills/spec-gate/SKILL.md +312 -0
- package/skills/subscription-lifecycle/SKILL.md +206 -0
- package/skills/swiftui-pro/references/design.md +44 -0
- package/skills/symphony-enforcer/SKILL.md +92 -11
- package/skills/symphony-orchestrator/SKILL.md +9 -7
- package/skills/systematic-debugging/SKILL.md +32 -7
- package/skills/ua-campaign/SKILL.md +207 -0
- package/skills/verification-gate/SKILL.md +23 -2
- package/workflows/gitnexus.md +123 -0
- package/symphony/LICENSE +0 -21
- package/symphony/README.md +0 -178
- package/symphony/app/api/agents/route.js +0 -152
- package/symphony/app/api/events/route.js +0 -22
- package/symphony/app/api/knowledge/route.js +0 -253
- package/symphony/app/api/locks/route.js +0 -29
- package/symphony/app/api/notes/route.js +0 -125
- package/symphony/app/api/preflight/route.js +0 -23
- package/symphony/app/api/projects/route.js +0 -116
- package/symphony/app/api/roles/route.js +0 -134
- package/symphony/app/api/skills/route.js +0 -82
- package/symphony/app/api/status/route.js +0 -18
- package/symphony/app/api/tasks/route.js +0 -157
- package/symphony/app/api/workflows/route.js +0 -61
- package/symphony/app/api/workspaces/route.js +0 -15
- package/symphony/app/globals.css +0 -2605
- package/symphony/app/layout.js +0 -20
- package/symphony/app/page.js +0 -2122
- package/symphony/cli/index.js +0 -1060
- package/symphony/core/agent-manager.js +0 -357
- package/symphony/core/context-bus.js +0 -100
- package/symphony/core/db.js +0 -223
- package/symphony/core/file-lock-manager.js +0 -154
- package/symphony/core/merge-pipeline.js +0 -234
- package/symphony/core/orchestrator.js +0 -236
- package/symphony/core/task-manager.js +0 -335
- package/symphony/core/workspace-manager.js +0 -168
- package/symphony/jsconfig.json +0 -7
- package/symphony/lib/core.mjs +0 -1034
- package/symphony/mcp/index.js +0 -29
- package/symphony/mcp/server.js +0 -110
- package/symphony/mcp/tools/context.js +0 -80
- package/symphony/mcp/tools/locks.js +0 -99
- package/symphony/mcp/tools/status.js +0 -82
- package/symphony/mcp/tools/tasks.js +0 -216
- package/symphony/mcp/tools/workspace.js +0 -143
- package/symphony/next.config.mjs +0 -7
- package/symphony/package.json +0 -53
- package/symphony/scripts/postinstall.js +0 -49
- package/symphony/symphony.config.js +0 -41
package/symphony/mcp/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Symphony MCP — Tool Registry
|
|
3
|
-
* Registers all 14 MCP tools on the server instance.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { registerTaskTools } = require('./tools/tasks');
|
|
7
|
-
const { registerLockTools } = require('./tools/locks');
|
|
8
|
-
const { registerContextTools } = require('./tools/context');
|
|
9
|
-
const { registerStatusTools } = require('./tools/status');
|
|
10
|
-
const workspaceTools = require('./tools/workspace');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Register all Symphony MCP tools on the given server.
|
|
14
|
-
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
15
|
-
* @param {() => string} getAgentId - Returns the current agent ID for this session
|
|
16
|
-
*/
|
|
17
|
-
function registerAllTools(server, getAgentId) {
|
|
18
|
-
registerTaskTools(server, getAgentId);
|
|
19
|
-
registerLockTools(server, getAgentId);
|
|
20
|
-
registerContextTools(server, getAgentId);
|
|
21
|
-
registerStatusTools(server);
|
|
22
|
-
|
|
23
|
-
// Register workspace tools (array-based export)
|
|
24
|
-
for (const tool of workspaceTools) {
|
|
25
|
-
server.tool(tool.name, tool.description, tool.schema, tool.handler);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = { registerAllTools };
|
package/symphony/mcp/server.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Symphony MCP Server
|
|
5
|
-
* Starts an MCP server via stdio transport for IDE ↔ Symphony communication.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* node mcp/server.js
|
|
9
|
-
* # Or via CLI:
|
|
10
|
-
* symphony mcp-serve
|
|
11
|
-
*
|
|
12
|
-
* Environment:
|
|
13
|
-
* SYMPHONY_AGENT_NAME — Agent display name (default: auto-generated)
|
|
14
|
-
* SYMPHONY_PROJECT — Project root path (default: cwd)
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
18
|
-
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
const { nanoid } = require('nanoid');
|
|
21
|
-
|
|
22
|
-
// Initialize database (ensure core modules can access it)
|
|
23
|
-
const SYMPHONY_ROOT = path.join(__dirname, '..');
|
|
24
|
-
process.chdir(process.env.SYMPHONY_PROJECT || SYMPHONY_ROOT);
|
|
25
|
-
|
|
26
|
-
// Import core DB to ensure it's initialized
|
|
27
|
-
const db = require(path.join(SYMPHONY_ROOT, 'core', 'db'));
|
|
28
|
-
const orchestrator = require(path.join(SYMPHONY_ROOT, 'core', 'orchestrator'));
|
|
29
|
-
|
|
30
|
-
// Read package version
|
|
31
|
-
let version = '0.1.0';
|
|
32
|
-
try {
|
|
33
|
-
const pkg = require(path.join(SYMPHONY_ROOT, 'package.json'));
|
|
34
|
-
version = pkg.version || version;
|
|
35
|
-
} catch (_) {
|
|
36
|
-
// Ignore
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Agent identification
|
|
40
|
-
const agentName = process.env.SYMPHONY_AGENT_NAME || `agent-${nanoid(6)}`;
|
|
41
|
-
let agentId = agentName;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get the current agent ID for this MCP session.
|
|
45
|
-
* @returns {string}
|
|
46
|
-
*/
|
|
47
|
-
function getAgentId() {
|
|
48
|
-
return agentId;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Main entry point — starts the MCP server.
|
|
53
|
-
*/
|
|
54
|
-
async function main() {
|
|
55
|
-
// Create MCP server instance
|
|
56
|
-
const server = new McpServer(
|
|
57
|
-
{
|
|
58
|
-
name: 'awkit-symphony',
|
|
59
|
-
version,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
capabilities: {
|
|
63
|
-
tools: {},
|
|
64
|
-
},
|
|
65
|
-
}
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// Register all 12 tools
|
|
69
|
-
const { registerAllTools } = require('./index');
|
|
70
|
-
registerAllTools(server, getAgentId);
|
|
71
|
-
|
|
72
|
-
// Register agent on startup
|
|
73
|
-
orchestrator.registerAgent(agentId, agentName);
|
|
74
|
-
|
|
75
|
-
// Log to stderr (stdout is reserved for MCP JSON-RPC)
|
|
76
|
-
process.stderr.write(`🎼 Symphony MCP Server v${version}\n`);
|
|
77
|
-
process.stderr.write(` Agent: ${agentName} (${agentId})\n`);
|
|
78
|
-
process.stderr.write(` Transport: stdio\n`);
|
|
79
|
-
process.stderr.write(` Tools: 12 registered\n\n`);
|
|
80
|
-
|
|
81
|
-
// Create stdio transport and connect
|
|
82
|
-
const transport = new StdioServerTransport();
|
|
83
|
-
await server.connect(transport);
|
|
84
|
-
|
|
85
|
-
// Graceful shutdown
|
|
86
|
-
const shutdown = () => {
|
|
87
|
-
process.stderr.write('\n🛑 Symphony MCP Server shutting down...\n');
|
|
88
|
-
try {
|
|
89
|
-
orchestrator.unregisterAgent(agentId);
|
|
90
|
-
} catch (_) {
|
|
91
|
-
// Ignore errors during shutdown
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
db.close();
|
|
95
|
-
} catch (_) {
|
|
96
|
-
// Ignore
|
|
97
|
-
}
|
|
98
|
-
process.exit(0);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
process.on('SIGINT', shutdown);
|
|
102
|
-
process.on('SIGTERM', shutdown);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Run if executed directly
|
|
106
|
-
main().catch((err) => {
|
|
107
|
-
process.stderr.write(`❌ Fatal error: ${err.message}\n`);
|
|
108
|
-
process.stderr.write(`${err.stack}\n`);
|
|
109
|
-
process.exit(1);
|
|
110
|
-
});
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Symphony MCP Tools — Context Bus
|
|
3
|
-
* 2 tools for inter-agent communication via event pub/sub.
|
|
4
|
-
*/
|
|
5
|
-
const { z } = require('zod');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const CORE = path.join(__dirname, '..', '..', 'core');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register context bus tools on the MCP server.
|
|
12
|
-
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
13
|
-
* @param {() => string} getAgentId - Returns current agent ID
|
|
14
|
-
*/
|
|
15
|
-
function registerContextTools(server, getAgentId) {
|
|
16
|
-
// Tool 9: Broadcast event
|
|
17
|
-
server.tool(
|
|
18
|
-
'symphony_broadcast',
|
|
19
|
-
'Broadcast an event to other agents. Use to notify about schema changes, file modifications, or API updates.',
|
|
20
|
-
{
|
|
21
|
-
event_type: z
|
|
22
|
-
.enum(['file_modified', 'api_changed', 'schema_updated', 'dependency_added', 'custom'])
|
|
23
|
-
.describe('Type of event'),
|
|
24
|
-
payload: z
|
|
25
|
-
.object({
|
|
26
|
-
files: z.array(z.string()).optional().describe('Affected files'),
|
|
27
|
-
description: z.string().describe('Human-readable description'),
|
|
28
|
-
impact: z.enum(['low', 'medium', 'high']).default('medium').describe('Impact level'),
|
|
29
|
-
})
|
|
30
|
-
.describe('Event payload'),
|
|
31
|
-
},
|
|
32
|
-
async ({ event_type, payload }) => {
|
|
33
|
-
const cb = require(path.join(CORE, 'context-bus'));
|
|
34
|
-
const agentId = getAgentId();
|
|
35
|
-
|
|
36
|
-
cb.publish(agentId, event_type, payload);
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
content: [
|
|
40
|
-
{
|
|
41
|
-
type: 'text',
|
|
42
|
-
text: `Event broadcasted: ${event_type} — ${payload.description}`,
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// Tool 10: Query events
|
|
50
|
-
server.tool(
|
|
51
|
-
'symphony_events',
|
|
52
|
-
'Query recent events from other agents. Use to stay informed about changes made by teammates.',
|
|
53
|
-
{
|
|
54
|
-
since: z.string().optional().describe('ISO timestamp — only events after this time'),
|
|
55
|
-
event_type: z.string().optional().describe('Filter by event type'),
|
|
56
|
-
limit: z.number().int().min(1).max(100).default(20).describe('Max events to return'),
|
|
57
|
-
},
|
|
58
|
-
async ({ since, event_type, limit }) => {
|
|
59
|
-
const cb = require(path.join(CORE, 'context-bus'));
|
|
60
|
-
|
|
61
|
-
const filter = {};
|
|
62
|
-
if (since) filter.since = since;
|
|
63
|
-
if (event_type) filter.eventType = event_type;
|
|
64
|
-
filter.limit = limit;
|
|
65
|
-
|
|
66
|
-
const events = cb.query(filter);
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
content: [
|
|
70
|
-
{
|
|
71
|
-
type: 'text',
|
|
72
|
-
text: JSON.stringify(events, null, 2),
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
module.exports = { registerContextTools };
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Symphony MCP Tools — File Lock Management
|
|
3
|
-
* 3 tools for checking, acquiring, and releasing file locks.
|
|
4
|
-
*/
|
|
5
|
-
const { z } = require('zod');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const CORE = path.join(__dirname, '..', '..', 'core');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register file lock tools on the MCP server.
|
|
12
|
-
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
13
|
-
* @param {() => string} getAgentId - Returns current agent ID
|
|
14
|
-
*/
|
|
15
|
-
function registerLockTools(server, getAgentId) {
|
|
16
|
-
// Tool 6: Check file availability
|
|
17
|
-
server.tool(
|
|
18
|
-
'symphony_check_files',
|
|
19
|
-
'Check if files are available (not locked by another agent). Use before editing to avoid conflicts.',
|
|
20
|
-
{
|
|
21
|
-
files: z.array(z.string()).min(1).describe('File paths to check'),
|
|
22
|
-
},
|
|
23
|
-
async ({ files }) => {
|
|
24
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
25
|
-
const result = flm.checkFiles(files);
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
content: [
|
|
29
|
-
{
|
|
30
|
-
type: 'text',
|
|
31
|
-
text: JSON.stringify(result, null, 2),
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// Tool 7: Acquire file locks
|
|
39
|
-
server.tool(
|
|
40
|
-
'symphony_lock_files',
|
|
41
|
-
'Acquire locks on specific files to prevent other agents from editing them.',
|
|
42
|
-
{
|
|
43
|
-
task_id: z.string().describe('Task ID the locks are for'),
|
|
44
|
-
files: z.array(z.string()).min(1).describe('File paths to lock'),
|
|
45
|
-
},
|
|
46
|
-
async ({ task_id, files }) => {
|
|
47
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
48
|
-
const agentId = getAgentId();
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const result = flm.acquireLocks(agentId, task_id, files);
|
|
52
|
-
return {
|
|
53
|
-
content: [
|
|
54
|
-
{
|
|
55
|
-
type: 'text',
|
|
56
|
-
text: JSON.stringify({ success: true, ...result }, null, 2),
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
} catch (err) {
|
|
61
|
-
return {
|
|
62
|
-
content: [
|
|
63
|
-
{
|
|
64
|
-
type: 'text',
|
|
65
|
-
text: JSON.stringify(
|
|
66
|
-
{ success: false, error: err.message },
|
|
67
|
-
null,
|
|
68
|
-
2
|
|
69
|
-
),
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
isError: true,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
// Tool 8: Release file locks
|
|
79
|
-
server.tool(
|
|
80
|
-
'symphony_unlock_files',
|
|
81
|
-
'Release locks on specific files. Other agents can then edit these files.',
|
|
82
|
-
{
|
|
83
|
-
task_id: z.string().describe('Task ID the locks belong to'),
|
|
84
|
-
files: z.array(z.string()).min(1).describe('File paths to unlock'),
|
|
85
|
-
},
|
|
86
|
-
async ({ task_id, files }) => {
|
|
87
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
88
|
-
const agentId = getAgentId();
|
|
89
|
-
|
|
90
|
-
flm.releaseSpecificLocks(agentId, files);
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
content: [{ type: 'text', text: `Released locks: ${files.join(', ')}` }],
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
module.exports = { registerLockTools };
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Symphony MCP Tools — Status & Task Creation
|
|
3
|
-
* 2 tools for system status overview and creating new tasks.
|
|
4
|
-
*/
|
|
5
|
-
const { z } = require('zod');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const CORE = path.join(__dirname, '..', '..', 'core');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register status tools on the MCP server.
|
|
12
|
-
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
13
|
-
*/
|
|
14
|
-
function registerStatusTools(server) {
|
|
15
|
-
// Tool 11: System status
|
|
16
|
-
server.tool(
|
|
17
|
-
'symphony_status',
|
|
18
|
-
'Get full Symphony system status: connected agents, file locks, task queue, and statistics.',
|
|
19
|
-
{},
|
|
20
|
-
async () => {
|
|
21
|
-
const orchestrator = require(path.join(CORE, 'orchestrator'));
|
|
22
|
-
const status = orchestrator.getStatus();
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: 'text',
|
|
28
|
-
text: JSON.stringify(status, null, 2),
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
// Tool 12: Create a new task
|
|
36
|
-
server.tool(
|
|
37
|
-
'symphony_create_task',
|
|
38
|
-
'Create a new task in the Symphony queue. The task will be available for any agent to claim.',
|
|
39
|
-
{
|
|
40
|
-
title: z.string().describe('Task title'),
|
|
41
|
-
description: z.string().optional().describe('Detailed description'),
|
|
42
|
-
priority: z.number().int().min(1).max(3).default(2).describe('Priority: 1=high, 2=medium, 3=low'),
|
|
43
|
-
acceptance: z.string().optional().describe('Acceptance criteria'),
|
|
44
|
-
phase: z.string().optional().describe('Phase/milestone'),
|
|
45
|
-
estimated_files: z
|
|
46
|
-
.array(z.string())
|
|
47
|
-
.optional()
|
|
48
|
-
.describe('Files this task will likely edit (for pre-locking)'),
|
|
49
|
-
},
|
|
50
|
-
async ({ title, description, priority, acceptance, phase, estimated_files }) => {
|
|
51
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
52
|
-
|
|
53
|
-
const task = tm.createTask(title, {
|
|
54
|
-
description,
|
|
55
|
-
priority,
|
|
56
|
-
acceptance,
|
|
57
|
-
phase,
|
|
58
|
-
estimatedFiles: estimated_files,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
content: [
|
|
63
|
-
{
|
|
64
|
-
type: 'text',
|
|
65
|
-
text: JSON.stringify(
|
|
66
|
-
{
|
|
67
|
-
id: task.id,
|
|
68
|
-
title: task.title,
|
|
69
|
-
status: task.status,
|
|
70
|
-
priority: task.priority,
|
|
71
|
-
},
|
|
72
|
-
null,
|
|
73
|
-
2
|
|
74
|
-
),
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
module.exports = { registerStatusTools };
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Symphony MCP Tools — Task Management
|
|
3
|
-
* 5 tools for task lifecycle: list, claim, progress, complete, abandon
|
|
4
|
-
*/
|
|
5
|
-
const { z } = require('zod');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
const CORE = path.join(__dirname, '..', '..', 'core');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register all task management tools on the MCP server.
|
|
12
|
-
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
13
|
-
* @param {() => string} getAgentId - Returns current agent ID
|
|
14
|
-
*/
|
|
15
|
-
function registerTaskTools(server, getAgentId) {
|
|
16
|
-
// Tool 1: List available tasks
|
|
17
|
-
server.tool(
|
|
18
|
-
'symphony_available_tasks',
|
|
19
|
-
'List tasks available for claiming. Use filter "ready" for unclaimed tasks, "my" for your tasks, or "all" for everything.',
|
|
20
|
-
{
|
|
21
|
-
filter: z.enum(['ready', 'all', 'my']).default('ready').describe('Task filter'),
|
|
22
|
-
limit: z.number().int().min(1).max(100).default(10).describe('Max results'),
|
|
23
|
-
},
|
|
24
|
-
async ({ filter, limit }) => {
|
|
25
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
26
|
-
const agentId = getAgentId();
|
|
27
|
-
|
|
28
|
-
let tasks;
|
|
29
|
-
switch (filter) {
|
|
30
|
-
case 'ready':
|
|
31
|
-
tasks = tm.listTasks({ status: 'ready', limit });
|
|
32
|
-
break;
|
|
33
|
-
case 'my':
|
|
34
|
-
tasks = tm.listTasks({ agentId, limit });
|
|
35
|
-
break;
|
|
36
|
-
case 'all':
|
|
37
|
-
tasks = tm.listTasks({ limit });
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
tasks = tm.listTasks({ status: 'ready', limit });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
content: [
|
|
45
|
-
{
|
|
46
|
-
type: 'text',
|
|
47
|
-
text: JSON.stringify(
|
|
48
|
-
tasks.map((t) => ({
|
|
49
|
-
id: t.id,
|
|
50
|
-
title: t.title,
|
|
51
|
-
description: t.description,
|
|
52
|
-
status: t.status,
|
|
53
|
-
priority: t.priority,
|
|
54
|
-
acceptance: t.acceptance,
|
|
55
|
-
phase: t.phase,
|
|
56
|
-
estimated_files: t.estimated_files,
|
|
57
|
-
})),
|
|
58
|
-
null,
|
|
59
|
-
2
|
|
60
|
-
),
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Tool 2: Claim a task
|
|
68
|
-
server.tool(
|
|
69
|
-
'symphony_claim_task',
|
|
70
|
-
'Claim a task to start working on it. This acquires file locks and prepares a workspace.',
|
|
71
|
-
{
|
|
72
|
-
task_id: z.string().describe('Task ID to claim'),
|
|
73
|
-
agent_name: z.string().optional().describe('Optional agent display name'),
|
|
74
|
-
},
|
|
75
|
-
async ({ task_id, agent_name }) => {
|
|
76
|
-
const orchestrator = require(path.join(CORE, 'orchestrator'));
|
|
77
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
78
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
79
|
-
const agentId = getAgentId();
|
|
80
|
-
|
|
81
|
-
// Ensure agent is registered
|
|
82
|
-
orchestrator.registerAgent(agentId, agent_name || agentId);
|
|
83
|
-
|
|
84
|
-
// Dispatch task to agent
|
|
85
|
-
const task = orchestrator.dispatchTask(agentId, task_id);
|
|
86
|
-
|
|
87
|
-
// Acquire file locks if estimated files are provided
|
|
88
|
-
let lockedFiles = [];
|
|
89
|
-
if (task.estimated_files && task.estimated_files.length > 0) {
|
|
90
|
-
const lockResult = flm.acquireLocks(agentId, task_id, task.estimated_files);
|
|
91
|
-
lockedFiles = lockResult.acquired || task.estimated_files;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
content: [
|
|
96
|
-
{
|
|
97
|
-
type: 'text',
|
|
98
|
-
text: JSON.stringify(
|
|
99
|
-
{
|
|
100
|
-
task_id: task.id,
|
|
101
|
-
title: task.title,
|
|
102
|
-
workspace_path: task.workspace_path || null,
|
|
103
|
-
branch: task.branch || null,
|
|
104
|
-
locked_files: lockedFiles,
|
|
105
|
-
acceptance_criteria: task.acceptance || null,
|
|
106
|
-
description: task.description || null,
|
|
107
|
-
},
|
|
108
|
-
null,
|
|
109
|
-
2
|
|
110
|
-
),
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
// Tool 3: Report progress
|
|
118
|
-
server.tool(
|
|
119
|
-
'symphony_report_progress',
|
|
120
|
-
'Report progress on a claimed task. Updates percentage and optionally current file being edited.',
|
|
121
|
-
{
|
|
122
|
-
task_id: z.string().describe('Task ID'),
|
|
123
|
-
progress: z.number().int().min(0).max(100).describe('Progress percentage 0-100'),
|
|
124
|
-
current_file: z.string().optional().describe('Current file being edited'),
|
|
125
|
-
last_action: z.string().optional().describe('Last action performed'),
|
|
126
|
-
},
|
|
127
|
-
async ({ task_id, progress, current_file, last_action }) => {
|
|
128
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
129
|
-
tm.updateProgress(task_id, progress, { currentFile: current_file, lastAction: last_action });
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
content: [{ type: 'text', text: `Progress updated: ${progress}%` }],
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
// Tool 4: Complete a task
|
|
138
|
-
server.tool(
|
|
139
|
-
'symphony_complete_task',
|
|
140
|
-
'Mark a task as complete. Releases file locks and marks agent as idle.',
|
|
141
|
-
{
|
|
142
|
-
task_id: z.string().describe('Task ID'),
|
|
143
|
-
summary: z.string().describe('Summary of what was done'),
|
|
144
|
-
files_changed: z.array(z.string()).default([]).describe('List of changed files'),
|
|
145
|
-
},
|
|
146
|
-
async ({ task_id, summary, files_changed }) => {
|
|
147
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
148
|
-
const orchestrator = require(path.join(CORE, 'orchestrator'));
|
|
149
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
150
|
-
const agentId = getAgentId();
|
|
151
|
-
|
|
152
|
-
// Complete the task
|
|
153
|
-
const task = tm.completeTask(task_id, summary, files_changed);
|
|
154
|
-
|
|
155
|
-
// Release all file locks for this agent
|
|
156
|
-
flm.releaseLocks(agentId);
|
|
157
|
-
|
|
158
|
-
// Mark agent as idle
|
|
159
|
-
orchestrator.markIdle(agentId);
|
|
160
|
-
|
|
161
|
-
// Check for next available task
|
|
162
|
-
const nextTasks = tm.listTasks({ status: 'ready', limit: 1 });
|
|
163
|
-
const nextTask = nextTasks.length > 0 ? nextTasks[0] : null;
|
|
164
|
-
|
|
165
|
-
return {
|
|
166
|
-
content: [
|
|
167
|
-
{
|
|
168
|
-
type: 'text',
|
|
169
|
-
text: JSON.stringify(
|
|
170
|
-
{
|
|
171
|
-
status: 'completed',
|
|
172
|
-
merge_status: 'pr_created', // TODO: implement actual merge logic
|
|
173
|
-
next_task: nextTask
|
|
174
|
-
? { id: nextTask.id, title: nextTask.title, priority: nextTask.priority }
|
|
175
|
-
: null,
|
|
176
|
-
},
|
|
177
|
-
null,
|
|
178
|
-
2
|
|
179
|
-
),
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
// Tool 5: Abandon a task
|
|
187
|
-
server.tool(
|
|
188
|
-
'symphony_abandon_task',
|
|
189
|
-
'Abandon a task you are working on. Releases all file locks and returns the task to the queue.',
|
|
190
|
-
{
|
|
191
|
-
task_id: z.string().describe('Task ID'),
|
|
192
|
-
reason: z.string().describe('Reason for abandoning'),
|
|
193
|
-
},
|
|
194
|
-
async ({ task_id, reason }) => {
|
|
195
|
-
const tm = require(path.join(CORE, 'task-manager'));
|
|
196
|
-
const orchestrator = require(path.join(CORE, 'orchestrator'));
|
|
197
|
-
const flm = require(path.join(CORE, 'file-lock-manager'));
|
|
198
|
-
const agentId = getAgentId();
|
|
199
|
-
|
|
200
|
-
// Abandon the task
|
|
201
|
-
tm.abandonTask(task_id, reason);
|
|
202
|
-
|
|
203
|
-
// Release file locks
|
|
204
|
-
flm.releaseLocks(agentId);
|
|
205
|
-
|
|
206
|
-
// Mark agent idle
|
|
207
|
-
orchestrator.markIdle(agentId);
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
content: [{ type: 'text', text: `Task ${task_id} abandoned: ${reason}` }],
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
module.exports = { registerTaskTools };
|