@@ -7,10 +7,12 @@ import type { OpencodeClient } from "../types/OpencodeClient"
77import type { Todo } from "../types/Todo"
88
99/**
10- * Regular expression pattern for Jira ticket references.
11- * Matches patterns like "PROJ-123", "ABC-1", "FEATURE-9999".
10+ * Default regular expression pattern for Jira ticket references.
11+ * Requires at least 2 uppercase letters followed by a dash and digits.
12+ * Matches patterns like "PROJ-123", "AB-1", "FEATURE-9999".
13+ * Does not match single-letter prefixes like "V-1" or "X-99".
1214 */
13- const TICKET_PATTERN = / ( [ A - Z ] + - \d + ) /
15+ const DEFAULT_TICKET_PATTERN = / \b ( [ A - Z ] { 2 , } - \d + ) \b /
1416
1517/**
1618 * Extracts Jira ticket references from user messages and todos.
@@ -22,18 +24,43 @@ const TICKET_PATTERN = /([A-Z]+-\d+)/
2224 *
2325 * Returns the first match found, allowing tickets to be updated
2426 * when mentioned in later messages.
27+ *
28+ * If `validProjects` is provided, only tickets from those projects
29+ * are recognized. Otherwise, any ticket matching the default pattern
30+ * (2+ uppercase letters) is accepted.
2531 */
2632export class TicketExtractor {
2733 /** OpenCode SDK client */
2834 private client : OpencodeClient
2935
36+ /** Compiled regex pattern for ticket matching */
37+ private ticketPattern : RegExp
38+
3039 /**
3140 * Creates a new ticket extractor instance.
3241 *
3342 * @param client - The OpenCode SDK client
43+ * @param validProjects - Optional whitelist of valid JIRA project keys
44+ *
45+ * @example
46+ * ```typescript
47+ * // Accept any ticket with 2+ letter prefix
48+ * const extractor = new TicketExtractor(client)
49+ *
50+ * // Only accept PROJ and SOSO tickets
51+ * const extractor = new TicketExtractor(client, ["PROJ", "SOSO"])
52+ * ```
3453 */
35- constructor ( client : OpencodeClient ) {
54+ constructor ( client : OpencodeClient , validProjects ?: string [ ] ) {
3655 this . client = client
56+
57+ if ( validProjects && validProjects . length > 0 ) {
58+ // Build pattern that only matches specified projects
59+ const projectsRegex = validProjects . join ( "|" )
60+ this . ticketPattern = new RegExp ( `\\b((?:${ projectsRegex } )-\\d+)\\b` )
61+ } else {
62+ this . ticketPattern = DEFAULT_TICKET_PATTERN
63+ }
3764 }
3865
3966 /**
@@ -149,7 +176,7 @@ export class TicketExtractor {
149176 * @returns The first ticket match, or `null` if not found
150177 */
151178 private extractFromText ( text : string ) : string | null {
152- const match = text . match ( TICKET_PATTERN )
179+ const match = text . match ( this . ticketPattern )
153180
154181 return match ?. [ 1 ] ?? null
155182 }
0 commit comments