@@ -34358,6 +34358,7 @@ const core = __importStar(__nccwpck_require__(7484));
3435834358const github = __importStar(__nccwpck_require__(3228));
3435934359const fs_1 = __importDefault(__nccwpck_require__(9896));
3436034360const extractTodosFromDir_1 = __nccwpck_require__(3838);
34361+ const extractTodosWithStructuredTagsFromDir_1 = __nccwpck_require__(6728); // 👈 novo
3436134362const issueManager_1 = __nccwpck_require__(893);
3436234363const report_1 = __nccwpck_require__(8557);
3436334364const todoUtils_1 = __nccwpck_require__(2674);
@@ -34375,7 +34376,10 @@ async function run() {
3437534376 if (useLLM && !process.env.OPENAI_API_KEY) {
3437634377 core.warning('⚠️ LLM is enabled, but OPENAI_API_KEY is not set.');
3437734378 }
34378- const todos = (0, extractTodosFromDir_1.extractTodosFromDir)(workspace);
34379+ const useStructured = core.getInput('structured') === 'true';
34380+ const todos = useStructured
34381+ ? (0, extractTodosWithStructuredTagsFromDir_1.extractTodosWithStructuredTagsFromDir)(workspace)
34382+ : (0, extractTodosFromDir_1.extractTodosFromDir)(workspace);
3437934383 const octokit = github.getOctokit(token);
3438034384 const { owner, repo } = github.context.repo;
3438134385 core.info(`🔍 Found ${todos.length} TODOs`);
@@ -34741,15 +34745,50 @@ async function ensureLabelExists(octokit, owner, repo, label) {
3474134745
3474234746"use strict";
3474334747
34748+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
34749+ if (k2 === undefined) k2 = k;
34750+ var desc = Object.getOwnPropertyDescriptor(m, k);
34751+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
34752+ desc = { enumerable: true, get: function() { return m[k]; } };
34753+ }
34754+ Object.defineProperty(o, k2, desc);
34755+ }) : (function(o, m, k, k2) {
34756+ if (k2 === undefined) k2 = k;
34757+ o[k2] = m[k];
34758+ }));
34759+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34760+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34761+ }) : function(o, v) {
34762+ o["default"] = v;
34763+ });
34764+ var __importStar = (this && this.__importStar) || (function () {
34765+ var ownKeys = function(o) {
34766+ ownKeys = Object.getOwnPropertyNames || function (o) {
34767+ var ar = [];
34768+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34769+ return ar;
34770+ };
34771+ return ownKeys(o);
34772+ };
34773+ return function (mod) {
34774+ if (mod && mod.__esModule) return mod;
34775+ var result = {};
34776+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34777+ __setModuleDefault(result, mod);
34778+ return result;
34779+ };
34780+ })();
3474434781var __importDefault = (this && this.__importDefault) || function (mod) {
3474534782 return (mod && mod.__esModule) ? mod : { "default": mod };
3474634783};
3474734784Object.defineProperty(exports, "__esModule", ({ value: true }));
3474834785exports.generateIssueTitleAndBodyLLM = generateIssueTitleAndBodyLLM;
3474934786const openai_1 = __importDefault(__nccwpck_require__(2583));
34787+ const core = __importStar(__nccwpck_require__(7484));
3475034788const openai = new openai_1.default({
34751- apiKey: process.env.OPENAI_API_KEY || '', // ou core.getInput('openai-api-key')
34789+ apiKey: core.getInput('openai-api-key'), // correto agora
3475234790});
34791+ const model = core.getInput('openai-model') || 'gpt-3.5-turbo';
3475334792async function generateIssueTitleAndBodyLLM(todo) {
3475434793 const prompt = `
3475534794You are a helpful assistant converting inline TODO comments from source code into GitHub Issues.
@@ -34768,18 +34807,29 @@ TITLE: <title>
3476834807BODY:
3476934808<detailed body>
3477034809`;
34771- const response = await openai.chat.completions.create({
34772- model: 'gpt-4',
34773- messages: [{ role: 'user', content: prompt }],
34774- temperature: 0.4,
34775- });
34776- const result = response.choices[0].message?.content || '';
34777- const match = result.match(/TITLE:\s*(.+?)\s*BODY:\s*([\s\S]*)/i);
34778- if (!match) {
34779- throw new Error('Failed to parse LLM response.');
34810+ // 👇 Adiciona aqui
34811+ console.log('[DEBUG] OpenAI key starts with:', process.env.OPENAI_API_KEY?.slice(0, 5));
34812+ console.log('[DEBUG] Using model:', model);
34813+ console.log('[DEBUG] Sending prompt to OpenAI...');
34814+ try {
34815+ const response = await openai.chat.completions.create({
34816+ model,
34817+ messages: [{ role: 'user', content: prompt }],
34818+ temperature: 0.4,
34819+ });
34820+ // TODO(priority=high): improve retry logic for API errors
34821+ const result = response.choices[0].message?.content || '';
34822+ const match = result.match(/TITLE:\s*(.+?)\s*BODY:\s*([\s\S]*)/i);
34823+ if (!match) {
34824+ throw new Error('Failed to parse LLM response.');
34825+ }
34826+ const [, title, body] = match;
34827+ return { title: title.trim(), body: body.trim() };
34828+ }
34829+ catch (err) {
34830+ console.error('[ERROR] OpenAI call failed:', err);
34831+ throw err;
3478034832 }
34781- const [, title, body] = match;
34782- return { title: title.trim(), body: body.trim() };
3478334833}
3478434834
3478534835
@@ -34883,6 +34933,55 @@ function todoKey(todo) {
3488334933}
3488434934
3488534935
34936+ /***/ }),
34937+
34938+ /***/ 5748:
34939+ /***/ ((__unused_webpack_module, exports) => {
34940+
34941+ "use strict";
34942+
34943+ // src/parser/extractStructuredTags.ts
34944+ Object.defineProperty(exports, "__esModule", ({ value: true }));
34945+ exports.extractStructuredTags = extractStructuredTags;
34946+ /**
34947+ * Extracts structured tags from TODO comment text.
34948+ *
34949+ * Supports:
34950+ * - @username → assignees
34951+ * - #module → modules
34952+ * - key=value → structured metadata
34953+ *
34954+ * @param text Raw TODO text
34955+ * @returns Partial<TodoItem> with assignees, modules, and structured tags
34956+ */
34957+ function extractStructuredTags(text) {
34958+ const assignees = [];
34959+ const modules = [];
34960+ const structured = {};
34961+ const words = text.split(/\s+/);
34962+ for (const word of words) {
34963+ if (word.startsWith('@') && word.length > 1) {
34964+ assignees.push(word.slice(1));
34965+ }
34966+ else if (word.startsWith('#') && word.length > 1) {
34967+ modules.push(word.slice(1));
34968+ }
34969+ else if (/^[a-zA-Z0-9_-]+=/.test(word)) {
34970+ const [key, ...valueParts] = word.split('=');
34971+ const value = valueParts.join('=');
34972+ if (key && value) {
34973+ structured[key] = value.replace(/^['"]|['"]$/g, ''); // strip quotes
34974+ }
34975+ }
34976+ }
34977+ return {
34978+ assignees: assignees.length ? assignees : undefined,
34979+ modules: modules.length ? modules : undefined,
34980+ structured: Object.keys(structured).length ? structured : undefined,
34981+ };
34982+ }
34983+
34984+
3488634985/***/ }),
3488734986
3488834987/***/ 2001:
@@ -34945,6 +35044,62 @@ function extractTodosFromFile(filePath) {
3494535044}
3494635045
3494735046
35047+ /***/ }),
35048+
35049+ /***/ 412:
35050+ /***/ ((__unused_webpack_module, exports) => {
35051+
35052+ "use strict";
35053+
35054+ Object.defineProperty(exports, "__esModule", ({ value: true }));
35055+ exports.extractTodosFromString = extractTodosFromString;
35056+ const COMMENT_PATTERNS = [
35057+ { ext: ['.ts', '.js', '.java', '.go'], pattern: /^\s*\/\/\s*(.*)$/ },
35058+ { ext: ['.py', '.sh', '.rb'], pattern: /^\s*#\s*(.*)$/ },
35059+ { ext: ['.html', '.xml'], pattern: /<!--\s*(.*?)\s*-->/ }
35060+ ];
35061+ const TAG_REGEX = /(TODO|FIXME|BUG|HACK)(\([^)]*\))?:?\s*(.*)/i;
35062+ function extractMetadata(str) {
35063+ const meta = {};
35064+ const match = str.match(/\((.*?)\)/);
35065+ if (match) {
35066+ const content = match[1];
35067+ content.split(',').forEach(pair => {
35068+ const [key, val] = pair.split('=').map(s => s.trim());
35069+ if (key && val)
35070+ meta[key] = val;
35071+ });
35072+ }
35073+ return meta;
35074+ }
35075+ function extractTodosFromString(content, ext) {
35076+ const pattern = COMMENT_PATTERNS.find(p => p.ext.includes(ext));
35077+ if (!pattern)
35078+ return [];
35079+ const lines = content.split('\n');
35080+ const todos = [];
35081+ lines.forEach((line, idx) => {
35082+ const commentMatch = line.match(pattern.pattern);
35083+ if (commentMatch) {
35084+ const comment = commentMatch[1];
35085+ const tagMatch = comment.match(TAG_REGEX);
35086+ if (tagMatch) {
35087+ const [_, tag, metaRaw, text] = tagMatch;
35088+ const metadata = metaRaw ? extractMetadata(metaRaw) : undefined;
35089+ todos.push({
35090+ file: `inline${ext}`,
35091+ line: idx + 1,
35092+ tag,
35093+ text: text.trim(),
35094+ metadata
35095+ });
35096+ }
35097+ }
35098+ });
35099+ return todos;
35100+ }
35101+
35102+
3494835103/***/ }),
3494935104
3495035105/***/ 3838:
@@ -34984,6 +35139,79 @@ function extractTodosFromDir(dirPath) {
3498435139}
3498535140
3498635141
35142+ /***/ }),
35143+
35144+ /***/ 903:
35145+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
35146+
35147+ "use strict";
35148+
35149+ var __importDefault = (this && this.__importDefault) || function (mod) {
35150+ return (mod && mod.__esModule) ? mod : { "default": mod };
35151+ };
35152+ Object.defineProperty(exports, "__esModule", ({ value: true }));
35153+ exports.extractTodosWithStructuredTags = extractTodosWithStructuredTags;
35154+ const extractTodosFromContent_1 = __nccwpck_require__(412);
35155+ const extractStructuredTags_1 = __nccwpck_require__(5748);
35156+ const fs_1 = __importDefault(__nccwpck_require__(9896));
35157+ function extractTodosWithStructuredTags(filePath) {
35158+ const ext = filePath.slice(filePath.lastIndexOf('.'));
35159+ const content = fs_1.default.readFileSync(filePath, 'utf8');
35160+ const todos = (0, extractTodosFromContent_1.extractTodosFromString)(content, ext);
35161+ return todos.map(todo => {
35162+ const structured = (0, extractStructuredTags_1.extractStructuredTags)(todo.text);
35163+ return {
35164+ ...todo,
35165+ metadata: {
35166+ ...(todo.metadata || {}),
35167+ ...Object.fromEntries(Object.entries(structured).map(([key, value]) => [key, String(value)])),
35168+ },
35169+ };
35170+ });
35171+ }
35172+
35173+
35174+ /***/ }),
35175+
35176+ /***/ 6728:
35177+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
35178+
35179+ "use strict";
35180+
35181+ var __importDefault = (this && this.__importDefault) || function (mod) {
35182+ return (mod && mod.__esModule) ? mod : { "default": mod };
35183+ };
35184+ Object.defineProperty(exports, "__esModule", ({ value: true }));
35185+ exports.extractTodosWithStructuredTagsFromDir = extractTodosWithStructuredTagsFromDir;
35186+ // src/parser/extractTodosWithStructuredTagsFromDir.ts
35187+ const path_1 = __importDefault(__nccwpck_require__(6928));
35188+ const fs_1 = __importDefault(__nccwpck_require__(9896));
35189+ const extractTodosWithStructuredTags_1 = __nccwpck_require__(903);
35190+ function extractTodosWithStructuredTagsFromDir(dir) {
35191+ const todos = [];
35192+ function walk(currentPath) {
35193+ const entries = fs_1.default.readdirSync(currentPath, { withFileTypes: true });
35194+ for (const entry of entries) {
35195+ const fullPath = path_1.default.join(currentPath, entry.name);
35196+ if (entry.isDirectory()) {
35197+ walk(fullPath);
35198+ }
35199+ else if (entry.isFile()) {
35200+ try {
35201+ const fileTodos = (0, extractTodosWithStructuredTags_1.extractTodosWithStructuredTags)(fullPath);
35202+ todos.push(...fileTodos);
35203+ }
35204+ catch {
35205+ // opcional: log de ficheiros ignorados
35206+ }
35207+ }
35208+ }
35209+ }
35210+ walk(dir);
35211+ return todos;
35212+ }
35213+
35214+
3498735215/***/ }),
3498835216
3498935217/***/ 450:
0 commit comments