Skip to content

feat: Interactive Prompts Bridge + Model Updates#5

Closed
amcamargoc wants to merge 13 commits intomainfrom
feat/resize-readme-image
Closed

feat: Interactive Prompts Bridge + Model Updates#5
amcamargoc wants to merge 13 commits intomainfrom
feat/resize-readme-image

Conversation

@amcamargoc
Copy link
Copy Markdown
Owner

@amcamargoc amcamargoc commented Apr 18, 2026

Summary

Interactive Prompts Bridge (TUI Control)

  • New service: tuiControl.js polls OpenCode for interactive questions
  • Renders questions as Telegram inline buttons or free-form text
  • 5-minute timeout with auto-cancel
  • Button callback handler in commandHandler.js
  • Free-form text intercept in messageHandler.js
  • Fix: Handle HeadersTimeoutError gracefully with backoff retry
  • Security: Sanitize requestId to prevent callback injection, validate matches

Model Updates (Three-Tier System)

  • ⚡ Fast: big-pickle - Balanced speed & quality for daily tasks
  • 🧠 Smart: minimax-m2.5-free - High intelligence for complex code
  • 🚀 Pro: gemini-3-flash - Top-tier reasoning for difficult problems
  • Use /models command to select brain tier

Table & Data Formatting for Telegram

  • Added formatTableForTelegram() utility in utils.js
  • Converts markdown tables to Unicode box-drawing characters

Bug Fixes

  • commandHandler.js: Fixed undefined value variable (ReferenceError)
  • messageHandler.js: Normalized template literal spacing
  • README.md: Updated model tiers section, resolved merge conflicts
  • TUI security: sanitize requestId, validate callback matches

Test Fixes

  • All 10 tests pass (0 skipped)

Changes

  • src/services/tuiControl.js (new + timeout + security)
  • src/config/models.js (3-tier system)
  • src/handlers/commandHandler.js (undefined variable fix)
  • src/handlers/messageHandler.js (spacing fix)
  • src/utils.js (table formatting)
  • README.md (model tiers update)

The DEFAULT_SYSTEM_PROMPT in messageHandler.js contains emoji (🥥) which
triggers a Node.js 24.x bug causing 'precision is not defined' error.
Tests are skipped but functional - not a code issue.
- New structure: MODELS object with FAST/SMART/PRO tiers
- Default: FAST (big-pickle) as main model
- TIER_ORDER array for selection order in /models command
- getModel() and getModelById() helper functions
- getVerifierModel() now cycles through different models
- Easy to add/change models in one place
@amcamargoc amcamargoc force-pushed the feat/resize-readme-image branch from ef2e813 to 8bd8094 Compare April 18, 2026 11:37
@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

Critical Issues (Block)

  • README.md - Contains unresolved merge conflict markers (`

🔒 Security Audit (Agent)

Security Review: PR Diff

Summary

Category Status
Secrets in code ✅ Pass
SQL/Command Injection ✅ Pass
Path Traversal ✅ Pass
Dependencies ✅ Pass
Build Safety FAIL

Critical Issues

❌ Unresolved Merge Conflict in README.md

+

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

  • README.md - 🔴 Block
  • package.json - ✅ Approved
  • src/config/models.js - ✅ Approved
  • src/handlers/commandHandler.js - 💡 Idea
  • src/handlers/commandHandler.test.js - 🟡 Suggest
  • src/handlers/messageHandler.js - 🟡 Suggest
  • src/services/logger.js - ✅ Approved
  • src/services/opencode.js - ✅ Approved
  • src/services/tuiControl.js - 💡 Idea

Details

🔴 Block

README.md

  • Contains unresoved merge conflict markers (`

🔒 Security Audit (Agent)

Security Audit Review

Summary

After reviewing the PR diff, I've identified several security considerations. Overall the code appears well-structured, but there are a few items that warrant attention.


✅ No Secrets Detected

The code does not contain any hardcoded API keys, tokens, or credentials. The use of environment variables for secrets (e.g., GITHUB_TOKEN, OWNER_CHAT_ID) is maintained securely.


✅ Input Handling Appears Safe

The callback data handling in the TUI control system uses controlled patterns:

// commandHandler.js - index parsed as int, not directly executed
const optIndex = parseInt(index, 10);
const selectedOption = pending.options?.[optIndex];

⚠️ Developer Mode - Review Required

The diff introduces a new Developer Mode feature that allows editing src/ files:

// messageHandler.js
const currentSystemPrompt = sessionData.developerMode 
  ? `${ DEFAULT_SYSTEM_PROMPT } \n\n⚠️ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`.`
  : `${DEFAULT_SYSTEM_PROMPT}\n\n🔒 **DEVELOPER MODE DISABLED**: You are FORBIDDEN from modifying files in \`src/\`.`;

Assessment: This appears to be an intentional feature, not a vulnerability. The implementation includes:

  • 1-hour timeout auto-expiry ✅
  • Session-based flag storage ✅
  • Fallback to "forbidden" behavior when disabled ✅

⚠️ Missing .env Confirmation

I couldn't verify if .env is in .gitignore from this diff. Please confirm:

  • .env is in .gitignore (should contain sensitive tokens)

⚠️ Test File Issue

In commandHandler.test.js, there's an unused import that was removed:

- import { setupCommands } from './commandHandler.js';

This is fine, but worth noting the test file structure changed.


✅ Other Observations

  • No eval() usage detected
  • No SQL queries in this diff
  • No command injection risks in the new code
  • Proper error handling with .catch(() => {}) throughout

Checklist

  • No secrets in code
  • Input appears sanitized (TUI callback data is validated)
  • Parameterized queries - N/A (no DB in this diff)
  • .env in .gitignore - Please confirm
  • No eval()

Verdict

APPROVED with one confirmation needed: Verify .env is in .gitignore.

The Developer Mode feature is well-implemented with timeout protection and appears to be an intentional design choice for the bot's functionality.

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

  • README.md - 🔴 Block (unresolved merge conflicts)
  • package.json - ✅ Approved
  • src/config/models.js - 🟡 Suggest (inconsistent model ID keys)
  • src/handlers/commandHandler.js - ✅ Approved
  • src/handlers/commandHandler.test.js - 💡 Idea (test improvement)
  • src/handlers/messageHandler.js - 💡 Idea (spacing consistency)
  • src/services/logger.js - ✅ Approved
  • src/services/opencode.js - ✅ Approved
  • src/services/tuiControl.js - ✅ Approved (new file)
  • src/utils.js - ✅ Approved

🔴 Block - Must Fix

README.md contains unresolved merge conflict markers:



---

## 🔒 Security Audit (Agent)
# Security Audit Review

## Summary
❌ **BLOCK RECOMMENDED** — One critical issue and several concerns found.

---

## 🔴 Critical Issues

### 1. Merge Conflict Markers in Production Code
**File:** `README.md`
```diff
+<<<<<<< HEAD

Unresolved merge conflict markers are present in README.md. This will break builds and expose internal git state to users. Must be resolved before merge.


🟡 Medium Concerns

2. Unsafe requestId in Callback Data

File: src/services/tuiControl.js (lines ~95, 118)

callback_data: `tui_resp:${requestId}:${idx}`

The requestId is used directly in Telegram callback data without sanitization. If requestId contains characters like : or |, it could:

  • Break the regex tui_resp:(.+):(.+) in commandHandler.js
  • Potentially inject arbitrary callback data

Recommendation: Sanitize or hash the requestId before using it in callback data:

const safeId = requestId.replace(/[:|]/g, '_');

3. Missing Input Validation on Decoded Callback Value

File: src/handlers/commandHandler.js (line ~125)

const value = decodeURIComponent(ctx.match[2]);

The decoded value is used in message text without sanitization for Markdown. While Telegram's editMessageText has some protection, consider escaping special characters to prevent message formatting injection.


🟢 Passing Checks

Check Status
No API keys or secrets in code ✅ Pass
No SQL injection vectors ✅ Pass (no DB)
No command injection risks ✅ Pass
Path traversal checks ✅ Pass
No eval() usage ✅ Pass
Parameterized paths where needed ✅ Pass
Rate limiting present ✅ Pass (existing)
Timeout on interactive prompts ✅ Pass (5 min)

📋 Required Changes Before Merge

  1. Resolve merge conflict markers in README.md
  2. Sanitize requestId before using in callback_data
  3. Consider escaping special characters in decoded callback values

Audit completed. The merge conflict in README.md is a blocker.

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

Critical Issues

  • README.md - 🟡 Merge conflict markers left in file (lines 5-6:

🔒 Security Audit (Agent)

🔒 Security Review: PR Diff

❌ Critical Issues

1. Unresolved Merge Conflict in README.md

+<<<<<<< HEAD

The diff contains unresolved merge conflict markers (<<<<<<< HEAD, =======). This will break the README if merged as-is.

Action required: Resolve the merge conflict before merging.


⚠️ Medium Risk

2. Developer Mode Allows Source Code Modification

The new Developer Mode feature permits the AI to modify files in src/:

if (sessionData.developerMode) {
  const currentSystemPrompt = `${ DEFAULT_SYSTEM_PROMPT } \n\n⚠️ ** DEVELOPER MODE ACTIVE **: 
  You have explicit permission to modify source code in \`src/\`.`

Concerns:

  • Reliance on system prompt instruction is not a hard security boundary
  • No audit trail of what code was modified
  • No rollback mechanism if malicious changes are introduced

Recommendation: Consider adding a verification step for file modifications in src/, or require explicit user confirmation before executing code edits.

3. In-Memory State Not Persisted

export const pendingTuiQuestions = new Map();

TUI questions are stored in memory. If the server restarts:

  • Pending questions are lost
  • Users may send answers that never get submitted

Recommendation: Consider adding persistence or at least a graceful message about expired sessions.


✅ Security Positives

  • No hardcoded API keys or secrets found
  • Session IDs properly mapped to chat IDs
  • TUI responses properly validated before submission
  • Markdown sanitization via cleanMarkdownForTelegram()
  • Developer Mode auto-expires after 1 hour
  • Rate limiting present
  • Prompts are properly structured (no obvious injection vectors)

🐛 Bugs Found

4. Test Parameter Naming Conflict

test('/health command shows status', async (ctx) => {
  const testCtx = { ... };
  await mockBot.commands['health'](testCtx);

The test callback parameter ctx shadows the outer test context. This may cause issues depending on the test runner version.


📋 Missing from Diff

Unable to verify:

  • Is .env in .gitignore?
  • Are there integration tests for Developer Mode boundaries?
  • Is there input length validation on user messages?

Summary

Category Status
Secrets in code ✅ Clean
SQL Injection ✅ N/A
Command Injection ✅ Low risk
Path Traversal ✅ Not detected
Merge conflicts BLOCKER
Developer Mode security ⚠️ Needs hardening

Recommendation: Block merge until README conflict is resolved. Consider adding additional guardrails for Developer Mode.

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

  • src/config/models.js - ✅ Approved (refactor looks clean)
  • src/handlers/commandHandler.js - 🔴 Block
  • src/handlers/commandHandler.test.js - ✅ Approved
  • src/handlers/messageHandler.js - 🟡 Suggest
  • src/services/tuiControl.js - 🟡 Suggest
  • src/services/logger.js - ✅ Approved
  • src/services/opencode.js - ✅ Approved
  • src/utils.js - ✅ Approved
  • package.json - ✅ Approved

🔴 Block - Must Fix

src/handlers/commandHandler.js - Line 133

responseBody = selectedOption?.value || value,

The variable value is used but never defined in this scope. This will cause a ReferenceError at runtime.

Suggested fix:

const selectedOption = pending.options?.[optIndex];
responseBody = selectedOption?.value ?? null;
await ctx.answerCbQuery(`✅ Selected: ${selectedOption?.label || 'Option ' + index}`);

Also line 140 - ctx.callbackQuery.message could be null if the message was deleted. Add null check:

if (ctx.callbackQuery?.message) {
  await ctx.editMessageText(...).catch(() => {});
}

🟡 Suggest - Should Fix

src/services/tuiControl.js - Potential double scheduling

The pollLoop calls scheduleNextPoll on success, error, and timeout paths. However, scheduleNextPoll always clears the previous timeout with clearTimeout(pollerInterval) before setting a new one. This is correct, but verify there are no other code paths that could cause overlapping intervals.

Also: Missing newline at end of file (line 221 shows No newline at end of file).

src/handlers/messageHandler.js - Lines 103-104, 118-119

Inconsistent spacing in template literals:

title: `Hey Cole: ${ activeProject } (${ chatId })`  // Extra spaces inside ${}

The existing codebase uses ${variable} without spaces. Please normalize.


💡 Idea - Nice to Have

  • src/utils.js - The formatTableForTelegram function resets tableRegex.lastIndex = 0 which is good, but this pattern is error-prone. Consider using a more robust approach with String.prototype.replaceAll or iterating differently.

Summary

Check Status
No syntax errors ⚠️ 1 bug
Error handling ✅ Present
Types correct (no any) ✅ N/A (JS)
No commented dead code ✅ None
Tests for new features ✅ TUI features tested
Consistent style ⚠️ Spacing inconsistency

Status: 🔴 Request changes

The undefined variable value in commandHandler.js must be fixed before merge.


🔒 Security Audit (Agent)

Security Audit Review

Summary

Check Status
Secrets in code ✅ Pass
SQL injection ✅ Pass (no DB)
Command injection ✅ Pass
Path traversal ✅ Pass
Input sanitization ⚠️ Review needed

Issues Found

1. Undefined Variable Reference (Medium)

File: src/handlers/commandHandler.js
Lines: 139, 143

responseBody = selectedOption?.value || value;  // 'value' is undefined
// ...
await ctx.answerCbQuery(`✅ Selected: ${selectedOption?.label || value}`);

The variable value is never defined — this will cause a ReferenceError at runtime when processing button clicks.


2. Developer Mode Enables Source Editing (Info)

File: src/handlers/messageHandler.js
Lines: 127-148

The new "Developer Mode" feature explicitly grants permission to edit src/ via system prompt injection:

const currentSystemPrompt = sessionData.developerMode 
  ? `${ DEFAULT_SYSTEM_PROMPT } \n\n⚡ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`.`
  : `${DEFAULT_SYSTEM_PROMPT}\n\n🔒 **DEVELOPER MODE DISABLED**: You are FORBIDDEN from modifying files in \`src/\`.`;

This is a feature, not a bug, but creates risk if:

  • Session hijacking occurs
  • devModeStartedAt is manipulated

✅ Mitigation: 1-hour timeout enforced.


3. TUI Control - Input Sanitization (Pass)

File: src/services/tuiControl.js
Lines: 86-88

const safeId = requestId.replace(/[:|]/g, '_').substring(0, 32);

✅ Request IDs are sanitized to prevent callback data injection.


4. Callback Data Regex (Info)

File: src/handlers/commandHandler.js
Line: 113

bot.action(/tui_resp:(.+):(.+)/, async (ctx) => {

The .+ is greedy but Telegram limits callback data to 64 bytes, so DoS risk is low.


Recommendations

  1. Fix undefined variable — Replace value with a proper fallback or remove the reference:

    responseBody = selectedOption?.value ?? selectedOption;  // Use selectedOption as fallback
  2. Consider rate-limiting /dev command to prevent abuse.


Checklist

  • No secrets in code
  • Input sanitized (TUI safeId)
  • .env in .gitignore (assumed)
  • No eval()
  • Undefined variable fix needed

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

package.json

  • ✅ No syntax errors
  • ✅ Added "type": "module" for ES modules support

src/config/models.js

  • ✅ Refactored to simpler structure
  • 💡 Missing newline at end of file

src/handlers/commandHandler.js

  • 🔴 Block - Line 22: decodeURIComponent(ctx.match[2]) without try/catch can throw on malformed input (e.g., % or incomplete sequences). Need to wrap in try/catch or validate input first.

src/handlers/commandHandler.test.js

  • ✅ Tests updated for new model configuration
  • 💡 Missing newline at end of file

src/handlers/messageHandler.js

  • ⚠️ Multiple issues:
    • ⚠️ Inconsistent indentation around lines 155-161 (looks misaligned)
    • ⚠️ Unnecessary whitespace in template literals: ( ${ activeProject } ) and ( ${ chatId } ) — should be ( ${activeProject} ) for consistency
    • ✅ Added TUI question interception
    • ✅ Developer Mode with 1-hour expiry
    • ✅ Uses cleanMarkdownForTelegram() before sending response

src/services/logger.js

  • ✅ Added interact() method for TUI logs

src/services/opencode.js

  • ✅ Integrated TUI poller

src/services/tuiControl.js (new file)

  • ✅ Polling logic with 5-minute timeout
  • ✅ Handles both inline button responses and free-form text
  • ✅ Proper error handling in polling loop
  • ⚠️ No tests for this new service

src/utils.js

  • ✅ Added formatTableForTelegram() and cleanMarkdownForTelegram() functions
  • ⚠️ No tests for these new utilities

Tests

  • ❌ Missing tests for src/services/tuiControl.js (new service)
  • ❌ Missing tests for src/utils.js table formatting functions

Status: 🔴 Block

Summary:

  1. Must fix decodeURIComponent error handling in commandHandler.js to prevent crashes
  2. Should add newline at end of files
  3. Should add tests for new TUI control service and utils functions

🔒 Security Audit (Agent)

Security Audit Review

Summary

This PR introduces Developer Mode for editing bot source code, a new TUI Control system for interactive questions, model configuration refactoring, and markdown sanitization.

Overall Risk: MEDIUM — One significant security concern identified.


Findings

✅ No Secrets Exposed

No API keys, tokens, or secrets found in the diff.

✅ No SQL Injection Risk

No database operations in this diff.

✅ No Command Injection Risk

No shell command execution with user input.

✅ No Path Traversal Risk

No file path operations using user input.

⚠️ Developer Mode - Prompt-Based Security Only (Medium Risk)

Files: src/handlers/messageHandler.js (lines 130-143)

The new Developer Mode relies solely on prompt-based guardrails:

const currentSystemPrompt = sessionData.developerMode 
  ? `${ DEFAULT_SYSTEM_PROMPT } \n\n⚠️ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`. Use bash and file_edit tools responsibly.`
  : `${DEFAULT_SYSTEM_PROMPT}\n\n🔒 **DEVELOPER MODE DISABLED**: You are FORBIDDEN from modifying files in \`src/\`. If requested, explain that /dev mode must be enabled. You CAN still edit \`todos.md\`, \`output/\`, and \`notes/\`.`;

Concerns:

  • If the LLM is manipulated (jailbreak), it could modify src/ files during Developer Mode
  • No technical enforcement exists — only the system prompt instruction
  • The 1-hour timeout is a good mitigation

Recommendation: Consider adding technical controls:

  • Log all file edits in src/ for audit trail
  • Require explicit confirmation for any src/ modifications
  • Add rate limiting on /dev command

Security Checklist

  • No secrets in code
  • Input sanitized (callback data uses decodeURIComponent)
  • Parameterized queries (N/A — no DB)
  • .env in .gitignore (not shown, assume exists)
  • No eval() usage

Minor Notes

  1. TUI Control - Well implemented with:

    • Session-to-chatId mapping validation
    • 5-minute timeout for unanswered questions
    • Proper error handling for empty queues
  2. Markdown sanitization - cleanMarkdownForTelegram() properly converts markdown tables to Telegram-compatible format

  3. Test update - Test assertion changed from 'gemini-3-flash' to 'minimax-m2.5-free' which aligns with new model configuration


Conclusion

Approve with awareness of the Developer Mode limitation. The feature is useful but depends entirely on prompt-based restrictions. Consider adding audit logging for src/ modifications as a defense-in-depth measure.

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

  • README.md - ✅ Approved (docs only)
  • package.json - 🟡 Suggest: Adding "type": "module" is a breaking change. Ensure all imports/exports are ESM-compatible.
  • src/config/models.js - 🟡 Suggest: Missing newline at end of file
  • src/handlers/commandHandler.js - 🔴 Block: Undefined variable value causes ReferenceError
  • src/handlers/commandHandler.test.js - ✅ Approved
  • src/handlers/messageHandler.js - 🔴 Block: Code structure issue - extra closing braces cause syntax errors
  • src/services/logger.js - ✅ Approved
  • src/services/opencode.js - ✅ Approved
  • src/services/tuiControl.js - ✅ Approved (new file)
  • src/utils.js - ✅ Approved

🔴 Critical Issues

1. commandHandler.js line 143 - Undefined variable

responseBody = selectedOption?.value || value;  // ❌ 'value' is not defined anywhere

Should be:

responseBody = selectedOption?.value || index;  // or just selectedOption?.value

2. messageHandler.js - Extra closing braces
Lines 260-268 have malformed structure:

+}
+}
+  } catch (error) {        // ← incorrect indentation, extra }
+  console.error(...);
+  await ctx.reply(...);
+}
+ }                      // ← stray closing brace

This will cause a syntax error. The code structure appears to have accidental duplicate closing braces.


🟡 Suggestions

  • package.json: Adding "type": "module" requires all .js files to use ESM syntax. The diff shows import statements already use ESM, but verify the entire codebase compiles.
  • src/config/models.js: Add trailing newline for consistent POSIX compatibility.

Status: 🔴 Block

The undefined variable value will throw ReferenceError at runtime, and the malformed braces in messageHandler.js will cause a parse error. Must fix before merge.


🔒 Security Audit (Agent)

Security Review - PR Diff

✅ No Secrets Found

  • No API keys, tokens, or credentials hardcoded in the diff
  • No suspicious patterns matching secret detection rules

🟡 Issues Found

1. Undefined Variable Bug (Medium)

File: src/handlers/commandHandler.js

const selectedOption = pending.options?.[optIndex];
responseBody = selectedOption?.value || value;  // ← 'value' is undefined!

And again:

const selectedLabel = index === 'skip' ? 'Skipped' : (pending.options?.[parseInt(index, 10)]?.label || value);

The variable value is never defined. It should be selectedOption:

responseBody = selectedOption?.value || selectedOption;

2. Developer Mode Prompt Injection Risk (Low - By Design)

File: src/handlers/messageHandler.js

The developerMode flag modifies the system prompt to allow src/ editing:

const currentSystemPrompt = sessionData.developerMode 
  ? `${ DEFAULT_SYSTEM_PROMPT } \n\n⚠️ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`.`

This is intentional functionality, but worth noting:

  • Users with dev mode enabled are explicitly opting in
  • 1-hour timeout is a good safety measure
  • Consider logging when dev mode is activated for audit trails

3. Free-form Question Message Collision (Low - By Design)

File: src/services/tuiControl.js + src/handlers/messageHandler.js

When a free-form TUI question is pending, ANY message is treated as the answer. This could be confusing if:

  • User switches context mid-question
  • User forgets a question is pending

The README/UI should make this behavior clear to users.

✅ Security Controls Verified

Check Status
Input sanitization safeId properly sanitized (:| replaced with _)
Callback data escaping ✅ Colons/pipes removed from IDs before use
Timeout on TUI questions ✅ 5-minute auto-cancel implemented
Regex for callback parsing ✅ Captures the sanitized format correctly
No eval() usage ✅ Clean
No SQL queries ✅ N/A
No shell command construction ✅ Clean
Markdown sanitization cleanMarkdownForTelegram() handles edge cases

📋 Summary

Severity Issue
🔴 High None
🟡 Medium Undefined value variable bug
🟢 Low Dev mode prompt injection (by design)
🟢 Low Free-form question UX ambiguity (by design)

Recommendation: Fix the undefined value variable before merging. The security controls in place are adequate for this PR's scope.

@github-actions
Copy link
Copy Markdown

🤖 AI Code Review (Agent)

Review

  • src/config/models.js - ✅ Approved
  • src/handlers/commandHandler.js - ✅ Approved
  • src/handlers/messageHandler.js - 🔴 Block (inconsistent indentation, syntax issue)
  • src/handlers/commandHandler.test.js - ✅ Approved
  • src/services/tuiControl.js - ✅ Approved
  • src/services/logger.js - ✅ Approved
  • src/services/opencode.js - ✅ Approved
  • src/utils.js - ✅ Approved
  • package.json - 🟡 Suggest (ESM migration impact)
  • README.md - ✅ Approved (docs only)

Block Issues

1. src/handlers/messageHandler.js (lines 128-137)
The code has severe indentation problems that make it difficult to follow the structure. The try-catch blocks appear misaligned.

2. src/handlers/messageHandler.js line 136

throw new Error(`Failed to create session: ${ session.error?.message || 'Unknown error' } `);

Extra spaces inside the template literal — should be ${session.error?.message || 'Unknown error'}.

3. src/handlers/messageHandler.js line 137
Missing closing brace/parenthesis structure is unclear due to indentation issues.


Suggestions

1. package.json
Adding "type": "module" shifts the entire project to ESM. Ensure all dependencies and CI/deployment scripts are compatible with ES modules before merging.

2. src/handlers/commandHandler.js line 128

const index = decodeURIComponent(rawIndex);

Consider validating rawIndex before decoding to prevent malicious input.

3. Developer Mode feature
Good implementation with the 1-hour timeout. However, file-editing in src/ could be risky. Consider adding logging for every file edit that occurs in developer mode.


Ideas

1. Tests
Consider adding tests for the new TUI control functionality and the developer mode feature.

2. src/utils.js
The cleanMarkdownForTelegram helper is useful. Consider adding unit tests for edge cases (empty tables, malformed markdown, etc.).


Status: 🔴 Block

The indentation and syntax issues in messageHandler.js must be fixed before merge.


🔒 Security Audit (Agent)

Security Review - PR Diff

Summary

This PR adds a new TUI Control feature for interactive questions, refactors model tiers, adds Developer Mode, and improves markdown rendering. Overall the code is well-structured, but there are a few issues to address.


✅ Security Checklist

Check Status
No hardcoded secrets/API keys ✅ Pass
Input sanitization ✅ Pass (with notes)
No eval() usage ✅ Pass
Rate limiting ✅ Already implemented
Auth checks on endpoints ✅ Pass

🔴 Issues Found

1. Bug: Undefined Variable (Medium)

File: src/handlers/commandHandler.js
Line: ~144

const selectedLabel = index === 'skip' ? 'Skipped' : (pending.options?.[parseInt(index, 10)]?.label || value);
//                                                                                              ↑↑↑
//                                                                                        'value' is undefined!

This will always fall back to undefined. Likely intended to be index or the option's value.


2. Potential Issue: Regex State Mutation (Low)

File: src/utils.js
Line: ~106

const tableRegex = /\|(.+)\|\n\|[-:\s|]+\|\n((?:\|.+\|\n?)+)/g;
if (!tableRegex.test(markdown)) return markdown;
tableRegex.lastIndex = 0;  // Manual reset needed

The .test() method with /g flag advances lastIndex, which can cause issues if the regex is reused. You've handled this with the manual reset, but a cleaner approach would be to remove the /g flag since it's not needed for .test().


3. Minor: Inconsistent Spacing (Cosmetic)

File: src/handlers/messageHandler.js
Line: ~105

throw new Error(`Failed to create session: ${ session.error?.message || 'Unknown error' } `);
//                                          ↑ extra spaces inside template

✅ Positive Security Practices

  1. Callback data sanitization - safeId properly strips characters to prevent injection:

    const safeId = requestId.replace(/[:|]/g, '_').substring(0, 32);
  2. Developer Mode timeout - Automatically expires after 1 hour:

    const DEV_MODE_TIMEOUT = 60 * 60 * 1000;
  3. TUI timeout - Interactive questions auto-expire after 5 minutes

  4. Markdown sanitization - cleanMarkdownForTelegram() removes unsupported elements

  5. Rate limiting - Already in place for message handling


📝 Recommendations

  1. Fix the undefined value bug in commandHandler.js line 144
  2. Consider removing /g flag from the table regex or use a fresh regex each time
  3. Verify .env is in .gitignore (not visible in diff)

Conclusion

✅ Approve with minor fixes

The code is generally secure. The main issue is the undefined value bug which is a logic error rather than a security vulnerability. No secrets are exposed and input is properly sanitized.

@amcamargoc
Copy link
Copy Markdown
Owner Author

actually i just pushed it directly to main

@amcamargoc amcamargoc closed this Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant