@sashabogi/foundation 0.1.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/LICENSE +21 -0
- package/README.md +341 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +308 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/services/config.service.d.ts +92 -0
- package/dist/services/config.service.d.ts.map +1 -0
- package/dist/services/config.service.js +284 -0
- package/dist/services/config.service.js.map +1 -0
- package/dist/services/git.service.d.ts +175 -0
- package/dist/services/git.service.d.ts.map +1 -0
- package/dist/services/git.service.js +395 -0
- package/dist/services/git.service.js.map +1 -0
- package/dist/services/provider.service.d.ts +74 -0
- package/dist/services/provider.service.d.ts.map +1 -0
- package/dist/services/provider.service.js +182 -0
- package/dist/services/provider.service.js.map +1 -0
- package/dist/services/storage.service.d.ts +84 -0
- package/dist/services/storage.service.d.ts.map +1 -0
- package/dist/services/storage.service.js +320 -0
- package/dist/services/storage.service.js.map +1 -0
- package/dist/tools/demerzel/index.d.ts +21 -0
- package/dist/tools/demerzel/index.d.ts.map +1 -0
- package/dist/tools/demerzel/index.js +166 -0
- package/dist/tools/demerzel/index.js.map +1 -0
- package/dist/tools/gaia/index.d.ts +27 -0
- package/dist/tools/gaia/index.d.ts.map +1 -0
- package/dist/tools/gaia/index.js +466 -0
- package/dist/tools/gaia/index.js.map +1 -0
- package/dist/tools/seldon/index.d.ts +43 -0
- package/dist/tools/seldon/index.d.ts.map +1 -0
- package/dist/tools/seldon/index.js +886 -0
- package/dist/tools/seldon/index.js.map +1 -0
- package/dist/types/index.d.ts +392 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demerzel Module Tools
|
|
3
|
+
*
|
|
4
|
+
* Codebase intelligence beyond context limits.
|
|
5
|
+
* Named after R. Daneel Olivaw/Demerzel - 20,000 years of perfect memory,
|
|
6
|
+
* observing silently, knowing everything about the codebase.
|
|
7
|
+
*
|
|
8
|
+
* Tools:
|
|
9
|
+
* - demerzel_snapshot: Create codebase snapshot
|
|
10
|
+
* - demerzel_search: Regex search across codebase
|
|
11
|
+
* - demerzel_find_files: Glob pattern file matching
|
|
12
|
+
* - demerzel_find_symbol: Locate function/class definitions
|
|
13
|
+
* - demerzel_find_importers: Find files that import a module
|
|
14
|
+
* - demerzel_get_deps: Get file dependencies
|
|
15
|
+
* - demerzel_get_context: Get lines around a location
|
|
16
|
+
* - demerzel_analyze: AI-powered deep analysis
|
|
17
|
+
* - demerzel_semantic_search: Natural language code search
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
export function registerDemerzelTools(server) {
|
|
21
|
+
// demerzel_snapshot
|
|
22
|
+
server.tool('demerzel_snapshot', 'Create a codebase snapshot for efficient searching and analysis. Enhanced snapshots include import graph and export index. "I have been watching for 20,000 years."', {
|
|
23
|
+
path: z.string().describe('Path to the codebase directory'),
|
|
24
|
+
enhanced: z.boolean().optional().describe('Create enhanced snapshot with import graph (default: true)'),
|
|
25
|
+
output: z.string().optional().describe('Output path for snapshot (default: .foundation/snapshot.txt)'),
|
|
26
|
+
}, async ({ path, enhanced = true, output: _output }) => {
|
|
27
|
+
// TODO: Port implementation from argus
|
|
28
|
+
return {
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: 'text',
|
|
32
|
+
text: `[Stub] Would create ${enhanced ? 'enhanced' : 'basic'} snapshot for ${path}`,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
// demerzel_search
|
|
38
|
+
server.tool('demerzel_search', 'Fast regex search across codebase. Zero AI cost. Returns file:line:content matches.', {
|
|
39
|
+
path: z.string().describe('Path to snapshot file'),
|
|
40
|
+
pattern: z.string().describe('Regex pattern to search'),
|
|
41
|
+
maxResults: z.number().optional().describe('Maximum results (default: 50)'),
|
|
42
|
+
caseInsensitive: z.boolean().optional().describe('Case insensitive search (default: true)'),
|
|
43
|
+
}, async ({ path, pattern, maxResults: _maxResults = 50, caseInsensitive: _caseInsensitive = true }) => {
|
|
44
|
+
// TODO: Port implementation from argus
|
|
45
|
+
return {
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: 'text',
|
|
49
|
+
text: `[Stub] Would search for "${pattern}" in ${path}`,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
// demerzel_find_files
|
|
55
|
+
server.tool('demerzel_find_files', 'Find files matching a glob pattern. Zero AI cost.', {
|
|
56
|
+
path: z.string().describe('Path to snapshot file'),
|
|
57
|
+
pattern: z.string().describe('Glob pattern (e.g., "*.ts", "src/**/*.tsx")'),
|
|
58
|
+
limit: z.number().optional().describe('Maximum results (default: 100)'),
|
|
59
|
+
}, async ({ path, pattern, limit: _limit = 100 }) => {
|
|
60
|
+
// TODO: Port implementation from argus
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: `[Stub] Would find files matching "${pattern}" in ${path}`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
// demerzel_find_symbol
|
|
71
|
+
server.tool('demerzel_find_symbol', 'Locate where a function, class, or type is exported. Zero AI cost. Requires enhanced snapshot.', {
|
|
72
|
+
path: z.string().describe('Path to snapshot file'),
|
|
73
|
+
symbol: z.string().describe('Symbol name to find (e.g., "AuthProvider", "useAuth")'),
|
|
74
|
+
}, async ({ path, symbol }) => {
|
|
75
|
+
// TODO: Port implementation from argus
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: `[Stub] Would find symbol "${symbol}" in ${path}`,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
// demerzel_find_importers
|
|
86
|
+
server.tool('demerzel_find_importers', 'Find all files that import a given module. Zero AI cost. Requires enhanced snapshot.', {
|
|
87
|
+
path: z.string().describe('Path to snapshot file'),
|
|
88
|
+
target: z.string().describe('File path to find importers of (e.g., "src/auth.ts")'),
|
|
89
|
+
}, async ({ path, target }) => {
|
|
90
|
+
// TODO: Port implementation from argus
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: `[Stub] Would find importers of "${target}" in ${path}`,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
// demerzel_get_deps
|
|
101
|
+
server.tool('demerzel_get_deps', 'Get all dependencies (imports) of a specific file. Zero AI cost. Requires enhanced snapshot.', {
|
|
102
|
+
path: z.string().describe('Path to snapshot file'),
|
|
103
|
+
file: z.string().describe('File path to get dependencies for'),
|
|
104
|
+
}, async ({ path, file }) => {
|
|
105
|
+
// TODO: Port implementation from argus
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: 'text',
|
|
110
|
+
text: `[Stub] Would get dependencies of "${file}" in ${path}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
// demerzel_get_context
|
|
116
|
+
server.tool('demerzel_get_context', 'Get lines of code around a specific location. Zero AI cost. Use after search to get more context.', {
|
|
117
|
+
path: z.string().describe('Path to snapshot file'),
|
|
118
|
+
file: z.string().describe('File path within the snapshot'),
|
|
119
|
+
line: z.number().describe('Center line number'),
|
|
120
|
+
before: z.number().optional().describe('Lines before (default: 10)'),
|
|
121
|
+
after: z.number().optional().describe('Lines after (default: 10)'),
|
|
122
|
+
}, async ({ path, file, line, before = 10, after = 10 }) => {
|
|
123
|
+
// TODO: Port implementation from argus
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: `[Stub] Would get context around line ${line} in ${file}`,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
// demerzel_analyze
|
|
134
|
+
server.tool('demerzel_analyze', 'AI-powered deep analysis of codebase. Uses recursive reasoning across entire codebase. ~500 tokens cost.', {
|
|
135
|
+
path: z.string().describe('Path to snapshot file'),
|
|
136
|
+
query: z.string().describe('Question about the codebase (be specific for best results)'),
|
|
137
|
+
maxTurns: z.number().optional().describe('Maximum reasoning turns (default: 15)'),
|
|
138
|
+
}, async ({ path, query, maxTurns = 15 }) => {
|
|
139
|
+
// TODO: Port implementation from argus
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: 'text',
|
|
144
|
+
text: `[Stub] Would analyze "${query}" in ${path}`,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
// demerzel_semantic_search
|
|
150
|
+
server.tool('demerzel_semantic_search', 'Search code using natural language. Uses FTS5 full-text search. More flexible than regex.', {
|
|
151
|
+
path: z.string().describe('Path to project directory'),
|
|
152
|
+
query: z.string().describe('Natural language query or code terms'),
|
|
153
|
+
limit: z.number().optional().describe('Maximum results (default: 20)'),
|
|
154
|
+
}, async ({ path, query, limit = 20 }) => {
|
|
155
|
+
// TODO: Port implementation from argus
|
|
156
|
+
return {
|
|
157
|
+
content: [
|
|
158
|
+
{
|
|
159
|
+
type: 'text',
|
|
160
|
+
text: `[Stub] Would semantic search "${query}" in ${path}`,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/demerzel/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gaia Module Tools
|
|
3
|
+
*
|
|
4
|
+
* Workflow patterns - shared memory and collective consciousness.
|
|
5
|
+
* Named after Gaia from Foundation - "We are all one, and one is all."
|
|
6
|
+
*
|
|
7
|
+
* Preserves context across sessions, learns from mistakes, enables
|
|
8
|
+
* seamless handoffs between Claude instances.
|
|
9
|
+
*
|
|
10
|
+
* Tools:
|
|
11
|
+
* - gaia_worktree_create: Create git worktree with session
|
|
12
|
+
* - gaia_worktree_list: List active worktrees
|
|
13
|
+
* - gaia_worktree_switch: Navigate between worktrees
|
|
14
|
+
* - gaia_worktree_cleanup: Remove stale worktrees
|
|
15
|
+
* - gaia_session_register: Track Claude session purpose
|
|
16
|
+
* - gaia_session_status: View active sessions
|
|
17
|
+
* - gaia_session_handoff: Prepare context for handoff
|
|
18
|
+
* - gaia_session_complete: Mark session as done
|
|
19
|
+
* - gaia_learn: Record correction for CLAUDE.md
|
|
20
|
+
* - gaia_apply: Write learnings to CLAUDE.md
|
|
21
|
+
* - gaia_review: Review accumulated learnings
|
|
22
|
+
* - gaia_remember: Save context state
|
|
23
|
+
* - gaia_recall: Restore previous context
|
|
24
|
+
*/
|
|
25
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
26
|
+
export declare function registerGaiaTools(server: McpServer): void;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/gaia/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8BzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyhBzD"}
|
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gaia Module Tools
|
|
3
|
+
*
|
|
4
|
+
* Workflow patterns - shared memory and collective consciousness.
|
|
5
|
+
* Named after Gaia from Foundation - "We are all one, and one is all."
|
|
6
|
+
*
|
|
7
|
+
* Preserves context across sessions, learns from mistakes, enables
|
|
8
|
+
* seamless handoffs between Claude instances.
|
|
9
|
+
*
|
|
10
|
+
* Tools:
|
|
11
|
+
* - gaia_worktree_create: Create git worktree with session
|
|
12
|
+
* - gaia_worktree_list: List active worktrees
|
|
13
|
+
* - gaia_worktree_switch: Navigate between worktrees
|
|
14
|
+
* - gaia_worktree_cleanup: Remove stale worktrees
|
|
15
|
+
* - gaia_session_register: Track Claude session purpose
|
|
16
|
+
* - gaia_session_status: View active sessions
|
|
17
|
+
* - gaia_session_handoff: Prepare context for handoff
|
|
18
|
+
* - gaia_session_complete: Mark session as done
|
|
19
|
+
* - gaia_learn: Record correction for CLAUDE.md
|
|
20
|
+
* - gaia_apply: Write learnings to CLAUDE.md
|
|
21
|
+
* - gaia_review: Review accumulated learnings
|
|
22
|
+
* - gaia_remember: Save context state
|
|
23
|
+
* - gaia_recall: Restore previous context
|
|
24
|
+
*/
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
import { nanoid } from 'nanoid';
|
|
27
|
+
import { StorageService } from '../../services/storage.service.js';
|
|
28
|
+
import { GitService } from '../../services/git.service.js';
|
|
29
|
+
const SessionTaskTypeSchema = z.enum([
|
|
30
|
+
'feature',
|
|
31
|
+
'bugfix',
|
|
32
|
+
'refactor',
|
|
33
|
+
'review',
|
|
34
|
+
'exploration',
|
|
35
|
+
'documentation',
|
|
36
|
+
]);
|
|
37
|
+
const LearningCategorySchema = z.enum([
|
|
38
|
+
'code_style',
|
|
39
|
+
'architecture',
|
|
40
|
+
'testing',
|
|
41
|
+
'performance',
|
|
42
|
+
'security',
|
|
43
|
+
'documentation',
|
|
44
|
+
'tooling',
|
|
45
|
+
'process',
|
|
46
|
+
'other',
|
|
47
|
+
]);
|
|
48
|
+
const LearningScopeSchema = z.enum(['global', 'project']);
|
|
49
|
+
export function registerGaiaTools(server) {
|
|
50
|
+
const storage = StorageService.getInstance();
|
|
51
|
+
const git = GitService.getInstance();
|
|
52
|
+
// ===========================================================================
|
|
53
|
+
// Worktree Tools
|
|
54
|
+
// ===========================================================================
|
|
55
|
+
// gaia_worktree_create
|
|
56
|
+
server.tool('gaia_worktree_create', 'Create a git worktree for parallel Claude sessions. Returns shell alias for quick navigation.', {
|
|
57
|
+
branch: z.string().describe('Branch name for the worktree'),
|
|
58
|
+
alias: z.string().optional().describe('Single letter alias for quick switching (e.g., "a" for `za`)'),
|
|
59
|
+
purpose: z.string().optional().describe('Purpose of this worktree'),
|
|
60
|
+
baseBranch: z.string().optional().describe('Base branch (default: main)'),
|
|
61
|
+
}, async ({ branch, alias, purpose, baseBranch = 'main' }) => {
|
|
62
|
+
try {
|
|
63
|
+
const repoRoot = await git.getRepoRoot();
|
|
64
|
+
const worktreePath = `${repoRoot}-${alias || branch.split('/').pop()}`;
|
|
65
|
+
await git.createWorktree(worktreePath, branch, { baseBranch });
|
|
66
|
+
const worktree = {
|
|
67
|
+
id: `wt_${nanoid(8)}`,
|
|
68
|
+
path: worktreePath,
|
|
69
|
+
branch,
|
|
70
|
+
baseBranch,
|
|
71
|
+
alias,
|
|
72
|
+
purpose,
|
|
73
|
+
status: 'active',
|
|
74
|
+
createdAt: Date.now(),
|
|
75
|
+
lastAccessedAt: Date.now(),
|
|
76
|
+
};
|
|
77
|
+
storage.addWorktree(worktree);
|
|
78
|
+
let output = `✓ Created worktree at ${worktreePath}\n\n`;
|
|
79
|
+
if (alias) {
|
|
80
|
+
output += `Shell alias: \`alias z${alias}='cd ${worktreePath} && claude'\`\n`;
|
|
81
|
+
}
|
|
82
|
+
output += `\nTo navigate: \`cd ${worktreePath}\``;
|
|
83
|
+
return {
|
|
84
|
+
content: [{ type: 'text', text: output }],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: 'text', text: `Error: ${error.message}` }],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
// gaia_worktree_list
|
|
94
|
+
server.tool('gaia_worktree_list', 'List all active worktrees with their status and session info.', {}, async () => {
|
|
95
|
+
const worktrees = storage.getWorktrees();
|
|
96
|
+
if (worktrees.length === 0) {
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: 'text', text: 'No active worktrees.' }],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
let output = '## Active Worktrees\n\n';
|
|
102
|
+
for (const wt of worktrees) {
|
|
103
|
+
output += `### ${wt.alias ? `[${wt.alias}] ` : ''}${wt.branch}\n`;
|
|
104
|
+
output += `- Path: \`${wt.path}\`\n`;
|
|
105
|
+
output += `- Status: ${wt.status}\n`;
|
|
106
|
+
if (wt.purpose)
|
|
107
|
+
output += `- Purpose: ${wt.purpose}\n`;
|
|
108
|
+
output += '\n';
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: 'text', text: output }],
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
// gaia_worktree_switch
|
|
115
|
+
server.tool('gaia_worktree_switch', 'Get the command to switch to a worktree by alias or branch.', {
|
|
116
|
+
target: z.string().describe('Worktree alias or branch name'),
|
|
117
|
+
}, async ({ target }) => {
|
|
118
|
+
const worktree = storage.getWorktreeByAlias(target) ||
|
|
119
|
+
storage.getWorktrees().find((w) => w.branch.includes(target));
|
|
120
|
+
if (!worktree) {
|
|
121
|
+
return {
|
|
122
|
+
content: [{ type: 'text', text: `No worktree found for "${target}"` }],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
storage.updateWorktree(worktree.id, { lastAccessedAt: Date.now() });
|
|
126
|
+
return {
|
|
127
|
+
content: [
|
|
128
|
+
{
|
|
129
|
+
type: 'text',
|
|
130
|
+
text: `To switch: \`cd ${worktree.path} && claude\``,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
// gaia_worktree_cleanup
|
|
136
|
+
server.tool('gaia_worktree_cleanup', 'Remove stale or completed worktrees.', {
|
|
137
|
+
target: z.string().optional().describe('Specific worktree ID or alias to remove'),
|
|
138
|
+
staleOnly: z.boolean().optional().describe('Only remove stale worktrees (default: false)'),
|
|
139
|
+
}, async ({ target, staleOnly = false }) => {
|
|
140
|
+
// TODO: Implement cleanup logic
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: 'text', text: '[Stub] Would cleanup worktrees' }],
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
// ===========================================================================
|
|
146
|
+
// Session Tools
|
|
147
|
+
// ===========================================================================
|
|
148
|
+
// gaia_session_register
|
|
149
|
+
server.tool('gaia_session_register', 'Register a new Claude session with its purpose for tracking. "We are all one."', {
|
|
150
|
+
purpose: z.string().describe('What this session is working on'),
|
|
151
|
+
taskType: SessionTaskTypeSchema.describe('Type of task'),
|
|
152
|
+
project: z.string().optional().describe('Project name'),
|
|
153
|
+
worktreeId: z.string().optional().describe('Associated worktree ID'),
|
|
154
|
+
}, async ({ purpose, taskType, project, worktreeId }) => {
|
|
155
|
+
const session = {
|
|
156
|
+
id: `sess_${nanoid(8)}`,
|
|
157
|
+
purpose,
|
|
158
|
+
taskType,
|
|
159
|
+
project,
|
|
160
|
+
worktreeId,
|
|
161
|
+
status: 'active',
|
|
162
|
+
notes: [],
|
|
163
|
+
startedAt: Date.now(),
|
|
164
|
+
lastActivityAt: Date.now(),
|
|
165
|
+
};
|
|
166
|
+
storage.addSession(session);
|
|
167
|
+
return {
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: 'text',
|
|
171
|
+
text: `✓ Session registered: ${session.id}\n\nPurpose: ${purpose}\nType: ${taskType}`,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
// gaia_session_status
|
|
177
|
+
server.tool('gaia_session_status', 'View status of active sessions.', {
|
|
178
|
+
sessionId: z.string().optional().describe('Specific session ID (or show all active)'),
|
|
179
|
+
}, async ({ sessionId }) => {
|
|
180
|
+
if (sessionId) {
|
|
181
|
+
const session = storage.getSession(sessionId);
|
|
182
|
+
if (!session) {
|
|
183
|
+
return {
|
|
184
|
+
content: [{ type: 'text', text: `Session not found: ${sessionId}` }],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
content: [
|
|
189
|
+
{
|
|
190
|
+
type: 'text',
|
|
191
|
+
text: `## Session ${session.id}\n\n- Purpose: ${session.purpose}\n- Status: ${session.status}\n- Type: ${session.taskType}`,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const sessions = storage.getActiveSessions();
|
|
197
|
+
if (sessions.length === 0) {
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: 'text', text: 'No active sessions.' }],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
let output = '## Active Sessions\n\n';
|
|
203
|
+
for (const s of sessions) {
|
|
204
|
+
output += `- **${s.id}**: ${s.purpose} (${s.status})\n`;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
content: [{ type: 'text', text: output }],
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
// gaia_session_handoff
|
|
211
|
+
server.tool('gaia_session_handoff', 'Generate a handoff document for transferring context to another session.', {
|
|
212
|
+
sessionId: z.string().describe('Session ID to create handoff for'),
|
|
213
|
+
includeGitStatus: z.boolean().optional().describe('Include git status (default: true)'),
|
|
214
|
+
includeChanges: z.boolean().optional().describe('Include recent changes (default: true)'),
|
|
215
|
+
nextSteps: z.array(z.string()).optional().describe('Next steps to include'),
|
|
216
|
+
}, async ({ sessionId, includeGitStatus = true, includeChanges = true, nextSteps = [] }) => {
|
|
217
|
+
const session = storage.getSession(sessionId);
|
|
218
|
+
if (!session) {
|
|
219
|
+
return {
|
|
220
|
+
content: [{ type: 'text', text: `Session not found: ${sessionId}` }],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
let handoff = `# Session Handoff: ${session.id}\n\n`;
|
|
224
|
+
handoff += `## Purpose\n${session.purpose}\n\n`;
|
|
225
|
+
handoff += `## Type\n${session.taskType}\n\n`;
|
|
226
|
+
if (includeGitStatus) {
|
|
227
|
+
try {
|
|
228
|
+
const status = await git.getStatus();
|
|
229
|
+
handoff += `## Git Status\n`;
|
|
230
|
+
handoff += `- Branch: ${status.branch}\n`;
|
|
231
|
+
if (status.staged.length)
|
|
232
|
+
handoff += `- Staged: ${status.staged.length} files\n`;
|
|
233
|
+
if (status.modified.length)
|
|
234
|
+
handoff += `- Modified: ${status.modified.length} files\n`;
|
|
235
|
+
handoff += '\n';
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Not in a git repo
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (nextSteps.length > 0) {
|
|
242
|
+
handoff += `## Next Steps\n`;
|
|
243
|
+
for (const step of nextSteps) {
|
|
244
|
+
handoff += `- ${step}\n`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
content: [{ type: 'text', text: handoff }],
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
// gaia_session_complete
|
|
252
|
+
server.tool('gaia_session_complete', 'Mark a session as completed.', {
|
|
253
|
+
sessionId: z.string().describe('Session ID to complete'),
|
|
254
|
+
outcome: z.enum(['completed', 'abandoned']).optional().describe('Session outcome'),
|
|
255
|
+
notes: z.string().optional().describe('Final notes'),
|
|
256
|
+
}, async ({ sessionId, outcome = 'completed', notes }) => {
|
|
257
|
+
const session = storage.getSession(sessionId);
|
|
258
|
+
if (!session) {
|
|
259
|
+
return {
|
|
260
|
+
content: [{ type: 'text', text: `Session not found: ${sessionId}` }],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
storage.updateSession(sessionId, {
|
|
264
|
+
status: outcome,
|
|
265
|
+
completedAt: Date.now(),
|
|
266
|
+
notes: notes ? [...session.notes, notes] : session.notes,
|
|
267
|
+
});
|
|
268
|
+
return {
|
|
269
|
+
content: [
|
|
270
|
+
{
|
|
271
|
+
type: 'text',
|
|
272
|
+
text: `✓ Session ${sessionId} marked as ${outcome}`,
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
};
|
|
276
|
+
});
|
|
277
|
+
// ===========================================================================
|
|
278
|
+
// Learning Tools
|
|
279
|
+
// ===========================================================================
|
|
280
|
+
// gaia_learn
|
|
281
|
+
server.tool('gaia_learn', 'Capture a correction for CLAUDE.md. Gaia learns from mistakes so all future sessions benefit.', {
|
|
282
|
+
mistake: z.string().describe('What went wrong'),
|
|
283
|
+
correction: z.string().describe('The correct approach'),
|
|
284
|
+
category: LearningCategorySchema.describe('Category of the learning'),
|
|
285
|
+
scope: LearningScopeSchema.optional().describe('Scope: global or project (default: project)'),
|
|
286
|
+
}, async ({ mistake, correction, category, scope = 'project' }) => {
|
|
287
|
+
const learning = {
|
|
288
|
+
id: `learn_${nanoid(8)}`,
|
|
289
|
+
mistakeDescription: mistake,
|
|
290
|
+
correction,
|
|
291
|
+
category,
|
|
292
|
+
scope,
|
|
293
|
+
applied: false,
|
|
294
|
+
createdAt: Date.now(),
|
|
295
|
+
};
|
|
296
|
+
storage.addLearning(learning);
|
|
297
|
+
return {
|
|
298
|
+
content: [
|
|
299
|
+
{
|
|
300
|
+
type: 'text',
|
|
301
|
+
text: `✓ Learning captured: ${learning.id}\n\n**Mistake**: ${mistake}\n**Correction**: ${correction}\n\nUse \`gaia_apply\` to write to CLAUDE.md`,
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
// gaia_apply
|
|
307
|
+
server.tool('gaia_apply', 'Apply captured learnings to CLAUDE.md.', {
|
|
308
|
+
learningIds: z.array(z.string()).optional().describe('Specific learning IDs to apply (or all pending)'),
|
|
309
|
+
}, async ({ learningIds }) => {
|
|
310
|
+
const pending = learningIds
|
|
311
|
+
? storage.getLearnings().filter((l) => learningIds.includes(l.id) && !l.applied)
|
|
312
|
+
: storage.getPendingLearnings();
|
|
313
|
+
if (pending.length === 0) {
|
|
314
|
+
return {
|
|
315
|
+
content: [{ type: 'text', text: 'No pending learnings to apply.' }],
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
// Format learnings for CLAUDE.md
|
|
319
|
+
const byCategory = {};
|
|
320
|
+
for (const l of pending) {
|
|
321
|
+
if (!byCategory[l.category])
|
|
322
|
+
byCategory[l.category] = [];
|
|
323
|
+
byCategory[l.category].push(l);
|
|
324
|
+
}
|
|
325
|
+
for (const [category, learnings] of Object.entries(byCategory)) {
|
|
326
|
+
const content = learnings
|
|
327
|
+
.map((l) => `- **${l.mistakeDescription}**: ${l.correction}`)
|
|
328
|
+
.join('\n');
|
|
329
|
+
await git.appendToClaudeMdSection(`Learned: ${category}`, content);
|
|
330
|
+
// Mark as applied
|
|
331
|
+
for (const l of learnings) {
|
|
332
|
+
storage.updateLearning(l.id, { applied: true, appliedAt: Date.now() });
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
content: [
|
|
337
|
+
{
|
|
338
|
+
type: 'text',
|
|
339
|
+
text: `✓ Applied ${pending.length} learning(s) to CLAUDE.md`,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
// gaia_review
|
|
345
|
+
server.tool('gaia_review', 'Review accumulated learnings across all sessions.', {
|
|
346
|
+
scope: LearningScopeSchema.optional().describe('Filter by scope'),
|
|
347
|
+
category: LearningCategorySchema.optional().describe('Filter by category'),
|
|
348
|
+
pendingOnly: z.boolean().optional().describe('Show only unapplied (default: false)'),
|
|
349
|
+
}, async ({ scope, category, pendingOnly = false }) => {
|
|
350
|
+
let learnings = scope ? storage.getLearnings(scope) : storage.getLearnings();
|
|
351
|
+
if (category) {
|
|
352
|
+
learnings = learnings.filter((l) => l.category === category);
|
|
353
|
+
}
|
|
354
|
+
if (pendingOnly) {
|
|
355
|
+
learnings = learnings.filter((l) => !l.applied);
|
|
356
|
+
}
|
|
357
|
+
if (learnings.length === 0) {
|
|
358
|
+
return {
|
|
359
|
+
content: [{ type: 'text', text: 'No learnings found matching criteria.' }],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
let output = `## Learnings (${learnings.length})\n\n`;
|
|
363
|
+
for (const l of learnings) {
|
|
364
|
+
output += `### ${l.id} [${l.category}] ${l.applied ? '✓' : '○'}\n`;
|
|
365
|
+
output += `**Mistake**: ${l.mistakeDescription}\n`;
|
|
366
|
+
output += `**Correction**: ${l.correction}\n\n`;
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
content: [{ type: 'text', text: output }],
|
|
370
|
+
};
|
|
371
|
+
});
|
|
372
|
+
// ===========================================================================
|
|
373
|
+
// Context Tools (Memory)
|
|
374
|
+
// ===========================================================================
|
|
375
|
+
// gaia_remember
|
|
376
|
+
server.tool('gaia_remember', 'Save current context state for later restoration. Gaia remembers everything.', {
|
|
377
|
+
name: z.string().describe('Name for this memory'),
|
|
378
|
+
description: z.string().optional().describe('Description of the context'),
|
|
379
|
+
includeGit: z.boolean().optional().describe('Include git info (default: true)'),
|
|
380
|
+
includeClaudeMd: z.boolean().optional().describe('Include CLAUDE.md (default: true)'),
|
|
381
|
+
notes: z.string().optional().describe('Additional notes'),
|
|
382
|
+
}, async ({ name, description, includeGit = true, includeClaudeMd = true, notes }) => {
|
|
383
|
+
const data = { notes };
|
|
384
|
+
if (includeGit) {
|
|
385
|
+
try {
|
|
386
|
+
const status = await git.getStatus();
|
|
387
|
+
const log = await git.getLog({ count: 5 });
|
|
388
|
+
data.gitBranch = status.branch;
|
|
389
|
+
data.gitStatus = JSON.stringify(status);
|
|
390
|
+
data.gitLog = log.map((l) => `${l.shortHash} ${l.message}`);
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
// Not in git repo
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (includeClaudeMd) {
|
|
397
|
+
try {
|
|
398
|
+
data.claudeMd = await git.readClaudeMd();
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// No CLAUDE.md
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const snapshot = {
|
|
405
|
+
id: `mem_${nanoid(8)}`,
|
|
406
|
+
name,
|
|
407
|
+
description,
|
|
408
|
+
data,
|
|
409
|
+
createdAt: Date.now(),
|
|
410
|
+
};
|
|
411
|
+
storage.addSnapshot(snapshot);
|
|
412
|
+
return {
|
|
413
|
+
content: [
|
|
414
|
+
{
|
|
415
|
+
type: 'text',
|
|
416
|
+
text: `✓ Memory saved: ${snapshot.id}\n\nName: ${name}`,
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
};
|
|
420
|
+
});
|
|
421
|
+
// gaia_recall
|
|
422
|
+
server.tool('gaia_recall', 'Restore a previously saved context. Gaia recalls everything.', {
|
|
423
|
+
memoryId: z.string().optional().describe('Memory ID to restore'),
|
|
424
|
+
name: z.string().optional().describe('Memory name to restore'),
|
|
425
|
+
}, async ({ memoryId, name }) => {
|
|
426
|
+
const snapshot = memoryId
|
|
427
|
+
? storage.getSnapshot(memoryId)
|
|
428
|
+
: name
|
|
429
|
+
? storage.getSnapshotByName(name)
|
|
430
|
+
: null;
|
|
431
|
+
if (!snapshot) {
|
|
432
|
+
// List available memories
|
|
433
|
+
const all = storage.getSnapshots();
|
|
434
|
+
if (all.length === 0) {
|
|
435
|
+
return {
|
|
436
|
+
content: [{ type: 'text', text: 'No memories available.' }],
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
let output = '## Available Memories\n\n';
|
|
440
|
+
for (const s of all) {
|
|
441
|
+
output += `- **${s.name}** (${s.id}): ${s.description || 'No description'}\n`;
|
|
442
|
+
}
|
|
443
|
+
return {
|
|
444
|
+
content: [{ type: 'text', text: output }],
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
let output = `## Recalled: ${snapshot.name}\n\n`;
|
|
448
|
+
if (snapshot.data.gitBranch) {
|
|
449
|
+
output += `**Git Branch**: ${snapshot.data.gitBranch}\n\n`;
|
|
450
|
+
}
|
|
451
|
+
if (snapshot.data.gitLog) {
|
|
452
|
+
output += `**Recent Commits**:\n`;
|
|
453
|
+
for (const log of snapshot.data.gitLog) {
|
|
454
|
+
output += `- ${log}\n`;
|
|
455
|
+
}
|
|
456
|
+
output += '\n';
|
|
457
|
+
}
|
|
458
|
+
if (snapshot.data.notes) {
|
|
459
|
+
output += `**Notes**: ${snapshot.data.notes}\n`;
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
content: [{ type: 'text', text: output }],
|
|
463
|
+
};
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
//# sourceMappingURL=index.js.map
|