@mandujs/mcp 0.12.2 → 0.16.0
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 +366 -367
- package/package.json +3 -2
- package/src/activity-monitor.ts +847 -847
- package/src/index.ts +106 -106
- package/src/tools/ate.ts +129 -0
- package/src/tools/generate.ts +7 -4
- package/src/tools/guard.ts +17 -4
- package/src/tools/hydration.ts +10 -10
- package/src/tools/index.ts +4 -1
- package/src/tools/spec.ts +80 -159
- package/src/utils/project.ts +22 -12
package/src/index.ts
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @mandujs/mcp - MCP Server for Mandu Framework
|
|
5
|
-
*
|
|
6
|
-
* DNA 기능 통합:
|
|
7
|
-
* - DNA-001: 플러그인 기반 도구 등록
|
|
8
|
-
* - DNA-006: 설정 핫 리로드
|
|
9
|
-
* - DNA-007: 에러 추출 및 분류
|
|
10
|
-
* - DNA-008: 구조화된 로깅
|
|
11
|
-
* - DNA-016: Pre/Post 도구 훅
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Main exports
|
|
15
|
-
export { ManduMcpServer, startServer } from "./server.js";
|
|
16
|
-
|
|
17
|
-
// Registry exports (DNA-001)
|
|
18
|
-
export {
|
|
19
|
-
McpToolRegistry,
|
|
20
|
-
mcpToolRegistry,
|
|
21
|
-
type ToolRegistration,
|
|
22
|
-
type RegistryEvent,
|
|
23
|
-
type RegistryDump,
|
|
24
|
-
} from "./registry/index.js";
|
|
25
|
-
|
|
26
|
-
// Adapter exports
|
|
27
|
-
export {
|
|
28
|
-
toolToPlugin,
|
|
29
|
-
pluginToTool,
|
|
30
|
-
moduleToPlugins,
|
|
31
|
-
pluginsToTools,
|
|
32
|
-
pluginsToHandlers,
|
|
33
|
-
monitorEventToRecord,
|
|
34
|
-
recordToMonitorEvent,
|
|
35
|
-
} from "./adapters/index.js";
|
|
36
|
-
|
|
37
|
-
// Executor exports (DNA-007)
|
|
38
|
-
export {
|
|
39
|
-
formatMcpError,
|
|
40
|
-
createToolResponse,
|
|
41
|
-
isErrorResponse,
|
|
42
|
-
extractErrorFromResponse,
|
|
43
|
-
logToolError,
|
|
44
|
-
ToolExecutor,
|
|
45
|
-
createToolExecutor,
|
|
46
|
-
type McpErrorResponse,
|
|
47
|
-
type McpToolResponse,
|
|
48
|
-
type ToolExecutorOptions,
|
|
49
|
-
type ExecutionResult,
|
|
50
|
-
} from "./executor/index.js";
|
|
51
|
-
|
|
52
|
-
// Hook exports (DNA-016)
|
|
53
|
-
export {
|
|
54
|
-
mcpHookRegistry,
|
|
55
|
-
registerDefaultMcpHooks,
|
|
56
|
-
slowToolLoggingHook,
|
|
57
|
-
statsCollectorHook,
|
|
58
|
-
getToolStats,
|
|
59
|
-
resetToolStats,
|
|
60
|
-
createArgValidationHook,
|
|
61
|
-
startMcpConfigWatcher,
|
|
62
|
-
type McpToolContext,
|
|
63
|
-
type McpPreToolHook,
|
|
64
|
-
type McpPostToolHook,
|
|
65
|
-
type McpConfigWatcherOptions,
|
|
66
|
-
} from "./hooks/index.js";
|
|
67
|
-
|
|
68
|
-
// Logging exports (DNA-008)
|
|
69
|
-
export {
|
|
70
|
-
createMcpActivityTransport,
|
|
71
|
-
setupMcpLogging,
|
|
72
|
-
teardownMcpLogging,
|
|
73
|
-
dispatchMonitorEvent,
|
|
74
|
-
createMcpLogRecord,
|
|
75
|
-
MCP_TRANSPORT_ID,
|
|
76
|
-
type McpTransportOptions,
|
|
77
|
-
} from "./logging/index.js";
|
|
78
|
-
|
|
79
|
-
// Tools exports
|
|
80
|
-
export {
|
|
81
|
-
registerBuiltinTools,
|
|
82
|
-
getToolCounts,
|
|
83
|
-
getToolsSummary,
|
|
84
|
-
} from "./tools/index.js";
|
|
85
|
-
|
|
86
|
-
// CLI entry point
|
|
87
|
-
import { startServer } from "./server.js";
|
|
88
|
-
import path from "path";
|
|
89
|
-
|
|
90
|
-
// Start server if run directly
|
|
91
|
-
if (import.meta.main) {
|
|
92
|
-
const args = process.argv.slice(2);
|
|
93
|
-
const globalMode = args.includes("--global");
|
|
94
|
-
const rootIndex = args.indexOf("--root");
|
|
95
|
-
const rootArg = rootIndex >= 0 ? args[rootIndex + 1] : undefined;
|
|
96
|
-
const projectRoot = rootArg
|
|
97
|
-
? path.resolve(rootArg)
|
|
98
|
-
: globalMode
|
|
99
|
-
? process.cwd()
|
|
100
|
-
: undefined;
|
|
101
|
-
|
|
102
|
-
startServer(projectRoot).catch((error) => {
|
|
103
|
-
console.error("Failed to start Mandu MCP server:", error);
|
|
104
|
-
process.exit(1);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @mandujs/mcp - MCP Server for Mandu Framework
|
|
5
|
+
*
|
|
6
|
+
* DNA 기능 통합:
|
|
7
|
+
* - DNA-001: 플러그인 기반 도구 등록
|
|
8
|
+
* - DNA-006: 설정 핫 리로드
|
|
9
|
+
* - DNA-007: 에러 추출 및 분류
|
|
10
|
+
* - DNA-008: 구조화된 로깅
|
|
11
|
+
* - DNA-016: Pre/Post 도구 훅
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Main exports
|
|
15
|
+
export { ManduMcpServer, startServer } from "./server.js";
|
|
16
|
+
|
|
17
|
+
// Registry exports (DNA-001)
|
|
18
|
+
export {
|
|
19
|
+
McpToolRegistry,
|
|
20
|
+
mcpToolRegistry,
|
|
21
|
+
type ToolRegistration,
|
|
22
|
+
type RegistryEvent,
|
|
23
|
+
type RegistryDump,
|
|
24
|
+
} from "./registry/index.js";
|
|
25
|
+
|
|
26
|
+
// Adapter exports
|
|
27
|
+
export {
|
|
28
|
+
toolToPlugin,
|
|
29
|
+
pluginToTool,
|
|
30
|
+
moduleToPlugins,
|
|
31
|
+
pluginsToTools,
|
|
32
|
+
pluginsToHandlers,
|
|
33
|
+
monitorEventToRecord,
|
|
34
|
+
recordToMonitorEvent,
|
|
35
|
+
} from "./adapters/index.js";
|
|
36
|
+
|
|
37
|
+
// Executor exports (DNA-007)
|
|
38
|
+
export {
|
|
39
|
+
formatMcpError,
|
|
40
|
+
createToolResponse,
|
|
41
|
+
isErrorResponse,
|
|
42
|
+
extractErrorFromResponse,
|
|
43
|
+
logToolError,
|
|
44
|
+
ToolExecutor,
|
|
45
|
+
createToolExecutor,
|
|
46
|
+
type McpErrorResponse,
|
|
47
|
+
type McpToolResponse,
|
|
48
|
+
type ToolExecutorOptions,
|
|
49
|
+
type ExecutionResult,
|
|
50
|
+
} from "./executor/index.js";
|
|
51
|
+
|
|
52
|
+
// Hook exports (DNA-016)
|
|
53
|
+
export {
|
|
54
|
+
mcpHookRegistry,
|
|
55
|
+
registerDefaultMcpHooks,
|
|
56
|
+
slowToolLoggingHook,
|
|
57
|
+
statsCollectorHook,
|
|
58
|
+
getToolStats,
|
|
59
|
+
resetToolStats,
|
|
60
|
+
createArgValidationHook,
|
|
61
|
+
startMcpConfigWatcher,
|
|
62
|
+
type McpToolContext,
|
|
63
|
+
type McpPreToolHook,
|
|
64
|
+
type McpPostToolHook,
|
|
65
|
+
type McpConfigWatcherOptions,
|
|
66
|
+
} from "./hooks/index.js";
|
|
67
|
+
|
|
68
|
+
// Logging exports (DNA-008)
|
|
69
|
+
export {
|
|
70
|
+
createMcpActivityTransport,
|
|
71
|
+
setupMcpLogging,
|
|
72
|
+
teardownMcpLogging,
|
|
73
|
+
dispatchMonitorEvent,
|
|
74
|
+
createMcpLogRecord,
|
|
75
|
+
MCP_TRANSPORT_ID,
|
|
76
|
+
type McpTransportOptions,
|
|
77
|
+
} from "./logging/index.js";
|
|
78
|
+
|
|
79
|
+
// Tools exports
|
|
80
|
+
export {
|
|
81
|
+
registerBuiltinTools,
|
|
82
|
+
getToolCounts,
|
|
83
|
+
getToolsSummary,
|
|
84
|
+
} from "./tools/index.js";
|
|
85
|
+
|
|
86
|
+
// CLI entry point
|
|
87
|
+
import { startServer } from "./server.js";
|
|
88
|
+
import path from "path";
|
|
89
|
+
|
|
90
|
+
// Start server if run directly
|
|
91
|
+
if (import.meta.main) {
|
|
92
|
+
const args = process.argv.slice(2);
|
|
93
|
+
const globalMode = args.includes("--global");
|
|
94
|
+
const rootIndex = args.indexOf("--root");
|
|
95
|
+
const rootArg = rootIndex >= 0 ? args[rootIndex + 1] : undefined;
|
|
96
|
+
const projectRoot = rootArg
|
|
97
|
+
? path.resolve(rootArg)
|
|
98
|
+
: globalMode
|
|
99
|
+
? process.cwd()
|
|
100
|
+
: undefined;
|
|
101
|
+
|
|
102
|
+
startServer(projectRoot).catch((error) => {
|
|
103
|
+
console.error("Failed to start Mandu MCP server:", error);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
});
|
|
106
|
+
}
|
package/src/tools/ate.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { ateExtract, ateGenerate, ateRun, ateReport, ateHeal, ateImpact } from "@mandujs/ate";
|
|
3
|
+
|
|
4
|
+
export const ateToolDefinitions: Tool[] = [
|
|
5
|
+
{
|
|
6
|
+
name: "mandu.ate.extract",
|
|
7
|
+
description: "ATE: AST 기반 상호작용 그래프 추출",
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
repoRoot: { type: "string" },
|
|
12
|
+
tsconfigPath: { type: "string" },
|
|
13
|
+
routeGlobs: { type: "array", items: { type: "string" } },
|
|
14
|
+
buildSalt: { type: "string" },
|
|
15
|
+
},
|
|
16
|
+
required: ["repoRoot"],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "mandu.ate.generate",
|
|
21
|
+
description: "ATE: 시나리오 생성 + Playwright spec codegen",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
repoRoot: { type: "string" },
|
|
26
|
+
oracleLevel: { type: "string", enum: ["L0", "L1", "L2", "L3"] },
|
|
27
|
+
onlyRoutes: { type: "array", items: { type: "string" } },
|
|
28
|
+
},
|
|
29
|
+
required: ["repoRoot"],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "mandu.ate.run",
|
|
34
|
+
description: "ATE: Playwright runner 실행(artifacts 수집)",
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
repoRoot: { type: "string" },
|
|
39
|
+
baseURL: { type: "string" },
|
|
40
|
+
ci: { type: "boolean" },
|
|
41
|
+
headless: { type: "boolean" },
|
|
42
|
+
browsers: { type: "array", items: { type: "string", enum: ["chromium", "firefox", "webkit"] } },
|
|
43
|
+
},
|
|
44
|
+
required: ["repoRoot"],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "mandu.ate.report",
|
|
49
|
+
description: "ATE: summary.json 생성",
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: "object",
|
|
52
|
+
properties: {
|
|
53
|
+
repoRoot: { type: "string" },
|
|
54
|
+
runId: { type: "string" },
|
|
55
|
+
startedAt: { type: "string" },
|
|
56
|
+
finishedAt: { type: "string" },
|
|
57
|
+
exitCode: { type: "number" },
|
|
58
|
+
oracleLevel: { type: "string", enum: ["L0", "L1", "L2", "L3"] },
|
|
59
|
+
impact: {
|
|
60
|
+
type: "object",
|
|
61
|
+
properties: {
|
|
62
|
+
mode: { type: "string", enum: ["full", "subset"] },
|
|
63
|
+
changedFiles: { type: "array", items: { type: "string" } },
|
|
64
|
+
selectedRoutes: { type: "array", items: { type: "string" } },
|
|
65
|
+
},
|
|
66
|
+
required: ["mode", "changedFiles", "selectedRoutes"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: ["repoRoot", "runId", "startedAt", "finishedAt", "exitCode"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "mandu.ate.heal",
|
|
74
|
+
description: "ATE: 실패 원인 분류 + 복구 제안(diff) 생성 (자동 커밋 금지)",
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {
|
|
78
|
+
repoRoot: { type: "string" },
|
|
79
|
+
runId: { type: "string" },
|
|
80
|
+
},
|
|
81
|
+
required: ["repoRoot", "runId"],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "mandu.ate.impact",
|
|
86
|
+
description: "ATE: git diff 기반 subset 계산",
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: "object",
|
|
89
|
+
properties: {
|
|
90
|
+
repoRoot: { type: "string" },
|
|
91
|
+
base: { type: "string" },
|
|
92
|
+
head: { type: "string" },
|
|
93
|
+
},
|
|
94
|
+
required: ["repoRoot"],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
export function ateTools(projectRoot: string) {
|
|
100
|
+
return {
|
|
101
|
+
"mandu.ate.extract": async (args: Record<string, unknown>) => {
|
|
102
|
+
return await ateExtract(args as any);
|
|
103
|
+
},
|
|
104
|
+
"mandu.ate.generate": async (args: Record<string, unknown>) => {
|
|
105
|
+
return ateGenerate(args as any);
|
|
106
|
+
},
|
|
107
|
+
"mandu.ate.run": async (args: Record<string, unknown>) => {
|
|
108
|
+
return await ateRun(args as any);
|
|
109
|
+
},
|
|
110
|
+
"mandu.ate.report": async (args: Record<string, unknown>) => {
|
|
111
|
+
const input = args as any;
|
|
112
|
+
return await ateReport({
|
|
113
|
+
repoRoot: input.repoRoot,
|
|
114
|
+
runId: input.runId,
|
|
115
|
+
startedAt: input.startedAt,
|
|
116
|
+
finishedAt: input.finishedAt,
|
|
117
|
+
exitCode: input.exitCode,
|
|
118
|
+
oracleLevel: input.oracleLevel ?? "L1",
|
|
119
|
+
impact: input.impact,
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
"mandu.ate.heal": async (args: Record<string, unknown>) => {
|
|
123
|
+
return ateHeal(args as any);
|
|
124
|
+
},
|
|
125
|
+
"mandu.ate.impact": async (args: Record<string, unknown>) => {
|
|
126
|
+
return ateImpact(args as any);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
package/src/tools/generate.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
import { loadManifest, generateRoutes, type GeneratedMap } from "@mandujs/core";
|
|
2
|
+
import { loadManifest, generateRoutes, generateManifest, GENERATED_RELATIVE_PATHS, type GeneratedMap } from "@mandujs/core";
|
|
3
3
|
import { getProjectPaths, readJsonFile } from "../utils/project.js";
|
|
4
4
|
|
|
5
5
|
export const generateToolDefinitions: Tool[] = [
|
|
@@ -36,7 +36,10 @@ export function generateTools(projectRoot: string) {
|
|
|
36
36
|
mandu_generate: async (args: Record<string, unknown>) => {
|
|
37
37
|
const { dryRun } = args as { dryRun?: boolean };
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// Regenerate manifest from FS Routes first
|
|
40
|
+
const fsResult = await generateManifest(projectRoot);
|
|
41
|
+
|
|
42
|
+
// Load the freshly generated manifest
|
|
40
43
|
const manifestResult = await loadManifest(paths.manifestPath);
|
|
41
44
|
if (!manifestResult.success || !manifestResult.data) {
|
|
42
45
|
return { error: manifestResult.errors };
|
|
@@ -50,11 +53,11 @@ export function generateTools(projectRoot: string) {
|
|
|
50
53
|
|
|
51
54
|
for (const route of routes) {
|
|
52
55
|
// Server handler
|
|
53
|
-
wouldCreate.push(
|
|
56
|
+
wouldCreate.push(`${GENERATED_RELATIVE_PATHS.serverRoutes}/${route.id}.route.ts`);
|
|
54
57
|
|
|
55
58
|
// Page component (for page kind)
|
|
56
59
|
if (route.kind === "page") {
|
|
57
|
-
wouldCreate.push(
|
|
60
|
+
wouldCreate.push(`${GENERATED_RELATIVE_PATHS.webRoutes}/${route.id}.route.tsx`);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
// Slot file (only if not exists)
|
package/src/tools/guard.ts
CHANGED
|
@@ -303,6 +303,11 @@ export const guardToolDefinitions: Tool[] = [
|
|
|
303
303
|
enum: ["auth", "crud", "api", "ui", "integration", "data", "util", "config", "other"],
|
|
304
304
|
description: "Feature category (auto-detected if not specified)",
|
|
305
305
|
},
|
|
306
|
+
preset: {
|
|
307
|
+
type: "string",
|
|
308
|
+
enum: ["fsd", "clean", "hexagonal", "atomic", "cqrs", "mandu"],
|
|
309
|
+
description: "Architecture preset (default: mandu). Use 'cqrs' for Command/Query separation.",
|
|
310
|
+
},
|
|
306
311
|
},
|
|
307
312
|
required: ["intent"],
|
|
308
313
|
},
|
|
@@ -332,6 +337,11 @@ export const guardToolDefinitions: Tool[] = [
|
|
|
332
337
|
type: "boolean",
|
|
333
338
|
description: "If true, overwrite existing files (default: false)",
|
|
334
339
|
},
|
|
340
|
+
preset: {
|
|
341
|
+
type: "string",
|
|
342
|
+
enum: ["fsd", "clean", "hexagonal", "atomic", "cqrs", "mandu"],
|
|
343
|
+
description: "Architecture preset (default: mandu)",
|
|
344
|
+
},
|
|
335
345
|
},
|
|
336
346
|
required: ["intent"],
|
|
337
347
|
},
|
|
@@ -437,7 +447,7 @@ export function guardTools(projectRoot: string) {
|
|
|
437
447
|
switch (error.errorType) {
|
|
438
448
|
case "SPEC_ERROR":
|
|
439
449
|
analysis.category = "Specification Error";
|
|
440
|
-
analysis.fixLocation = error.fix?.file || "
|
|
450
|
+
analysis.fixLocation = error.fix?.file || ".mandu/routes.manifest.json";
|
|
441
451
|
analysis.actions = [
|
|
442
452
|
"Check the spec file for JSON syntax errors",
|
|
443
453
|
"Validate route IDs are unique",
|
|
@@ -966,11 +976,12 @@ Mandu.filling()
|
|
|
966
976
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
967
977
|
|
|
968
978
|
mandu_negotiate: async (args: Record<string, unknown>) => {
|
|
969
|
-
const { intent, requirements, constraints, category } = args as {
|
|
979
|
+
const { intent, requirements, constraints, category, preset } = args as {
|
|
970
980
|
intent: string;
|
|
971
981
|
requirements?: string[];
|
|
972
982
|
constraints?: string[];
|
|
973
983
|
category?: FeatureCategory;
|
|
984
|
+
preset?: GuardPreset;
|
|
974
985
|
};
|
|
975
986
|
|
|
976
987
|
if (!intent) {
|
|
@@ -985,6 +996,7 @@ Mandu.filling()
|
|
|
985
996
|
requirements,
|
|
986
997
|
constraints,
|
|
987
998
|
category,
|
|
999
|
+
preset,
|
|
988
1000
|
};
|
|
989
1001
|
|
|
990
1002
|
const result = await negotiate(request, projectRoot);
|
|
@@ -1029,11 +1041,12 @@ Mandu.filling()
|
|
|
1029
1041
|
},
|
|
1030
1042
|
|
|
1031
1043
|
mandu_generate_scaffold: async (args: Record<string, unknown>) => {
|
|
1032
|
-
const { intent, category, dryRun = false, overwrite = false } = args as {
|
|
1044
|
+
const { intent, category, dryRun = false, overwrite = false, preset } = args as {
|
|
1033
1045
|
intent: string;
|
|
1034
1046
|
category?: FeatureCategory;
|
|
1035
1047
|
dryRun?: boolean;
|
|
1036
1048
|
overwrite?: boolean;
|
|
1049
|
+
preset?: GuardPreset;
|
|
1037
1050
|
};
|
|
1038
1051
|
|
|
1039
1052
|
if (!intent) {
|
|
@@ -1044,7 +1057,7 @@ Mandu.filling()
|
|
|
1044
1057
|
}
|
|
1045
1058
|
|
|
1046
1059
|
// 먼저 협상하여 구조 계획 얻기
|
|
1047
|
-
const plan = await negotiate({ intent, category }, projectRoot);
|
|
1060
|
+
const plan = await negotiate({ intent, category, preset }, projectRoot);
|
|
1048
1061
|
|
|
1049
1062
|
if (!plan.approved) {
|
|
1050
1063
|
return {
|
package/src/tools/hydration.ts
CHANGED
|
@@ -318,8 +318,8 @@ export function hydrationTools(projectRoot: string) {
|
|
|
318
318
|
};
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
// Create client slot file in
|
|
322
|
-
const clientModulePath = `
|
|
321
|
+
// Create client slot file in spec/slots/
|
|
322
|
+
const clientModulePath = `spec/slots/${routeId}.client.tsx`;
|
|
323
323
|
const clientFilePath = path.join(projectRoot, clientModulePath);
|
|
324
324
|
|
|
325
325
|
// Check if file already exists
|
|
@@ -378,19 +378,19 @@ function generateClientSlotTemplate(routeId: string, slotModule?: string): strin
|
|
|
378
378
|
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
379
379
|
.join("");
|
|
380
380
|
|
|
381
|
-
const typeImport = slotModule
|
|
382
|
-
? `// Import types from server slot if needed (adjust path to your project)
|
|
383
|
-
// import type { LoaderData } from "../../../spec/slots/${routeId}.slot";
|
|
384
|
-
|
|
385
|
-
`
|
|
386
|
-
: "";
|
|
381
|
+
const typeImport = slotModule
|
|
382
|
+
? `// Import types from server slot if needed (adjust path to your project)
|
|
383
|
+
// import type { LoaderData } from "../../../spec/slots/${routeId}.slot";
|
|
384
|
+
|
|
385
|
+
`
|
|
386
|
+
: "";
|
|
387
387
|
|
|
388
388
|
return `/**
|
|
389
389
|
* ${pascalCase} Client Slot
|
|
390
390
|
* 브라우저에서 실행되는 클라이언트 로직
|
|
391
391
|
*/
|
|
392
392
|
|
|
393
|
-
import { ManduClient } from "@mandujs/core/client";
|
|
393
|
+
import { ManduClient } from "@mandujs/core/client";
|
|
394
394
|
import { useState, useCallback } from "react";
|
|
395
395
|
|
|
396
396
|
${typeImport}// 서버에서 전달받는 데이터 타입
|
|
@@ -399,7 +399,7 @@ interface ServerData {
|
|
|
399
399
|
[key: string]: unknown;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
export default ManduClient.island<ServerData>({
|
|
402
|
+
export default ManduClient.island<ServerData>({
|
|
403
403
|
/**
|
|
404
404
|
* Setup Phase
|
|
405
405
|
* - 서버 데이터를 받아 클라이언트 상태 초기화
|
package/src/tools/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ export { brainTools, brainToolDefinitions } from "./brain.js";
|
|
|
22
22
|
export { runtimeTools, runtimeToolDefinitions } from "./runtime.js";
|
|
23
23
|
export { seoTools, seoToolDefinitions } from "./seo.js";
|
|
24
24
|
export { projectTools, projectToolDefinitions } from "./project.js";
|
|
25
|
+
export { ateTools, ateToolDefinitions } from "./ate.js";
|
|
25
26
|
|
|
26
27
|
// 도구 모듈 import (등록용)
|
|
27
28
|
import { specTools, specToolDefinitions } from "./spec.js";
|
|
@@ -36,13 +37,14 @@ import { brainTools, brainToolDefinitions } from "./brain.js";
|
|
|
36
37
|
import { runtimeTools, runtimeToolDefinitions } from "./runtime.js";
|
|
37
38
|
import { seoTools, seoToolDefinitions } from "./seo.js";
|
|
38
39
|
import { projectTools, projectToolDefinitions } from "./project.js";
|
|
40
|
+
import { ateTools, ateToolDefinitions } from "./ate.js";
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* 도구 모듈 정보
|
|
42
44
|
*/
|
|
43
45
|
interface ToolModule {
|
|
44
46
|
category: string;
|
|
45
|
-
definitions:
|
|
47
|
+
definitions: any;
|
|
46
48
|
handlers: (
|
|
47
49
|
projectRoot: string,
|
|
48
50
|
server?: Server,
|
|
@@ -67,6 +69,7 @@ const TOOL_MODULES: ToolModule[] = [
|
|
|
67
69
|
{ category: "runtime", definitions: runtimeToolDefinitions, handlers: runtimeTools },
|
|
68
70
|
{ category: "seo", definitions: seoToolDefinitions, handlers: seoTools },
|
|
69
71
|
{ category: "project", definitions: projectToolDefinitions, handlers: projectTools as ToolModule["handlers"], requiresServer: true },
|
|
72
|
+
{ category: "ate", definitions: ateToolDefinitions as any, handlers: ateTools as any },
|
|
70
73
|
];
|
|
71
74
|
|
|
72
75
|
/**
|