@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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/cli.d.ts +12 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +308 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +32 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +78 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/services/config.service.d.ts +92 -0
  12. package/dist/services/config.service.d.ts.map +1 -0
  13. package/dist/services/config.service.js +284 -0
  14. package/dist/services/config.service.js.map +1 -0
  15. package/dist/services/git.service.d.ts +175 -0
  16. package/dist/services/git.service.d.ts.map +1 -0
  17. package/dist/services/git.service.js +395 -0
  18. package/dist/services/git.service.js.map +1 -0
  19. package/dist/services/provider.service.d.ts +74 -0
  20. package/dist/services/provider.service.d.ts.map +1 -0
  21. package/dist/services/provider.service.js +182 -0
  22. package/dist/services/provider.service.js.map +1 -0
  23. package/dist/services/storage.service.d.ts +84 -0
  24. package/dist/services/storage.service.d.ts.map +1 -0
  25. package/dist/services/storage.service.js +320 -0
  26. package/dist/services/storage.service.js.map +1 -0
  27. package/dist/tools/demerzel/index.d.ts +21 -0
  28. package/dist/tools/demerzel/index.d.ts.map +1 -0
  29. package/dist/tools/demerzel/index.js +166 -0
  30. package/dist/tools/demerzel/index.js.map +1 -0
  31. package/dist/tools/gaia/index.d.ts +27 -0
  32. package/dist/tools/gaia/index.d.ts.map +1 -0
  33. package/dist/tools/gaia/index.js +466 -0
  34. package/dist/tools/gaia/index.js.map +1 -0
  35. package/dist/tools/seldon/index.d.ts +43 -0
  36. package/dist/tools/seldon/index.d.ts.map +1 -0
  37. package/dist/tools/seldon/index.js +886 -0
  38. package/dist/tools/seldon/index.js.map +1 -0
  39. package/dist/types/index.d.ts +392 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/index.js +10 -0
  42. package/dist/types/index.js.map +1 -0
  43. 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":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,oBAAoB;IACpB,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,qKAAqK,EACrK;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAC3D,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;QACvG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;KACvG,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACnD,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,uBAAuB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,iBAAiB,IAAI,EAAE;iBACpF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,kBAAkB;IAClB,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,qFAAqF,EACrF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACvD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QAC3E,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;KAC5F,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,GAAG,EAAE,EAAE,eAAe,EAAE,gBAAgB,GAAG,IAAI,EAAE,EAAE,EAAE;QAClG,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,4BAA4B,OAAO,QAAQ,IAAI,EAAE;iBACxD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,mDAAmD,EACnD;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QAC3E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;KACxE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE;QAC/C,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,qCAAqC,OAAO,QAAQ,IAAI,EAAE;iBACjE;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,uBAAuB;IACvB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,gGAAgG,EAChG;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;KACrF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzB,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,6BAA6B,MAAM,QAAQ,IAAI,EAAE;iBACxD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,0BAA0B;IAC1B,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,sFAAsF,EACtF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;KACpF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzB,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,mCAAmC,MAAM,QAAQ,IAAI,EAAE;iBAC9D;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,oBAAoB;IACpB,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,8FAA8F,EAC9F;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;KAC/D,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QACvB,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,qCAAqC,IAAI,QAAQ,IAAI,EAAE;iBAC9D;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,uBAAuB;IACvB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,mGAAmG,EACnG;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QAC1D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAC/C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACnE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE;QACtD,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,wCAAwC,IAAI,OAAO,IAAI,EAAE;iBAChE;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,mBAAmB;IACnB,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,0GAA0G,EAC1G;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;QACxF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;KAClF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,GAAG,EAAE,EAAE,EAAE,EAAE;QACvC,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,yBAAyB,KAAK,QAAQ,IAAI,EAAE;iBACnD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,2BAA2B;IAC3B,MAAM,CAAC,IAAI,CACT,0BAA0B,EAC1B,2FAA2F,EAC3F;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACtD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QAClE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KACvE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,EAAE;QACpC,uCAAuC;QACvC,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,iCAAiC,KAAK,QAAQ,IAAI,EAAE;iBAC3D;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -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