@musashishao/agent-kit 1.2.2 → 1.4.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.
Files changed (40) hide show
  1. package/.agent/mcp-gateway/README.md +121 -0
  2. package/.agent/mcp-gateway/dist/index.d.ts +11 -0
  3. package/.agent/mcp-gateway/dist/index.js +504 -0
  4. package/.agent/mcp-gateway/dist/sync/debouncer.d.ts +56 -0
  5. package/.agent/mcp-gateway/dist/sync/debouncer.js +112 -0
  6. package/.agent/mcp-gateway/dist/sync/incremental_syncer.d.ts +58 -0
  7. package/.agent/mcp-gateway/dist/sync/incremental_syncer.js +172 -0
  8. package/.agent/mcp-gateway/dist/sync/index.d.ts +6 -0
  9. package/.agent/mcp-gateway/dist/sync/index.js +6 -0
  10. package/.agent/mcp-gateway/dist/sync/timestamp_checker.d.ts +69 -0
  11. package/.agent/mcp-gateway/dist/sync/timestamp_checker.js +169 -0
  12. package/.agent/mcp-gateway/package.json +28 -0
  13. package/.agent/mcp-gateway/src/index.ts +608 -0
  14. package/.agent/mcp-gateway/src/sync/debouncer.ts +129 -0
  15. package/.agent/mcp-gateway/src/sync/incremental_syncer.ts +237 -0
  16. package/.agent/mcp-gateway/src/sync/index.ts +7 -0
  17. package/.agent/mcp-gateway/src/sync/timestamp_checker.ts +194 -0
  18. package/.agent/scripts/ak_cli.py +549 -0
  19. package/.agent/scripts/setup_host.py +557 -0
  20. package/.agent/scripts/verify_install.py +174 -0
  21. package/.agent/skills/app-builder/SKILL.md +51 -1
  22. package/.agent/skills/app-builder/scripts/generate_ai_infra.py +510 -0
  23. package/.agent/skills/documentation-templates/SKILL.md +9 -1
  24. package/.agent/skills/documentation-templates/agents-template.md +202 -0
  25. package/.agent/skills/graph-mapper/SKILL.md +211 -0
  26. package/.agent/skills/graph-mapper/scripts/generate_graph.py +705 -0
  27. package/.agent/skills/rag-engineering/SKILL.md +342 -0
  28. package/.agent/skills/rag-engineering/chunking-strategies.md +229 -0
  29. package/.agent/skills/rag-engineering/contextual-retrieval.md +261 -0
  30. package/.agent/skills/rag-engineering/hybrid-search.md +356 -0
  31. package/.agent/skills/rag-engineering/scripts/chunk_code.py +916 -0
  32. package/.agent/templates/mcp_configs/claude_desktop.json +14 -0
  33. package/.agent/templates/mcp_configs/cursor.json +13 -0
  34. package/.agent/templates/mcp_configs/vscode.json +13 -0
  35. package/.agent/workflows/create.md +70 -2
  36. package/bin/cli.js +91 -0
  37. package/docs/AI_DATA_INFRASTRUCTURE.md +288 -0
  38. package/docs/CHANGELOG_AI_INFRA.md +111 -0
  39. package/docs/PLAN-universal-intelligence.md +48 -0
  40. package/package.json +7 -2
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Debouncer
3
+ *
4
+ * Prevents excessive syncing by enforcing a cooldown period
5
+ * between sync operations. Essential for performance when
6
+ * AI makes many rapid queries.
7
+ */
8
+ export class Debouncer {
9
+ lastSync = 0;
10
+ cooldownMs;
11
+ pendingSync = null;
12
+ /**
13
+ * @param cooldownMs Minimum time between syncs (default: 30 seconds)
14
+ */
15
+ constructor(cooldownMs = 30000) {
16
+ this.cooldownMs = cooldownMs;
17
+ }
18
+ /**
19
+ * Check if enough time has passed since last sync
20
+ */
21
+ canSync() {
22
+ const now = Date.now();
23
+ return now - this.lastSync >= this.cooldownMs;
24
+ }
25
+ /**
26
+ * Get remaining cooldown time in milliseconds
27
+ */
28
+ getRemainingCooldown() {
29
+ const elapsed = Date.now() - this.lastSync;
30
+ const remaining = this.cooldownMs - elapsed;
31
+ return Math.max(0, remaining);
32
+ }
33
+ /**
34
+ * Get remaining cooldown time in human-readable format
35
+ */
36
+ getRemainingCooldownFormatted() {
37
+ const remaining = this.getRemainingCooldown();
38
+ if (remaining === 0)
39
+ return "Ready";
40
+ return `${Math.ceil(remaining / 1000)}s`;
41
+ }
42
+ /**
43
+ * Mark that a sync has occurred
44
+ */
45
+ markSynced() {
46
+ this.lastSync = Date.now();
47
+ this.pendingSync = null;
48
+ }
49
+ /**
50
+ * Execute a sync operation with debouncing
51
+ *
52
+ * @param syncFn The sync function to execute
53
+ * @returns Result of sync or null if debounced
54
+ */
55
+ async executeWithDebounce(syncFn) {
56
+ if (!this.canSync()) {
57
+ return {
58
+ executed: false,
59
+ reason: `Cooldown active. Next sync available in ${this.getRemainingCooldownFormatted()}`,
60
+ };
61
+ }
62
+ // Prevent concurrent syncs
63
+ if (this.pendingSync) {
64
+ return {
65
+ executed: false,
66
+ reason: "Sync already in progress",
67
+ };
68
+ }
69
+ try {
70
+ this.pendingSync = Promise.resolve();
71
+ const result = await syncFn();
72
+ this.markSynced();
73
+ return { executed: true, result };
74
+ }
75
+ catch (error) {
76
+ this.pendingSync = null;
77
+ return {
78
+ executed: false,
79
+ reason: `Sync failed: ${error instanceof Error ? error.message : String(error)}`,
80
+ };
81
+ }
82
+ }
83
+ /**
84
+ * Force reset the debouncer (for manual sync commands)
85
+ */
86
+ reset() {
87
+ this.lastSync = 0;
88
+ this.pendingSync = null;
89
+ }
90
+ /**
91
+ * Get debouncer status
92
+ */
93
+ getStatus() {
94
+ return {
95
+ lastSync: this.lastSync > 0
96
+ ? new Date(this.lastSync).toISOString()
97
+ : "Never",
98
+ canSync: this.canSync(),
99
+ cooldownRemaining: this.getRemainingCooldownFormatted(),
100
+ };
101
+ }
102
+ }
103
+ /**
104
+ * Singleton debouncer instance for global use
105
+ */
106
+ let globalDebouncer = null;
107
+ export function getGlobalDebouncer(cooldownMs) {
108
+ if (!globalDebouncer) {
109
+ globalDebouncer = new Debouncer(cooldownMs);
110
+ }
111
+ return globalDebouncer;
112
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Incremental Syncer
3
+ *
4
+ * Updates only the changed files in the AI infrastructure
5
+ * instead of regenerating everything from scratch.
6
+ */
7
+ import { TimestampChecker } from "./timestamp_checker.js";
8
+ export interface SyncResult {
9
+ success: boolean;
10
+ target: "graph" | "rag" | "all";
11
+ filesUpdated: string[];
12
+ duration: number;
13
+ error?: string;
14
+ }
15
+ export declare class IncrementalSyncer {
16
+ private projectRoot;
17
+ private kitPath;
18
+ private timestampChecker;
19
+ constructor(projectRoot: string, kitPath?: string);
20
+ /**
21
+ * Detect Agent Kit installation path
22
+ */
23
+ private detectKitPath;
24
+ /**
25
+ * Run a Python script and return output
26
+ */
27
+ private runPythonScript;
28
+ /**
29
+ * Sync dependency graph (full or incremental)
30
+ */
31
+ syncGraph(changedFiles?: string[]): Promise<SyncResult>;
32
+ /**
33
+ * Sync RAG chunks (full or incremental)
34
+ */
35
+ syncRag(changedFiles?: string[]): Promise<SyncResult>;
36
+ /**
37
+ * Sync all AI infrastructure
38
+ */
39
+ syncAll(): Promise<{
40
+ graph: SyncResult;
41
+ rag: SyncResult;
42
+ }>;
43
+ /**
44
+ * Check if sync is needed and perform if necessary
45
+ */
46
+ syncIfNeeded(): Promise<{
47
+ synced: boolean;
48
+ reason?: string;
49
+ results?: {
50
+ graph: SyncResult;
51
+ rag: SyncResult;
52
+ };
53
+ }>;
54
+ /**
55
+ * Get sync status
56
+ */
57
+ getSyncStatus(): ReturnType<TimestampChecker["getSyncStatus"]>;
58
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Incremental Syncer
3
+ *
4
+ * Updates only the changed files in the AI infrastructure
5
+ * instead of regenerating everything from scratch.
6
+ */
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import { spawn } from "child_process";
10
+ import { TimestampChecker } from "./timestamp_checker.js";
11
+ export class IncrementalSyncer {
12
+ projectRoot;
13
+ kitPath;
14
+ timestampChecker;
15
+ constructor(projectRoot, kitPath) {
16
+ this.projectRoot = projectRoot;
17
+ this.kitPath = kitPath || this.detectKitPath();
18
+ this.timestampChecker = new TimestampChecker(projectRoot);
19
+ }
20
+ /**
21
+ * Detect Agent Kit installation path
22
+ */
23
+ detectKitPath() {
24
+ // Check environment variable first
25
+ if (process.env.AGENT_KIT_PATH) {
26
+ return process.env.AGENT_KIT_PATH;
27
+ }
28
+ // Check relative to this file (when running from kit)
29
+ const relativePath = path.join(__dirname, "..", "..", "..");
30
+ if (fs.existsSync(path.join(relativePath, "skills"))) {
31
+ return relativePath;
32
+ }
33
+ // Check in project's .agent directory
34
+ const projectAgentPath = path.join(this.projectRoot, ".agent");
35
+ if (fs.existsSync(path.join(projectAgentPath, "skills"))) {
36
+ return projectAgentPath;
37
+ }
38
+ // Fallback to node_modules
39
+ const nodeModulesPath = path.join(this.projectRoot, "node_modules", "@musashishao", "agent-kit", ".agent");
40
+ return nodeModulesPath;
41
+ }
42
+ /**
43
+ * Run a Python script and return output
44
+ */
45
+ async runPythonScript(scriptPath, args) {
46
+ return new Promise((resolve) => {
47
+ if (!fs.existsSync(scriptPath)) {
48
+ resolve({ success: false, output: `Script not found: ${scriptPath}` });
49
+ return;
50
+ }
51
+ const proc = spawn("python3", [scriptPath, ...args], {
52
+ cwd: this.projectRoot,
53
+ env: { ...process.env, PYTHONUNBUFFERED: "1" },
54
+ });
55
+ let output = "";
56
+ let error = "";
57
+ proc.stdout.on("data", (data) => {
58
+ output += data.toString();
59
+ });
60
+ proc.stderr.on("data", (data) => {
61
+ error += data.toString();
62
+ });
63
+ proc.on("close", (code) => {
64
+ resolve({
65
+ success: code === 0,
66
+ output: code === 0 ? output : error || output,
67
+ });
68
+ });
69
+ proc.on("error", (err) => {
70
+ resolve({ success: false, output: `Failed to run script: ${err.message}` });
71
+ });
72
+ });
73
+ }
74
+ /**
75
+ * Sync dependency graph (full or incremental)
76
+ */
77
+ async syncGraph(changedFiles) {
78
+ const startTime = Date.now();
79
+ const scriptPath = path.join(this.kitPath, "skills", "graph-mapper", "scripts", "generate_graph.py");
80
+ // Determine source directory
81
+ let sourceDir = "src";
82
+ if (fs.existsSync(path.join(this.projectRoot, "app"))) {
83
+ sourceDir = "app";
84
+ }
85
+ const args = [
86
+ "--src",
87
+ path.join(this.projectRoot, sourceDir),
88
+ "--output",
89
+ path.join(this.projectRoot, ".agent", "graph.json"),
90
+ "--format",
91
+ "both",
92
+ ];
93
+ const result = await this.runPythonScript(scriptPath, args);
94
+ if (result.success) {
95
+ // Update timestamps for synced files
96
+ if (changedFiles && changedFiles.length > 0) {
97
+ this.timestampChecker.updateFileTimestamps(changedFiles);
98
+ }
99
+ else {
100
+ this.timestampChecker.markAllSynced(sourceDir);
101
+ }
102
+ }
103
+ return {
104
+ success: result.success,
105
+ target: "graph",
106
+ filesUpdated: changedFiles || [],
107
+ duration: Date.now() - startTime,
108
+ error: result.success ? undefined : result.output,
109
+ };
110
+ }
111
+ /**
112
+ * Sync RAG chunks (full or incremental)
113
+ */
114
+ async syncRag(changedFiles) {
115
+ const startTime = Date.now();
116
+ const scriptPath = path.join(this.kitPath, "skills", "rag-engineering", "scripts", "chunk_code.py");
117
+ // Determine source directory
118
+ let sourceDir = "src";
119
+ if (fs.existsSync(path.join(this.projectRoot, "app"))) {
120
+ sourceDir = "app";
121
+ }
122
+ const args = [
123
+ "--src",
124
+ path.join(this.projectRoot, sourceDir),
125
+ "--output",
126
+ path.join(this.projectRoot, ".agent", "rag", "chunks.json"),
127
+ ];
128
+ const result = await this.runPythonScript(scriptPath, args);
129
+ return {
130
+ success: result.success,
131
+ target: "rag",
132
+ filesUpdated: changedFiles || [],
133
+ duration: Date.now() - startTime,
134
+ error: result.success ? undefined : result.output,
135
+ };
136
+ }
137
+ /**
138
+ * Sync all AI infrastructure
139
+ */
140
+ async syncAll() {
141
+ const changedFiles = this.timestampChecker.getChangedFiles();
142
+ const [graphResult, ragResult] = await Promise.all([
143
+ this.syncGraph(changedFiles),
144
+ this.syncRag(changedFiles),
145
+ ]);
146
+ return { graph: graphResult, rag: ragResult };
147
+ }
148
+ /**
149
+ * Check if sync is needed and perform if necessary
150
+ */
151
+ async syncIfNeeded() {
152
+ const status = this.timestampChecker.getSyncStatus();
153
+ if (!status.needsSync) {
154
+ return {
155
+ synced: false,
156
+ reason: "No changes detected since last sync",
157
+ };
158
+ }
159
+ const results = await this.syncAll();
160
+ return {
161
+ synced: true,
162
+ reason: `${status.changedFiles} files changed`,
163
+ results,
164
+ };
165
+ }
166
+ /**
167
+ * Get sync status
168
+ */
169
+ getSyncStatus() {
170
+ return this.timestampChecker.getSyncStatus();
171
+ }
172
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sync Module Exports
3
+ */
4
+ export { TimestampChecker } from "./timestamp_checker.js";
5
+ export { IncrementalSyncer, type SyncResult } from "./incremental_syncer.js";
6
+ export { Debouncer, getGlobalDebouncer } from "./debouncer.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sync Module Exports
3
+ */
4
+ export { TimestampChecker } from "./timestamp_checker.js";
5
+ export { IncrementalSyncer } from "./incremental_syncer.js";
6
+ export { Debouncer, getGlobalDebouncer } from "./debouncer.js";
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Timestamp Checker
3
+ *
4
+ * Tracks file modification times to detect when source code
5
+ * has changed since the last sync of AI infrastructure data.
6
+ */
7
+ export interface TimestampCache {
8
+ lastSync: number;
9
+ files: Record<string, number>;
10
+ }
11
+ export declare class TimestampChecker {
12
+ private cachePath;
13
+ private cache;
14
+ private projectRoot;
15
+ constructor(projectRoot: string);
16
+ /**
17
+ * Load timestamp cache from disk
18
+ */
19
+ private loadCache;
20
+ /**
21
+ * Save timestamp cache to disk
22
+ */
23
+ saveCache(): void;
24
+ /**
25
+ * Get modification time of a file
26
+ */
27
+ private getFileModTime;
28
+ /**
29
+ * Check if a specific file has changed since last sync
30
+ */
31
+ hasFileChanged(filePath: string): boolean;
32
+ /**
33
+ * Check if any source files have changed
34
+ */
35
+ hasAnyChanges(sourceDir?: string): boolean;
36
+ /**
37
+ * Get list of all changed files since last sync
38
+ */
39
+ getChangedFiles(sourceDir?: string): string[];
40
+ /**
41
+ * Get all source files in a directory
42
+ */
43
+ private getAllSourceFiles;
44
+ /**
45
+ * Update timestamp for a file
46
+ */
47
+ updateFileTimestamp(filePath: string): void;
48
+ /**
49
+ * Update timestamps for multiple files
50
+ */
51
+ updateFileTimestamps(files: string[]): void;
52
+ /**
53
+ * Mark all current files as synced
54
+ */
55
+ markAllSynced(sourceDir?: string): void;
56
+ /**
57
+ * Get last sync time
58
+ */
59
+ getLastSyncTime(): number;
60
+ /**
61
+ * Get human-readable sync status
62
+ */
63
+ getSyncStatus(sourceDir?: string): {
64
+ lastSync: string;
65
+ totalFiles: number;
66
+ changedFiles: number;
67
+ needsSync: boolean;
68
+ };
69
+ }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Timestamp Checker
3
+ *
4
+ * Tracks file modification times to detect when source code
5
+ * has changed since the last sync of AI infrastructure data.
6
+ */
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ export class TimestampChecker {
10
+ cachePath;
11
+ cache;
12
+ projectRoot;
13
+ constructor(projectRoot) {
14
+ this.projectRoot = projectRoot;
15
+ this.cachePath = path.join(projectRoot, ".agent", ".cache", "timestamps.json");
16
+ this.cache = this.loadCache();
17
+ }
18
+ /**
19
+ * Load timestamp cache from disk
20
+ */
21
+ loadCache() {
22
+ try {
23
+ if (fs.existsSync(this.cachePath)) {
24
+ const data = fs.readFileSync(this.cachePath, "utf-8");
25
+ return JSON.parse(data);
26
+ }
27
+ }
28
+ catch (error) {
29
+ console.error("Failed to load timestamp cache:", error);
30
+ }
31
+ return { lastSync: 0, files: {} };
32
+ }
33
+ /**
34
+ * Save timestamp cache to disk
35
+ */
36
+ saveCache() {
37
+ try {
38
+ const cacheDir = path.dirname(this.cachePath);
39
+ if (!fs.existsSync(cacheDir)) {
40
+ fs.mkdirSync(cacheDir, { recursive: true });
41
+ }
42
+ fs.writeFileSync(this.cachePath, JSON.stringify(this.cache, null, 2));
43
+ }
44
+ catch (error) {
45
+ console.error("Failed to save timestamp cache:", error);
46
+ }
47
+ }
48
+ /**
49
+ * Get modification time of a file
50
+ */
51
+ getFileModTime(filePath) {
52
+ try {
53
+ const fullPath = path.resolve(this.projectRoot, filePath);
54
+ const stats = fs.statSync(fullPath);
55
+ return stats.mtimeMs;
56
+ }
57
+ catch {
58
+ return 0;
59
+ }
60
+ }
61
+ /**
62
+ * Check if a specific file has changed since last sync
63
+ */
64
+ hasFileChanged(filePath) {
65
+ const currentMtime = this.getFileModTime(filePath);
66
+ const cachedMtime = this.cache.files[filePath] || 0;
67
+ return currentMtime > cachedMtime;
68
+ }
69
+ /**
70
+ * Check if any source files have changed
71
+ */
72
+ hasAnyChanges(sourceDir = "src") {
73
+ const files = this.getAllSourceFiles(sourceDir);
74
+ for (const file of files) {
75
+ if (this.hasFileChanged(file)) {
76
+ return true;
77
+ }
78
+ }
79
+ return false;
80
+ }
81
+ /**
82
+ * Get list of all changed files since last sync
83
+ */
84
+ getChangedFiles(sourceDir = "src") {
85
+ const files = this.getAllSourceFiles(sourceDir);
86
+ return files.filter((file) => this.hasFileChanged(file));
87
+ }
88
+ /**
89
+ * Get all source files in a directory
90
+ */
91
+ getAllSourceFiles(dir) {
92
+ const fullDir = path.resolve(this.projectRoot, dir);
93
+ if (!fs.existsSync(fullDir)) {
94
+ return [];
95
+ }
96
+ const files = [];
97
+ const extensions = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".go"]);
98
+ const excludeDirs = new Set(["node_modules", "__pycache__", ".git", "dist", "build", ".next"]);
99
+ const walk = (currentDir) => {
100
+ try {
101
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
102
+ for (const entry of entries) {
103
+ const fullPath = path.join(currentDir, entry.name);
104
+ const relativePath = path.relative(this.projectRoot, fullPath);
105
+ if (entry.isDirectory()) {
106
+ if (!excludeDirs.has(entry.name)) {
107
+ walk(fullPath);
108
+ }
109
+ }
110
+ else if (entry.isFile()) {
111
+ const ext = path.extname(entry.name);
112
+ if (extensions.has(ext)) {
113
+ files.push(relativePath);
114
+ }
115
+ }
116
+ }
117
+ }
118
+ catch (error) {
119
+ // Skip directories we can't read
120
+ }
121
+ };
122
+ walk(fullDir);
123
+ return files;
124
+ }
125
+ /**
126
+ * Update timestamp for a file
127
+ */
128
+ updateFileTimestamp(filePath) {
129
+ this.cache.files[filePath] = this.getFileModTime(filePath);
130
+ }
131
+ /**
132
+ * Update timestamps for multiple files
133
+ */
134
+ updateFileTimestamps(files) {
135
+ for (const file of files) {
136
+ this.updateFileTimestamp(file);
137
+ }
138
+ this.cache.lastSync = Date.now();
139
+ this.saveCache();
140
+ }
141
+ /**
142
+ * Mark all current files as synced
143
+ */
144
+ markAllSynced(sourceDir = "src") {
145
+ const files = this.getAllSourceFiles(sourceDir);
146
+ this.updateFileTimestamps(files);
147
+ }
148
+ /**
149
+ * Get last sync time
150
+ */
151
+ getLastSyncTime() {
152
+ return this.cache.lastSync;
153
+ }
154
+ /**
155
+ * Get human-readable sync status
156
+ */
157
+ getSyncStatus(sourceDir = "src") {
158
+ const allFiles = this.getAllSourceFiles(sourceDir);
159
+ const changedFiles = this.getChangedFiles(sourceDir);
160
+ return {
161
+ lastSync: this.cache.lastSync > 0
162
+ ? new Date(this.cache.lastSync).toISOString()
163
+ : "Never",
164
+ totalFiles: allFiles.length,
165
+ changedFiles: changedFiles.length,
166
+ needsSync: changedFiles.length > 0,
167
+ };
168
+ }
169
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@musashishao/agent-kit-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP Gateway Server for Agent Kit - Live Project Cortex",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "agent-kit-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "watch": "tsc --watch"
15
+ },
16
+ "dependencies": {
17
+ "@modelcontextprotocol/sdk": "^1.0.0",
18
+ "zod": "^3.23.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^20.0.0",
22
+ "tsx": "^4.0.0",
23
+ "typescript": "^5.0.0"
24
+ },
25
+ "engines": {
26
+ "node": ">=18.0.0"
27
+ }
28
+ }