mcp-codex-subagent 1.0.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 (70) hide show
  1. package/README.md +121 -0
  2. package/dist/errors.d.ts +16 -0
  3. package/dist/errors.d.ts.map +1 -0
  4. package/dist/errors.js +35 -0
  5. package/dist/errors.js.map +1 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +19 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/server.d.ts +10 -0
  11. package/dist/server.d.ts.map +1 -0
  12. package/dist/server.js +90 -0
  13. package/dist/server.js.map +1 -0
  14. package/dist/session/storage.d.ts +44 -0
  15. package/dist/session/storage.d.ts.map +1 -0
  16. package/dist/session/storage.js +113 -0
  17. package/dist/session/storage.js.map +1 -0
  18. package/dist/templates/index.d.ts +22 -0
  19. package/dist/templates/index.d.ts.map +1 -0
  20. package/dist/templates/index.js +147 -0
  21. package/dist/templates/index.js.map +1 -0
  22. package/dist/templates/overlays/coder-csharp.mdx +58 -0
  23. package/dist/templates/overlays/coder-go.mdx +53 -0
  24. package/dist/templates/overlays/coder-java.mdx +54 -0
  25. package/dist/templates/overlays/coder-kotlin.mdx +56 -0
  26. package/dist/templates/overlays/coder-nextjs.mdx +65 -0
  27. package/dist/templates/overlays/coder-python.mdx +53 -0
  28. package/dist/templates/overlays/coder-react.mdx +55 -0
  29. package/dist/templates/overlays/coder-ruby.mdx +59 -0
  30. package/dist/templates/overlays/coder-rust.mdx +48 -0
  31. package/dist/templates/overlays/coder-supabase.mdx +268 -0
  32. package/dist/templates/overlays/coder-supastarter.mdx +313 -0
  33. package/dist/templates/overlays/coder-swift.mdx +56 -0
  34. package/dist/templates/overlays/coder-tauri.mdx +566 -0
  35. package/dist/templates/overlays/coder-triggerdev.mdx +296 -0
  36. package/dist/templates/overlays/coder-typescript.mdx +45 -0
  37. package/dist/templates/overlays/coder-vue.mdx +62 -0
  38. package/dist/templates/overlays/planner-architecture.mdx +78 -0
  39. package/dist/templates/overlays/planner-bugfix.mdx +36 -0
  40. package/dist/templates/overlays/planner-feature.mdx +38 -0
  41. package/dist/templates/overlays/planner-migration.mdx +50 -0
  42. package/dist/templates/overlays/planner-refactor.mdx +57 -0
  43. package/dist/templates/overlays/researcher-library.mdx +59 -0
  44. package/dist/templates/overlays/researcher-performance.mdx +68 -0
  45. package/dist/templates/overlays/researcher-security.mdx +86 -0
  46. package/dist/templates/overlays/tester-graphql.mdx +191 -0
  47. package/dist/templates/overlays/tester-playwright.mdx +621 -0
  48. package/dist/templates/overlays/tester-rest.mdx +101 -0
  49. package/dist/templates/overlays/tester-suite.mdx +177 -0
  50. package/dist/templates/super-coder.mdx +529 -0
  51. package/dist/templates/super-planner.mdx +568 -0
  52. package/dist/templates/super-researcher.mdx +406 -0
  53. package/dist/templates/super-tester.mdx +243 -0
  54. package/dist/tools/definitions.d.ts +3 -0
  55. package/dist/tools/definitions.d.ts.map +1 -0
  56. package/dist/tools/definitions.js +186 -0
  57. package/dist/tools/definitions.js.map +1 -0
  58. package/dist/tools/handlers.d.ts +30 -0
  59. package/dist/tools/handlers.d.ts.map +1 -0
  60. package/dist/tools/handlers.js +370 -0
  61. package/dist/tools/handlers.js.map +1 -0
  62. package/dist/types.d.ts +118 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +65 -0
  65. package/dist/types.js.map +1 -0
  66. package/dist/utils/command.d.ts +19 -0
  67. package/dist/utils/command.d.ts.map +1 -0
  68. package/dist/utils/command.js +171 -0
  69. package/dist/utils/command.js.map +1 -0
  70. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # Codex MCP Server
2
+
3
+ [![npm version](https://img.shields.io/npm/v/codex-mcp-server.svg)](https://www.npmjs.com/package/codex-mcp-server)
4
+ [![npm downloads](https://img.shields.io/npm/dm/codex-mcp-server.svg)](https://www.npmjs.com/package/codex-mcp-server)
5
+ [![license](https://img.shields.io/npm/l/codex-mcp-server.svg)](https://www.npmjs.com/package/codex-mcp-server)
6
+
7
+ Bridge between Claude and OpenAI's Codex CLI — get AI-powered code analysis, generation, and review right in your editor.
8
+
9
+ ```mermaid
10
+ graph LR
11
+ A[Claude Code] --> B[Codex MCP Server]
12
+ B --> C[Codex CLI]
13
+ C --> D[OpenAI API]
14
+
15
+ style A fill:#FF6B35
16
+ style B fill:#4A90E2
17
+ style C fill:#00D4AA
18
+ style D fill:#FFA500
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Install Codex CLI
24
+
25
+ ```bash
26
+ npm i -g @openai/codex
27
+ codex login --api-key "your-openai-api-key"
28
+ ```
29
+
30
+ ### 2. Add to Claude Code
31
+
32
+ ```bash
33
+ claude mcp add codex-cli -- npx -y codex-mcp-server
34
+ ```
35
+
36
+ ### 3. Start Using
37
+
38
+ ```
39
+ Ask codex to explain this function
40
+ Use codex to refactor this code for better performance
41
+ Use review to check my uncommitted changes
42
+ ```
43
+
44
+ ## One-Click Install
45
+
46
+ [![VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=codex-cli&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22codex-mcp-server%22%5D%7D)
47
+ [![VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=codex-cli&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22codex-mcp-server%22%5D%7D)
48
+ [![Cursor](https://img.shields.io/badge/Cursor-Install-00D8FF?style=flat-square&logo=cursor&logoColor=white)](https://cursor.com/en/install-mcp?name=codex&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IC15IGNvZGV4LW1jcC1zZXJ2ZXIiLCJlbnYiOnt9fQ%3D%3D)
49
+
50
+ ## Tools
51
+
52
+ | Tool | Description |
53
+ |------|-------------|
54
+ | `codex` | AI coding assistant with session support, model selection, and structured output metadata |
55
+ | `review` | AI-powered code review for uncommitted changes, branches, or commits |
56
+ | `listSessions` | View active conversation sessions |
57
+ | `ping` | Test server connection |
58
+ | `help` | Get Codex CLI help |
59
+
60
+ ## Examples
61
+
62
+ **Code analysis:**
63
+ ```
64
+ Use codex to analyze this authentication logic for security issues
65
+ ```
66
+
67
+ **Multi-turn conversations:**
68
+ ```
69
+ Use codex with sessionId "refactor" to analyze this module
70
+ Use codex with sessionId "refactor" to implement your suggestions
71
+ ```
72
+ Passing a sessionId creates the session on first use, so listSessions will show
73
+ it (for this server instance) and subsequent calls can resume context.
74
+
75
+ **Code review:**
76
+ ```
77
+ Use review with base "main" to check my PR changes
78
+ Use review with uncommitted true to review my local changes
79
+ ```
80
+
81
+ **Advanced options:**
82
+ ```
83
+ Use codex with model "o3" and reasoningEffort "high" for complex analysis
84
+ Use codex with fullAuto true and sandbox "workspace-write" for automated tasks
85
+ Use codex with callbackUri "http://localhost:1234/callback" for static callbacks
86
+ Use codex to return structuredContent with threadId metadata when available
87
+ ```
88
+
89
+ ## Requirements
90
+
91
+ - **Codex CLI v0.75.0+** — Install with `npm i -g @openai/codex` or `brew install codex`
92
+ - **OpenAI API key** — Run `codex login --api-key "your-key"` to authenticate
93
+
94
+ ## Codex 0.87 Compatibility
95
+ - **Thread ID + structured output**: When Codex CLI emits `threadId`, this server returns it in content metadata and `structuredContent`, and advertises an `outputSchema` for structured responses.
96
+
97
+ ## Documentation
98
+
99
+ - **[API Reference](docs/api-reference.md)** — Full tool parameters and response formats
100
+ - **[Session Management](docs/session-management.md)** — How conversations work
101
+ - **[Codex CLI Integration](docs/codex-cli-integration.md)** — Version compatibility and CLI details
102
+
103
+ ## Environment Variables
104
+ - `CODEX_MCP_CALLBACK_URI`: Static MCP callback URI passed to Codex when set (overridden by `callbackUri` tool arg)
105
+
106
+ ## Development
107
+
108
+ ```bash
109
+ npm install # Install dependencies
110
+ npm run dev # Development mode
111
+ npm run build # Build for production
112
+ npm test # Run tests
113
+ ```
114
+
115
+ ## Related Projects
116
+
117
+ - **[gemini-mcp-server](https://github.com/tuannvm/gemini-mcp-server)** — MCP server for Gemini CLI with 1M+ token context, web search, and media analysis
118
+
119
+ ## License
120
+
121
+ ISC
@@ -0,0 +1,16 @@
1
+ export declare class ToolExecutionError extends Error {
2
+ readonly toolName: string;
3
+ readonly cause?: unknown | undefined;
4
+ constructor(toolName: string, message: string, cause?: unknown | undefined);
5
+ }
6
+ export declare class CommandExecutionError extends Error {
7
+ readonly command: string;
8
+ readonly cause?: unknown | undefined;
9
+ constructor(command: string, message: string, cause?: unknown | undefined);
10
+ }
11
+ export declare class ValidationError extends Error {
12
+ readonly toolName: string;
13
+ constructor(toolName: string, message: string);
14
+ }
15
+ export declare function handleError(error: unknown, context: string): string;
16
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,QAAQ,EAAE,MAAM;aAEhB,KAAK,CAAC,EAAE,OAAO;gBAFf,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAED,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,OAAO,EAAE,MAAM;aAEf,KAAK,CAAC,EAAE,OAAO;gBAFf,OAAO,EAAE,MAAM,EAC/B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM;CAKlB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnE"}
package/dist/errors.js ADDED
@@ -0,0 +1,35 @@
1
+ export class ToolExecutionError extends Error {
2
+ toolName;
3
+ cause;
4
+ constructor(toolName, message, cause) {
5
+ super(`Failed to execute tool "${toolName}": ${message}`);
6
+ this.toolName = toolName;
7
+ this.cause = cause;
8
+ this.name = 'ToolExecutionError';
9
+ }
10
+ }
11
+ export class CommandExecutionError extends Error {
12
+ command;
13
+ cause;
14
+ constructor(command, message, cause) {
15
+ super(`Command execution failed for "${command}": ${message}`);
16
+ this.command = command;
17
+ this.cause = cause;
18
+ this.name = 'CommandExecutionError';
19
+ }
20
+ }
21
+ export class ValidationError extends Error {
22
+ toolName;
23
+ constructor(toolName, message) {
24
+ super(`Validation failed for tool "${toolName}": ${message}`);
25
+ this.toolName = toolName;
26
+ this.name = 'ValidationError';
27
+ }
28
+ }
29
+ export function handleError(error, context) {
30
+ if (error instanceof Error) {
31
+ return `Error in ${context}: ${error.message}`;
32
+ }
33
+ return `Error in ${context}: ${String(error)}`;
34
+ }
35
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEzB;IAEA;IAHlB,YACkB,QAAgB,EAChC,OAAe,EACC,KAAe;QAE/B,KAAK,CAAC,2BAA2B,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;QAJ1C,aAAQ,GAAR,QAAQ,CAAQ;QAEhB,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAE5B;IAEA;IAHlB,YACkB,OAAe,EAC/B,OAAe,EACC,KAAe;QAE/B,KAAK,CAAC,iCAAiC,OAAO,MAAM,OAAO,EAAE,CAAC,CAAC;QAJ/C,YAAO,GAAP,OAAO,CAAQ;QAEf,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB;IADlB,YACkB,QAAgB,EAChC,OAAe;QAEf,KAAK,CAAC,+BAA+B,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;QAH9C,aAAQ,GAAR,QAAQ,CAAQ;QAIhC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,OAAe;IACzD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,YAAY,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,YAAY,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACjD,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import chalk from 'chalk';
3
+ import { CodexMcpServer } from './server.js';
4
+ const SERVER_CONFIG = {
5
+ name: 'codex-mcp-server',
6
+ version: '0.0.6',
7
+ };
8
+ async function main() {
9
+ try {
10
+ const server = new CodexMcpServer(SERVER_CONFIG);
11
+ await server.start();
12
+ }
13
+ catch (error) {
14
+ console.error(chalk.red('Failed to start server:'), error);
15
+ process.exit(1);
16
+ }
17
+ }
18
+ main();
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,OAAO;CACR,CAAC;AAEX,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,aAAa,CAAC,CAAC;QACjD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,KAAK,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type ServerConfig } from './types.js';
2
+ export declare class CodexMcpServer {
3
+ private readonly server;
4
+ private readonly config;
5
+ constructor(config: ServerConfig);
6
+ private setupHandlers;
7
+ private isValidToolName;
8
+ start(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,YAAY,CAAC;AAKpB,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,YAAY;IAiBhC,OAAO,CAAC,aAAa;IA4DrB,OAAO,CAAC,eAAe;IAIjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
package/dist/server.js ADDED
@@ -0,0 +1,90 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
+ import chalk from 'chalk';
5
+ import { TOOLS, } from './types.js';
6
+ import { handleError } from './errors.js';
7
+ import { toolDefinitions } from './tools/definitions.js';
8
+ import { toolHandlers } from './tools/handlers.js';
9
+ export class CodexMcpServer {
10
+ server;
11
+ config;
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.server = new Server({
15
+ name: config.name,
16
+ version: config.version,
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ this.setupHandlers();
23
+ }
24
+ setupHandlers() {
25
+ // List tools handler
26
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
27
+ return { tools: toolDefinitions };
28
+ });
29
+ // Call tool handler
30
+ this.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
31
+ const { name, arguments: args } = request.params;
32
+ const progressToken = request.params._meta?.progressToken;
33
+ // Create progress sender that uses MCP notifications
34
+ const createProgressContext = () => {
35
+ let progressCount = 0;
36
+ return {
37
+ progressToken,
38
+ sendProgress: async (message, progress, total) => {
39
+ if (!progressToken)
40
+ return;
41
+ progressCount++;
42
+ try {
43
+ await extra.sendNotification({
44
+ method: 'notifications/progress',
45
+ params: {
46
+ progressToken,
47
+ progress: progress ?? progressCount,
48
+ total,
49
+ message,
50
+ },
51
+ });
52
+ }
53
+ catch (err) {
54
+ // Log but don't fail the operation if progress notification fails
55
+ console.error(chalk.yellow('Failed to send progress notification:'), err);
56
+ }
57
+ },
58
+ };
59
+ };
60
+ try {
61
+ if (!this.isValidToolName(name)) {
62
+ throw new Error(`Unknown tool: ${name}`);
63
+ }
64
+ const handler = toolHandlers[name];
65
+ const context = createProgressContext();
66
+ return await handler.execute(args, context);
67
+ }
68
+ catch (error) {
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: handleError(error, `tool "${name}"`),
74
+ },
75
+ ],
76
+ isError: true,
77
+ };
78
+ }
79
+ });
80
+ }
81
+ isValidToolName(name) {
82
+ return Object.values(TOOLS).includes(name);
83
+ }
84
+ async start() {
85
+ const transport = new StdioServerTransport();
86
+ await this.server.connect(transport);
87
+ console.error(chalk.green(`${this.config.name} started successfully`));
88
+ }
89
+ }
90
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface ConversationTurn {
2
+ prompt: string;
3
+ response: string;
4
+ timestamp: Date;
5
+ }
6
+ export interface SessionData {
7
+ id: string;
8
+ createdAt: Date;
9
+ lastAccessedAt: Date;
10
+ turns: ConversationTurn[];
11
+ codexConversationId?: string;
12
+ }
13
+ export interface SessionStorage {
14
+ createSession(): string;
15
+ ensureSession(sessionId: string): void;
16
+ getSession(sessionId: string): SessionData | undefined;
17
+ updateSession(sessionId: string, data: Partial<SessionData>): void;
18
+ deleteSession(sessionId: string): boolean;
19
+ listSessions(): SessionData[];
20
+ addTurn(sessionId: string, turn: ConversationTurn): void;
21
+ resetSession(sessionId: string): void;
22
+ setCodexConversationId(sessionId: string, conversationId: string): void;
23
+ getCodexConversationId(sessionId: string): string | undefined;
24
+ }
25
+ export declare class InMemorySessionStorage implements SessionStorage {
26
+ private sessions;
27
+ private readonly maxSessions;
28
+ private readonly sessionTtl;
29
+ private readonly maxSessionIdLength;
30
+ private readonly sessionIdPattern;
31
+ createSession(): string;
32
+ ensureSession(sessionId: string): void;
33
+ getSession(sessionId: string): SessionData | undefined;
34
+ updateSession(sessionId: string, data: Partial<SessionData>): void;
35
+ deleteSession(sessionId: string): boolean;
36
+ listSessions(): SessionData[];
37
+ addTurn(sessionId: string, turn: ConversationTurn): void;
38
+ resetSession(sessionId: string): void;
39
+ setCodexConversationId(sessionId: string, conversationId: string): void;
40
+ getCodexConversationId(sessionId: string): string | undefined;
41
+ private cleanupExpiredSessions;
42
+ private enforceMaxSessions;
43
+ }
44
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/session/storage.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC;IACrB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,IAAI,MAAM,CAAC;IACxB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IACnE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,YAAY,IAAI,WAAW,EAAE,CAAC;IAC9B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACzD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC/D;AAED,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsB;IAEvD,aAAa,IAAI,MAAM;IAiBvB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA+BtC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAQtD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAQlE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIzC,YAAY,IAAI,WAAW,EAAE;IAO7B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAYxD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IASrC,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI;IAQvE,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK7D,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,kBAAkB;CAU3B"}
@@ -0,0 +1,113 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { TOOLS } from '../types.js';
3
+ import { ValidationError } from '../errors.js';
4
+ export class InMemorySessionStorage {
5
+ sessions = new Map();
6
+ maxSessions = 100;
7
+ sessionTtl = 24 * 60 * 60 * 1000; // 24 hours
8
+ maxSessionIdLength = 256;
9
+ sessionIdPattern = /^[a-zA-Z0-9_-]+$/;
10
+ createSession() {
11
+ this.cleanupExpiredSessions();
12
+ const sessionId = randomUUID();
13
+ const now = new Date();
14
+ this.sessions.set(sessionId, {
15
+ id: sessionId,
16
+ createdAt: now,
17
+ lastAccessedAt: now,
18
+ turns: [],
19
+ });
20
+ this.enforceMaxSessions();
21
+ return sessionId;
22
+ }
23
+ ensureSession(sessionId) {
24
+ this.cleanupExpiredSessions();
25
+ if (!sessionId ||
26
+ sessionId.length > this.maxSessionIdLength ||
27
+ !this.sessionIdPattern.test(sessionId)) {
28
+ throw new ValidationError(TOOLS.CODEX, 'Session ID must be 1-256 characters and contain only letters, numbers, hyphens, and underscores');
29
+ }
30
+ const existing = this.sessions.get(sessionId);
31
+ if (existing) {
32
+ existing.lastAccessedAt = new Date();
33
+ return;
34
+ }
35
+ const now = new Date();
36
+ this.sessions.set(sessionId, {
37
+ id: sessionId,
38
+ createdAt: now,
39
+ lastAccessedAt: now,
40
+ turns: [],
41
+ });
42
+ this.enforceMaxSessions();
43
+ }
44
+ getSession(sessionId) {
45
+ const session = this.sessions.get(sessionId);
46
+ if (session) {
47
+ session.lastAccessedAt = new Date();
48
+ }
49
+ return session;
50
+ }
51
+ updateSession(sessionId, data) {
52
+ const session = this.sessions.get(sessionId);
53
+ if (session) {
54
+ Object.assign(session, data);
55
+ session.lastAccessedAt = new Date();
56
+ }
57
+ }
58
+ deleteSession(sessionId) {
59
+ return this.sessions.delete(sessionId);
60
+ }
61
+ listSessions() {
62
+ this.cleanupExpiredSessions();
63
+ return Array.from(this.sessions.values()).sort((a, b) => b.lastAccessedAt.getTime() - a.lastAccessedAt.getTime());
64
+ }
65
+ addTurn(sessionId, turn) {
66
+ const session = this.sessions.get(sessionId);
67
+ if (session) {
68
+ // Ensure turns array exists and is valid
69
+ if (!Array.isArray(session.turns)) {
70
+ session.turns = [];
71
+ }
72
+ session.turns.push(turn);
73
+ session.lastAccessedAt = new Date();
74
+ }
75
+ }
76
+ resetSession(sessionId) {
77
+ const session = this.sessions.get(sessionId);
78
+ if (session) {
79
+ session.turns = [];
80
+ session.codexConversationId = undefined;
81
+ session.lastAccessedAt = new Date();
82
+ }
83
+ }
84
+ setCodexConversationId(sessionId, conversationId) {
85
+ const session = this.sessions.get(sessionId);
86
+ if (session) {
87
+ session.codexConversationId = conversationId;
88
+ session.lastAccessedAt = new Date();
89
+ }
90
+ }
91
+ getCodexConversationId(sessionId) {
92
+ const session = this.sessions.get(sessionId);
93
+ return session?.codexConversationId;
94
+ }
95
+ cleanupExpiredSessions() {
96
+ const now = Date.now();
97
+ for (const [sessionId, session] of this.sessions) {
98
+ if (now - session.lastAccessedAt.getTime() > this.sessionTtl) {
99
+ this.sessions.delete(sessionId);
100
+ }
101
+ }
102
+ }
103
+ enforceMaxSessions() {
104
+ if (this.sessions.size <= this.maxSessions)
105
+ return;
106
+ const sessions = this.listSessions();
107
+ const sessionsToDelete = sessions.slice(this.maxSessions);
108
+ for (const session of sessionsToDelete) {
109
+ this.sessions.delete(session.id);
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/session/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export declare const TASK_TYPES: {
2
+ readonly 'super-coder': "super coder for all coding tasks";
3
+ readonly 'super-planner': "super planner for all planning tasks";
4
+ readonly 'super-researcher': "super researcher for answering any question";
5
+ readonly 'super-tester': "super tester to test stuff properly";
6
+ };
7
+ export type TaskType = keyof typeof TASK_TYPES;
8
+ export declare const TASK_TYPE_IDS: TaskType[];
9
+ export declare function isValidTaskType(type: string): type is TaskType;
10
+ /**
11
+ * Matryoshka template resolution:
12
+ * base template (super-coder.mdx)
13
+ * + specialization overlay (overlays/coder-typescript.mdx)
14
+ * + user prompt (injected at {{user_prompt}})
15
+ *
16
+ * The overlay is inserted before the "## BEGIN" section of the base template.
17
+ * If no overlay or no BEGIN section, overlay is appended before user prompt injection.
18
+ *
19
+ * When MCP_ENABLED_TOOLS is set, TOOLKIT table rows are filtered to only show enabled tools.
20
+ */
21
+ export declare function applyTemplate(taskType: TaskType, userPrompt: string, specialization?: string): string;
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,UAAU,CAAC;AAC/C,eAAO,MAAM,aAAa,EAA8B,QAAQ,EAAE,CAAC;AAmFnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,QAAQ,CAE9D;AAaD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAsCrG"}