Skip to content

Commit 1ea6dea

Browse files
feat(watch-mode): introduce CODEX trigger pattern for watch mode
1 parent 499c33f commit 1ea6dea

File tree

3 files changed

+37
-38
lines changed

3 files changed

+37
-38
lines changed

codex-cli/src/utils/config.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export type StoredConfig = {
143143
/** Configuration for watch mode */
144144
watchMode?: {
145145
/**
146-
* Custom trigger pattern. Default is '/(?:\/\/|#|--|;|\'|%|REM)\s*(.*?)(?:,\s*)?AI[!?]/i'.
146+
* Custom trigger pattern. Default is '/\\/\\/\\s*CODEX:\\s+(.*)/i'.
147147
* Must be a valid regular expression string, with the first capture group containing the instruction.
148148
* Examples:
149149
* - '/(?:\/\/|#)\s*AI:(TODO|FIXME)\s+(.*)/i' to match "// AI:TODO fix this" or "# AI:FIXME handle errors"
@@ -195,7 +195,7 @@ export type AppConfig = {
195195
/** Configuration for watch mode */
196196
watchMode?: {
197197
/**
198-
* Custom trigger pattern. Default is '/(?:\/\/|#|--|;|\'|%|REM)\s*(.*?)(?:,\s*)?AI[!?]/i'.
198+
* Custom trigger pattern. Default is '/\\/\\/\\s*CODEX:\\s+(.*)/i'.
199199
* Must be a valid regular expression string, with the first capture group containing the instruction.
200200
* Examples:
201201
* - '/(?:\/\/|#)\s*AI:(TODO|FIXME)\s+(.*)/i' to match "// AI:TODO fix this" or "# AI:FIXME handle errors"

codex-cli/src/utils/watch-mode-utils.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import { loadConfig } from "./config";
1616
*
1717
* Examples:
1818
*
19-
* Default pattern (single-line comments ending with AI! or AI?):
20-
* - "// what does this function do, AI?"
21-
* - "# Fix this code, AI!"
22-
* - "-- Optimize this query, AI!"
19+
* Default pattern (single-line comments starting with "// CODEX: "):
20+
* - "// CODEX: what does this function do"
21+
* - "// CODEX: Fix this code"
22+
* - "// CODEX: Optimize this query"
2323
*
2424
* Custom pattern for task management:
2525
* - "// AI:TODO fix this bug"
@@ -32,7 +32,7 @@ import { loadConfig } from "./config";
3232
*/
3333

3434
// Default trigger pattern
35-
const DEFAULT_TRIGGER_PATTERN = '/(?:\\/\\/|#|--|;|\'|%|REM)\\s*(.*?)(?:,\\s*)?AI[!?]/i';
35+
const DEFAULT_TRIGGER_PATTERN = '/\\/\\/\\s*CODEX:\\s+(.*)/i';
3636

3737
/**
3838
* Get the configured trigger pattern from config.json or use the default
@@ -124,7 +124,7 @@ export function extractContextAroundTrigger(
124124
: "fix or improve this code";
125125

126126
// Remove any comment prefixes that might have been captured
127-
instruction = instruction.replace(/^(?:\/\/|#|--|;|'|%|REM)\s*/, "");
127+
instruction = instruction.replace(/^(?:\/\/|#|--|;|'|%|REM)\s*CODEX:\s*/, "").replace(/^(?:\/\/|#|--|;|'|%|REM)\s*/, "");
128128

129129
return { context, instruction };
130130
}

codex-cli/tests/watch-mode-trigger-extraction.test.ts

+29-30
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,52 @@ import {
1212
const TEST_CONTEXT_SIZE = 20;
1313

1414
describe("Watch mode trigger pattern matching", () => {
15-
it("should detect double-slash (JS-style) AI triggers", () => {
15+
it("should detect double-slash (JS-style) CODEX triggers", () => {
1616
const content = `
1717
function testFunction() {
1818
// This is a normal comment
19-
// Fix this bug, AI!
19+
// CODEX: Fix this bug
2020
return 1 + 1;
2121
}
2222
`;
2323

2424
const matches = findAllTriggers(content);
2525

2626
expect(matches.length).toBe(1);
27-
expect(matches[0]![0]).toContain("Fix this bug, AI!");
27+
expect(matches[0]![0]).toContain("// CODEX: Fix this bug");
2828
expect(matches[0]![1]).toBe("Fix this bug");
2929
});
3030

31-
it("should detect hash (Python/Ruby-style) AI triggers", () => {
31+
it("should detect CODEX triggers with different indentation", () => {
3232
const content = `
3333
def test_function():
3434
# This is a normal comment
35-
# What does this function do, AI?
35+
// CODEX: What does this function do
3636
return 1 + 1
3737
`;
3838

3939
const matches = findAllTriggers(content);
4040

4141
expect(matches.length).toBe(1);
42-
expect(matches[0]![0]).toContain("# What does this function do, AI?");
42+
expect(matches[0]![0]).toContain("// CODEX: What does this function do");
4343
expect(matches[0]![1]).toBe("What does this function do");
4444
});
4545

4646

47-
it("should detect multiple AI triggers in a single file", () => {
47+
it("should detect multiple CODEX triggers in a single file", () => {
4848
const content = `
4949
function testFunction() {
50-
// Fix this bug, AI!
50+
// CODEX: Fix this bug
5151
return 1 + 1;
5252
}
5353
5454
function anotherFunction() {
55-
# What does this function do, AI?
55+
// CODEX: What does this function do
5656
return 2 + 2;
5757
}
5858
5959
function thirdFunction() {
60-
-- Optimize this algorithm, AI!
60+
// CODEX: Optimize this algorithm
6161
return 3 + 3;
6262
}
6363
`;
@@ -70,24 +70,24 @@ describe("Watch mode trigger pattern matching", () => {
7070
expect(matches[2]![1]).toBe("Optimize this algorithm");
7171
});
7272

73-
it("should handle AI! pattern with question mark", () => {
73+
it("should handle CODEX pattern with question", () => {
7474
const content = `
7575
function testFunction() {
76-
// What's going on here, AI?
76+
// CODEX: What's going on here?
7777
return 1 + 1;
7878
}
7979
`;
8080

8181
const matches = findAllTriggers(content);
8282

8383
expect(matches.length).toBe(1);
84-
expect(matches[0]![1]).toBe("What's going on here");
84+
expect(matches[0]![1]).toBe("What's going on here?");
8585
});
8686

87-
it("should handle AI! pattern with exclamation mark", () => {
87+
it("should handle CODEX pattern with imperative", () => {
8888
const content = `
8989
function testFunction() {
90-
// Fix this, AI!
90+
// CODEX: Fix this
9191
return 1 + 1;
9292
}
9393
`;
@@ -98,12 +98,12 @@ describe("Watch mode trigger pattern matching", () => {
9898
expect(matches[0]![1]).toBe("Fix this");
9999
});
100100

101-
it("should ignore non-AI comments", () => {
101+
it("should ignore non-CODEX comments", () => {
102102
const content = `
103103
function testFunction() {
104104
// This is a normal comment
105-
// AI is an interesting topic
106-
// This uses an AI model
105+
// CODEX is a great tool
106+
// This uses a CODEX model
107107
return 1 + 1;
108108
}
109109
`;
@@ -113,19 +113,18 @@ describe("Watch mode trigger pattern matching", () => {
113113
expect(matches.length).toBe(0);
114114
});
115115

116-
it("should detect SQL-style (--) AI triggers", () => {
116+
it("should not detect SQL-style (--) comments with the new pattern", () => {
117117
const content = `
118118
SELECT * FROM users
119119
-- This is a normal comment
120-
-- Optimize this query, AI!
120+
-- CODEX: Optimize this query
121121
WHERE age > 18;
122122
`;
123123

124124
const matches = findAllTriggers(content);
125125

126-
expect(matches.length).toBe(1);
127-
expect(matches[0]![0]).toContain("-- Optimize this query, AI!");
128-
expect(matches[0]![1]).toBe("Optimize this query");
126+
// Should not match because the pattern only looks for // CODEX:
127+
expect(matches.length).toBe(0);
129128
});
130129

131130

@@ -163,7 +162,7 @@ describe("Watch mode trigger pattern matching", () => {
163162
});
164163
});
165164

166-
describe("Context extraction around AI triggers", () => {
165+
describe("Context extraction around CODEX triggers", () => {
167166
it("should extract the correct context around a trigger in the middle of the file", () => {
168167
const content = `// File header
169168
import { useState } from 'react';
@@ -173,7 +172,7 @@ function Counter() {
173172
// State initialization
174173
const [count, setCount] = useState(0);
175174
176-
// Fix this increment function, AI!
175+
// CODEX: Fix this increment function
177176
const increment = () => {
178177
setCount(count); // Bug: doesn't increment
179178
};
@@ -206,7 +205,7 @@ export default Counter;`;
206205

207206
// Should include appropriate context around the trigger (the entire file in this case)
208207
// Use includes instead of exact equality to handle whitespace differences
209-
expect(context).toContain("// Fix this increment function, AI!");
208+
expect(context).toContain("// CODEX: Fix this increment function");
210209

211210
// Should extract the instruction correctly
212211
expect(instruction).toBe("Fix this increment function");
@@ -217,7 +216,7 @@ export default Counter;`;
217216
const fileLines = Array.from({ length: 100 }, (_, i) => `// Line ${i + 1}`);
218217

219218
// Insert the trigger at line 50
220-
fileLines[49] = "// Optimize this code, AI!";
219+
fileLines[49] = "// CODEX: Optimize this code";
221220

222221
const content = fileLines.join("\n");
223222
const matches = findAllTriggers(content);
@@ -234,14 +233,14 @@ export default Counter;`;
234233
expect(contextLines.length).toBeGreaterThanOrEqual(41); // At least the trigger line + 20 before + 20 after
235234

236235
// Should include the trigger line
237-
expect(context).toContain("// Optimize this code, AI!");
236+
expect(context).toContain("// CODEX: Optimize this code");
238237

239238
// Should extract the instruction correctly
240239
expect(instruction).toBe("Optimize this code");
241240
});
242241

243242
it("should handle triggers at the beginning of the file", () => {
244-
const content = `// Explain this code, AI!
243+
const content = `// CODEX: Explain this code
245244
function complexFunction() {
246245
return [1, 2, 3].map(x => x * 2).reduce((a, b) => a + b, 0);
247246
}`;
@@ -265,7 +264,7 @@ function complexFunction() {
265264
const content = `function complexFunction() {
266265
return [1, 2, 3].map(x => x * 2).reduce((a, b) => a + b, 0);
267266
}
268-
// Explain this code, AI!`;
267+
// CODEX: Explain this code`;
269268

270269
const matches = findAllTriggers(content);
271270

0 commit comments

Comments
 (0)