@affectively/aeon-pages 1.3.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 (124) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +625 -0
  3. package/examples/basic/aeon.config.ts +39 -0
  4. package/examples/basic/components/Cursor.tsx +86 -0
  5. package/examples/basic/components/OfflineIndicator.tsx +103 -0
  6. package/examples/basic/components/PresenceBar.tsx +77 -0
  7. package/examples/basic/package.json +20 -0
  8. package/examples/basic/pages/index.tsx +80 -0
  9. package/package.json +101 -0
  10. package/packages/analytics/README.md +309 -0
  11. package/packages/analytics/build.ts +35 -0
  12. package/packages/analytics/package.json +50 -0
  13. package/packages/analytics/src/click-tracker.ts +368 -0
  14. package/packages/analytics/src/context-bridge.ts +319 -0
  15. package/packages/analytics/src/data-layer.ts +302 -0
  16. package/packages/analytics/src/gtm-loader.ts +239 -0
  17. package/packages/analytics/src/index.ts +230 -0
  18. package/packages/analytics/src/merkle-tree.ts +489 -0
  19. package/packages/analytics/src/provider.tsx +300 -0
  20. package/packages/analytics/src/types.ts +320 -0
  21. package/packages/analytics/src/use-analytics.ts +296 -0
  22. package/packages/analytics/tsconfig.json +19 -0
  23. package/packages/benchmarks/src/benchmark.test.ts +691 -0
  24. package/packages/cli/dist/index.js +61899 -0
  25. package/packages/cli/package.json +43 -0
  26. package/packages/cli/src/commands/build.test.ts +682 -0
  27. package/packages/cli/src/commands/build.ts +890 -0
  28. package/packages/cli/src/commands/dev.ts +473 -0
  29. package/packages/cli/src/commands/init.ts +409 -0
  30. package/packages/cli/src/commands/start.ts +297 -0
  31. package/packages/cli/src/index.ts +105 -0
  32. package/packages/directives/src/use-aeon.ts +272 -0
  33. package/packages/mcp-server/package.json +51 -0
  34. package/packages/mcp-server/src/index.ts +178 -0
  35. package/packages/mcp-server/src/resources.ts +346 -0
  36. package/packages/mcp-server/src/tools/index.ts +36 -0
  37. package/packages/mcp-server/src/tools/navigation.ts +545 -0
  38. package/packages/mcp-server/tsconfig.json +21 -0
  39. package/packages/react/package.json +40 -0
  40. package/packages/react/src/Link.tsx +388 -0
  41. package/packages/react/src/components/InstallPrompt.tsx +286 -0
  42. package/packages/react/src/components/OfflineDiagnostics.tsx +677 -0
  43. package/packages/react/src/components/PushNotifications.tsx +453 -0
  44. package/packages/react/src/hooks/useAeonNavigation.ts +219 -0
  45. package/packages/react/src/hooks/useConflicts.ts +277 -0
  46. package/packages/react/src/hooks/useNetworkState.ts +209 -0
  47. package/packages/react/src/hooks/usePilotNavigation.ts +254 -0
  48. package/packages/react/src/hooks/useServiceWorker.ts +278 -0
  49. package/packages/react/src/hooks.ts +195 -0
  50. package/packages/react/src/index.ts +151 -0
  51. package/packages/react/src/provider.tsx +467 -0
  52. package/packages/react/tsconfig.json +19 -0
  53. package/packages/runtime/README.md +399 -0
  54. package/packages/runtime/build.ts +48 -0
  55. package/packages/runtime/package.json +71 -0
  56. package/packages/runtime/schema.sql +40 -0
  57. package/packages/runtime/src/api-routes.ts +465 -0
  58. package/packages/runtime/src/benchmark.ts +171 -0
  59. package/packages/runtime/src/cache.ts +479 -0
  60. package/packages/runtime/src/durable-object.ts +1341 -0
  61. package/packages/runtime/src/index.ts +360 -0
  62. package/packages/runtime/src/navigation.test.ts +421 -0
  63. package/packages/runtime/src/navigation.ts +422 -0
  64. package/packages/runtime/src/nextjs-adapter.ts +272 -0
  65. package/packages/runtime/src/offline/encrypted-queue.test.ts +607 -0
  66. package/packages/runtime/src/offline/encrypted-queue.ts +478 -0
  67. package/packages/runtime/src/offline/encryption.test.ts +412 -0
  68. package/packages/runtime/src/offline/encryption.ts +397 -0
  69. package/packages/runtime/src/offline/types.ts +465 -0
  70. package/packages/runtime/src/predictor.ts +371 -0
  71. package/packages/runtime/src/registry.ts +351 -0
  72. package/packages/runtime/src/router/context-extractor.ts +661 -0
  73. package/packages/runtime/src/router/esi-control-react.tsx +2053 -0
  74. package/packages/runtime/src/router/esi-control.ts +541 -0
  75. package/packages/runtime/src/router/esi-cyrano.ts +779 -0
  76. package/packages/runtime/src/router/esi-format-react.tsx +1744 -0
  77. package/packages/runtime/src/router/esi-react.tsx +1065 -0
  78. package/packages/runtime/src/router/esi-translate-observer.ts +476 -0
  79. package/packages/runtime/src/router/esi-translate-react.tsx +556 -0
  80. package/packages/runtime/src/router/esi-translate.ts +503 -0
  81. package/packages/runtime/src/router/esi.ts +666 -0
  82. package/packages/runtime/src/router/heuristic-adapter.test.ts +295 -0
  83. package/packages/runtime/src/router/heuristic-adapter.ts +557 -0
  84. package/packages/runtime/src/router/index.ts +298 -0
  85. package/packages/runtime/src/router/merkle-capability.ts +473 -0
  86. package/packages/runtime/src/router/speculation.ts +451 -0
  87. package/packages/runtime/src/router/types.ts +630 -0
  88. package/packages/runtime/src/router.test.ts +470 -0
  89. package/packages/runtime/src/router.ts +302 -0
  90. package/packages/runtime/src/server.ts +481 -0
  91. package/packages/runtime/src/service-worker-push.ts +319 -0
  92. package/packages/runtime/src/service-worker.ts +553 -0
  93. package/packages/runtime/src/skeleton-hydrate.ts +237 -0
  94. package/packages/runtime/src/speculation.test.ts +389 -0
  95. package/packages/runtime/src/speculation.ts +486 -0
  96. package/packages/runtime/src/storage.test.ts +1297 -0
  97. package/packages/runtime/src/storage.ts +1048 -0
  98. package/packages/runtime/src/sync/conflict-resolver.test.ts +528 -0
  99. package/packages/runtime/src/sync/conflict-resolver.ts +565 -0
  100. package/packages/runtime/src/sync/coordinator.test.ts +608 -0
  101. package/packages/runtime/src/sync/coordinator.ts +596 -0
  102. package/packages/runtime/src/tree-compiler.ts +295 -0
  103. package/packages/runtime/src/types.ts +728 -0
  104. package/packages/runtime/src/worker.ts +327 -0
  105. package/packages/runtime/tsconfig.json +20 -0
  106. package/packages/runtime/wasm/aeon_pages_runtime.d.ts +504 -0
  107. package/packages/runtime/wasm/aeon_pages_runtime.js +1657 -0
  108. package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm +0 -0
  109. package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm.d.ts +196 -0
  110. package/packages/runtime/wasm/package.json +21 -0
  111. package/packages/runtime/wrangler.toml +41 -0
  112. package/packages/runtime-wasm/Cargo.lock +436 -0
  113. package/packages/runtime-wasm/Cargo.toml +29 -0
  114. package/packages/runtime-wasm/pkg/aeon_pages_runtime.d.ts +480 -0
  115. package/packages/runtime-wasm/pkg/aeon_pages_runtime.js +1568 -0
  116. package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm +0 -0
  117. package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm.d.ts +192 -0
  118. package/packages/runtime-wasm/pkg/package.json +21 -0
  119. package/packages/runtime-wasm/src/hydrate.rs +352 -0
  120. package/packages/runtime-wasm/src/lib.rs +191 -0
  121. package/packages/runtime-wasm/src/render.rs +629 -0
  122. package/packages/runtime-wasm/src/router.rs +298 -0
  123. package/packages/runtime-wasm/src/skeleton.rs +430 -0
  124. package/rfcs/RFC-001-ZERO-DEPENDENCY-RENDERING.md +1446 -0
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Aeon Pages CLI
4
+ *
5
+ * Commands:
6
+ * - aeon init [dir] - Initialize a new Aeon Pages project
7
+ * - aeon dev - Start development server with hot reload
8
+ * - aeon build - Build for production
9
+ * - aeon start - Start production server
10
+ */
11
+
12
+ import { parseArgs } from 'util';
13
+
14
+ const { values, positionals } = parseArgs({
15
+ args: process.argv.slice(2),
16
+ options: {
17
+ help: { type: 'boolean', short: 'h' },
18
+ version: { type: 'boolean', short: 'v' },
19
+ port: { type: 'string', short: 'p', default: '3000' },
20
+ config: { type: 'string', short: 'c' },
21
+ },
22
+ allowPositionals: true,
23
+ });
24
+
25
+ const VERSION = '0.1.0';
26
+
27
+ async function main() {
28
+ if (values.version) {
29
+ console.log(`aeon v${VERSION}`);
30
+ process.exit(0);
31
+ }
32
+
33
+ const command = positionals[0];
34
+
35
+ if (!command || values.help) {
36
+ printHelp();
37
+ process.exit(command ? 0 : 1);
38
+ }
39
+
40
+ switch (command) {
41
+ case 'init':
42
+ await import('./commands/init').then((m) => m.init(positionals[1]));
43
+ break;
44
+
45
+ case 'dev':
46
+ await import('./commands/dev').then((m) =>
47
+ m.dev({ port: parseInt(values.port || '3000'), config: values.config }),
48
+ );
49
+ break;
50
+
51
+ case 'build':
52
+ await import('./commands/build').then((m) =>
53
+ m.build({ config: values.config }),
54
+ );
55
+ break;
56
+
57
+ case 'start':
58
+ await import('./commands/start').then((m) =>
59
+ m.start({
60
+ port: parseInt(values.port || '3000'),
61
+ config: values.config,
62
+ }),
63
+ );
64
+ break;
65
+
66
+ default:
67
+ console.error(`Unknown command: ${command}`);
68
+ printHelp();
69
+ process.exit(1);
70
+ }
71
+ }
72
+
73
+ function printHelp() {
74
+ console.log(`
75
+ aeon v${VERSION} - The CMS IS the website
76
+
77
+ Usage: aeon <command> [options]
78
+
79
+ Commands:
80
+ init [dir] Initialize a new Aeon Pages project
81
+ dev Start development server with hot reload
82
+ build Build for production (Cloudflare Workers)
83
+ start Start production server
84
+
85
+ Options:
86
+ -p, --port Server port (default: 3000)
87
+ -c, --config Path to aeon.config.ts
88
+ -h, --help Show this help message
89
+ -v, --version Show version
90
+
91
+ Examples:
92
+ aeon init my-app Create new project in ./my-app
93
+ aeon dev Start dev server on port 3000
94
+ aeon dev -p 8080 Start dev server on port 8080
95
+ aeon build Build for Cloudflare Workers
96
+ aeon start Start production server
97
+
98
+ Documentation: https://github.com/affectively/aeon-pages
99
+ `);
100
+ }
101
+
102
+ main().catch((err) => {
103
+ console.error('Error:', err.message);
104
+ process.exit(1);
105
+ });
@@ -0,0 +1,272 @@
1
+ /**
2
+ * 'use aeon' Directive Processor
3
+ *
4
+ * Transforms pages with the 'use aeon' directive to enable:
5
+ * - Collaborative editing
6
+ * - Real-time presence
7
+ * - Schema versioning
8
+ * - Offline support
9
+ *
10
+ * @example
11
+ * Input:
12
+ * ```tsx
13
+ * 'use aeon';
14
+ *
15
+ * export default function Page() {
16
+ * return <div>Hello</div>;
17
+ * }
18
+ * ```
19
+ *
20
+ * Output:
21
+ * ```tsx
22
+ * import { AeonPageProvider, useAeonPage } from '@affectively/aeon-pages/react';
23
+ *
24
+ * function Page() {
25
+ * return <div>Hello</div>;
26
+ * }
27
+ *
28
+ * export default function AeonWrappedPage(props) {
29
+ * return (
30
+ * <AeonPageProvider route="/path/to/page">
31
+ * <Page {...props} />
32
+ * </AeonPageProvider>
33
+ * );
34
+ * }
35
+ * ```
36
+ */
37
+
38
+ export interface TransformOptions {
39
+ /** File path for route derivation */
40
+ filePath: string;
41
+ /** Base pages directory */
42
+ pagesDir?: string;
43
+ }
44
+
45
+ export interface TransformResult {
46
+ /** Transformed code */
47
+ code: string;
48
+ /** Whether the file was transformed */
49
+ transformed: boolean;
50
+ /** Derived route from file path */
51
+ route: string;
52
+ }
53
+
54
+ /**
55
+ * Check if a file contains the 'use aeon' directive
56
+ */
57
+ export function hasAeonDirective(code: string): boolean {
58
+ // Match 'use aeon' or "use aeon" at the start of the file
59
+ const directivePattern = /^['"]use aeon['"];?\s*\n/m;
60
+ return directivePattern.test(code.trimStart());
61
+ }
62
+
63
+ /**
64
+ * Process the 'use aeon' directive and transform the code
65
+ */
66
+ export function processAeonDirective(
67
+ code: string,
68
+ options: TransformOptions,
69
+ ): TransformResult {
70
+ const { filePath, pagesDir = './pages' } = options;
71
+
72
+ // Check for directive
73
+ if (!hasAeonDirective(code)) {
74
+ return {
75
+ code,
76
+ transformed: false,
77
+ route: deriveRoute(filePath, pagesDir),
78
+ };
79
+ }
80
+
81
+ const route = deriveRoute(filePath, pagesDir);
82
+
83
+ // Remove the directive
84
+ const codeWithoutDirective = code.replace(/^['"]use aeon['"];?\s*\n/m, '');
85
+
86
+ // Find the default export
87
+ const defaultExportMatch = codeWithoutDirective.match(
88
+ /export\s+default\s+function\s+(\w+)/,
89
+ );
90
+
91
+ if (!defaultExportMatch) {
92
+ // Handle arrow function exports or other patterns
93
+ return transformArrowExport(codeWithoutDirective, route);
94
+ }
95
+
96
+ const componentName = defaultExportMatch[1];
97
+
98
+ // Transform the code
99
+ const transformedCode = `
100
+ // Aeon Pages - Transformed from 'use aeon' directive
101
+ import { AeonPageProvider, useAeonPage } from '@affectively/aeon-pages/react';
102
+
103
+ ${codeWithoutDirective.replace(
104
+ /export\s+default\s+function\s+(\w+)/,
105
+ 'function $1',
106
+ )}
107
+
108
+ // Re-export useAeonPage for convenience
109
+ export { useAeonPage };
110
+
111
+ // Wrapped component with Aeon providers
112
+ export default function AeonWrappedPage(props: any) {
113
+ return (
114
+ <AeonPageProvider route="${route}">
115
+ <${componentName} {...props} />
116
+ </AeonPageProvider>
117
+ );
118
+ }
119
+ `.trim();
120
+
121
+ return {
122
+ code: transformedCode,
123
+ transformed: true,
124
+ route,
125
+ };
126
+ }
127
+
128
+ /**
129
+ * Transform arrow function or other export patterns
130
+ */
131
+ function transformArrowExport(code: string, route: string): TransformResult {
132
+ // Match: export default () => ... or export default function() ...
133
+ const arrowExportMatch = code.match(
134
+ /export\s+default\s+((?:\([^)]*\)|[^=])\s*=>|function\s*\()/,
135
+ );
136
+
137
+ if (!arrowExportMatch) {
138
+ // No recognizable default export, wrap the whole thing
139
+ return {
140
+ code: `
141
+ // Aeon Pages - Transformed from 'use aeon' directive
142
+ import { AeonPageProvider, useAeonPage } from '@affectively/aeon-pages/react';
143
+
144
+ const OriginalPage = (() => {
145
+ ${code}
146
+ return undefined; // Placeholder
147
+ })();
148
+
149
+ export { useAeonPage };
150
+
151
+ export default function AeonWrappedPage(props: any) {
152
+ return (
153
+ <AeonPageProvider route="${route}">
154
+ {OriginalPage}
155
+ </AeonPageProvider>
156
+ );
157
+ }
158
+ `.trim(),
159
+ transformed: true,
160
+ route,
161
+ };
162
+ }
163
+
164
+ // Extract the arrow function/anonymous function
165
+ const transformedCode = `
166
+ // Aeon Pages - Transformed from 'use aeon' directive
167
+ import { AeonPageProvider, useAeonPage } from '@affectively/aeon-pages/react';
168
+
169
+ ${code.replace(/export\s+default\s+/, 'const OriginalPage = ')}
170
+
171
+ export { useAeonPage };
172
+
173
+ export default function AeonWrappedPage(props: any) {
174
+ return (
175
+ <AeonPageProvider route="${route}">
176
+ <OriginalPage {...props} />
177
+ </AeonPageProvider>
178
+ );
179
+ }
180
+ `.trim();
181
+
182
+ return {
183
+ code: transformedCode,
184
+ transformed: true,
185
+ route,
186
+ };
187
+ }
188
+
189
+ /**
190
+ * Derive route from file path
191
+ *
192
+ * @example
193
+ * - pages/index.tsx -> /
194
+ * - pages/about.tsx -> /about
195
+ * - pages/blog/[slug].tsx -> /blog/[slug]
196
+ * - pages/blog/[slug]/page.tsx -> /blog/[slug]
197
+ */
198
+ export function deriveRoute(filePath: string, pagesDir: string): string {
199
+ // Normalize paths
200
+ const normalizedPath = filePath.replace(/\\/g, '/');
201
+ const normalizedPagesDir = pagesDir.replace(/\\/g, '/').replace(/\/$/, '');
202
+
203
+ // Remove pages directory prefix
204
+ let route = normalizedPath;
205
+ if (route.startsWith(normalizedPagesDir)) {
206
+ route = route.slice(normalizedPagesDir.length);
207
+ }
208
+
209
+ // Remove file extension
210
+ route = route.replace(/\.(tsx?|jsx?)$/, '');
211
+
212
+ // Remove /page suffix (Next.js app router style)
213
+ route = route.replace(/\/page$/, '');
214
+
215
+ // Remove /index suffix
216
+ route = route.replace(/\/index$/, '');
217
+
218
+ // Handle route groups (parentheses)
219
+ route = route.replace(/\/\([^)]+\)/g, '');
220
+
221
+ // Ensure leading slash
222
+ if (!route.startsWith('/')) {
223
+ route = '/' + route;
224
+ }
225
+
226
+ // Handle root
227
+ if (route === '' || route === '/') {
228
+ return '/';
229
+ }
230
+
231
+ return route;
232
+ }
233
+
234
+ /**
235
+ * Bun plugin for processing 'use aeon' directives
236
+ */
237
+ export function aeonBunPlugin(options: { pagesDir?: string } = {}) {
238
+ return {
239
+ name: 'aeon-directive',
240
+ setup(build: { onLoad: (opts: unknown, callback: unknown) => void }) {
241
+ build.onLoad(
242
+ { filter: /\.(tsx?|jsx?)$/ },
243
+ async (args: { path: string }) => {
244
+ const file = Bun.file(args.path);
245
+ const code = await file.text();
246
+
247
+ if (!hasAeonDirective(code)) {
248
+ return undefined; // Let Bun handle it normally
249
+ }
250
+
251
+ const result = processAeonDirective(code, {
252
+ filePath: args.path,
253
+ pagesDir: options.pagesDir,
254
+ });
255
+
256
+ return {
257
+ contents: result.code,
258
+ loader: args.path.endsWith('.tsx') ? 'tsx' : 'ts',
259
+ };
260
+ },
261
+ );
262
+ },
263
+ };
264
+ }
265
+
266
+ // Export for use in build tools
267
+ export default {
268
+ hasAeonDirective,
269
+ processAeonDirective,
270
+ deriveRoute,
271
+ aeonBunPlugin,
272
+ };
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@aeon/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for aeon-flux site navigation - enables Cyrano to suggest and invoke navigation",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "aeon-mcp": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.0.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.7.0",
22
+ "@types/node": "^22.0.0"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js"
31
+ },
32
+ "./tools": {
33
+ "types": "./dist/tools/navigation.d.ts",
34
+ "import": "./dist/tools/navigation.js"
35
+ },
36
+ "./resources": {
37
+ "types": "./dist/resources.d.ts",
38
+ "import": "./dist/resources.js"
39
+ }
40
+ },
41
+ "keywords": [
42
+ "mcp",
43
+ "model-context-protocol",
44
+ "aeon-flux",
45
+ "cyrano",
46
+ "navigation",
47
+ "ai"
48
+ ],
49
+ "author": "AFFECTIVELY",
50
+ "license": "MIT"
51
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Aeon Flux MCP Server
3
+ *
4
+ * Model Context Protocol server for aeon-flux site navigation.
5
+ * Enables Cyrano to suggest and invoke navigation with auto-accept mode.
6
+ *
7
+ * Tools:
8
+ * - navigate: Navigate to a route
9
+ * - suggest_route: Suggest a route to the user
10
+ * - get_current_route: Get the current route
11
+ * - get_sitemap: Get the site structure
12
+ * - speculate: Prefetch likely next routes
13
+ * - personalize: Apply personalization to current page
14
+ *
15
+ * Resources:
16
+ * - sitemap: Full sitemap as RAG context
17
+ * - current_session: Current user session data
18
+ * - consciousness_state: Site consciousness state
19
+ */
20
+
21
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
22
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
23
+ import {
24
+ CallToolRequestSchema,
25
+ ListToolsRequestSchema,
26
+ ListResourcesRequestSchema,
27
+ ReadResourceRequestSchema,
28
+ } from '@modelcontextprotocol/sdk/types.js';
29
+
30
+ import {
31
+ navigateTool,
32
+ suggestRouteTool,
33
+ getCurrentRouteTool,
34
+ getSitemapTool,
35
+ speculateTool,
36
+ personalizeTool,
37
+ invokeToolTool,
38
+ handleNavigate,
39
+ handleSuggestRoute,
40
+ handleGetCurrentRoute,
41
+ handleGetSitemap,
42
+ handleSpeculate,
43
+ handlePersonalize,
44
+ handleInvokeTool,
45
+ } from './tools/navigation';
46
+
47
+ import {
48
+ sitemapResource,
49
+ sessionResource,
50
+ consciousnessResource,
51
+ handleReadSitemap,
52
+ handleReadSession,
53
+ handleReadConsciousness,
54
+ } from './resources';
55
+
56
+ // ============================================================================
57
+ // Server Setup
58
+ // ============================================================================
59
+
60
+ const server = new Server(
61
+ {
62
+ name: 'aeon-flux',
63
+ version: '1.0.0',
64
+ },
65
+ {
66
+ capabilities: {
67
+ tools: {},
68
+ resources: {},
69
+ },
70
+ },
71
+ );
72
+
73
+ // ============================================================================
74
+ // Tool Handlers
75
+ // ============================================================================
76
+
77
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
78
+ return {
79
+ tools: [
80
+ navigateTool,
81
+ suggestRouteTool,
82
+ getCurrentRouteTool,
83
+ getSitemapTool,
84
+ speculateTool,
85
+ personalizeTool,
86
+ invokeToolTool,
87
+ ],
88
+ };
89
+ });
90
+
91
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
92
+ const { name, arguments: args } = request.params;
93
+
94
+ switch (name) {
95
+ case 'navigate':
96
+ return handleNavigate(args as { route: string; autoAccept?: boolean });
97
+
98
+ case 'suggest_route':
99
+ return handleSuggestRoute(
100
+ args as {
101
+ route: string;
102
+ reason: string;
103
+ autoAccept?: boolean;
104
+ },
105
+ );
106
+
107
+ case 'get_current_route':
108
+ return handleGetCurrentRoute();
109
+
110
+ case 'get_sitemap':
111
+ return handleGetSitemap(args as { filter?: string });
112
+
113
+ case 'speculate':
114
+ return handleSpeculate(args as { depth?: number });
115
+
116
+ case 'personalize':
117
+ return handlePersonalize(
118
+ args as {
119
+ theme?: 'light' | 'dark';
120
+ accent?: string;
121
+ density?: 'compact' | 'normal' | 'comfortable';
122
+ },
123
+ );
124
+
125
+ case 'invoke_tool':
126
+ return handleInvokeTool(
127
+ args as {
128
+ toolId: string;
129
+ params?: Record<string, unknown>;
130
+ },
131
+ );
132
+
133
+ default:
134
+ throw new Error(`Unknown tool: ${name}`);
135
+ }
136
+ });
137
+
138
+ // ============================================================================
139
+ // Resource Handlers
140
+ // ============================================================================
141
+
142
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
143
+ return {
144
+ resources: [sitemapResource, sessionResource, consciousnessResource],
145
+ };
146
+ });
147
+
148
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
149
+ const { uri } = request.params;
150
+
151
+ switch (uri) {
152
+ case 'aeon://sitemap':
153
+ return handleReadSitemap();
154
+
155
+ case 'aeon://session':
156
+ return handleReadSession();
157
+
158
+ case 'aeon://consciousness':
159
+ return handleReadConsciousness();
160
+
161
+ default:
162
+ throw new Error(`Unknown resource: ${uri}`);
163
+ }
164
+ });
165
+
166
+ // ============================================================================
167
+ // Main
168
+ // ============================================================================
169
+
170
+ async function main() {
171
+ const transport = new StdioServerTransport();
172
+ await server.connect(transport);
173
+ console.error('Aeon Flux MCP Server running on stdio');
174
+ }
175
+
176
+ main().catch(console.error);
177
+
178
+ export { server };