fix: resolve typing hang, intent detector reversed .test() bugs, and 'now' false positive
- Add missing clearInterval(typingInterval) in intent bypass early return path - Fix intent-detector category detection: pattern.test(regex) → regex.test(trimmed) - Fix short-answer patterns: same reversed .test() bug - Prevent 'now' being matched as 'no' by adding \b word boundary to greeting regex - Also tighten other greeting patterns with $ anchor where appropriate
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "zcode-cli-x",
|
"name": "zcode-cli-x",
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "zcode-cli-x",
|
"name": "zcode-cli-x",
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "^0.81.0",
|
"@anthropic-ai/sdk": "^0.81.0",
|
||||||
"@grammyjs/auto-retry": "^2.0.2",
|
"@grammyjs/auto-retry": "^2.0.2",
|
||||||
@@ -31,8 +32,14 @@
|
|||||||
"bin": {
|
"bin": {
|
||||||
"zcode": "bin/zcode.js"
|
"zcode": "bin/zcode.js"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0",
|
||||||
|
"npm": ">=9.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/uroma2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@anthropic-ai/sdk": {
|
"node_modules/@anthropic-ai/sdk": {
|
||||||
|
|||||||
@@ -1256,14 +1256,14 @@ export async function initBot(config, api, tools, skills, agents) {
|
|||||||
try {
|
try {
|
||||||
// ── Intent detection: bypass AI for simple messages ──
|
// ── Intent detection: bypass AI for simple messages ──
|
||||||
const intent = detectIntent(text);
|
const intent = detectIntent(text);
|
||||||
if (intent && intent.bypassAI) {
|
if (intent && intent.bypassAI) {
|
||||||
logger.info(`🎯 Intent: ${intent.type} — bypassing AI`);
|
logger.info(`🎯 Intent: ${intent.type} — bypassing AI`);
|
||||||
const reply = intent.response || 'Got it.';
|
clearInterval(typingInterval);
|
||||||
await queueRequest(key, text, async () => {
|
const reply = intent.response || 'Got it.';
|
||||||
await sendFormatted(ctx, reply);
|
await sendFormatted(ctx, reply);
|
||||||
});
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ── Load conversation history for this chat ──
|
// ── Load conversation history for this chat ──
|
||||||
const chatKey = conversation._key(ctx.chat.id, ctx.message?.message_thread_id);
|
const chatKey = conversation._key(ctx.chat.id, ctx.message?.message_thread_id);
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ const GREETINGS = [
|
|||||||
/^(hi|hey|hello|howdy|greetings|sup|yo|what'?s up|what'?s up|how are you|how's it going|how do you do)/i,
|
/^(hi|hey|hello|howdy|greetings|sup|yo|what'?s up|what'?s up|how are you|how's it going|how do you do)/i,
|
||||||
/^(good morning|good afternoon|good evening|good night)/i,
|
/^(good morning|good afternoon|good evening|good night)/i,
|
||||||
/^(thanks|thank you|thx|ty|appreciate it)/i,
|
/^(thanks|thank you|thx|ty|appreciate it)/i,
|
||||||
/^(ok|okay|alright|sure|yes|yeah|yep|nope|no)/i,
|
/^(?:ok|okay|alright|sure|yes|yeah|yep|nope|no)\b/i,
|
||||||
/^(continue|go ahead|proceed|do it|carry on|keep going)/i,
|
/^(continue|go ahead|proceed|do it|carry on|keep going)$/i,
|
||||||
/^(done|finished|completed|all good|looks good)/i,
|
/^(done|finished|completed|all good|looks good)$/i,
|
||||||
/^(bye|goodbye|see you|later|take care)/i,
|
/^(bye|goodbye|see you|later|take care)/i,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -76,11 +76,12 @@ export function detectIntent(message) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let category = 'greeting';
|
let category = 'greeting';
|
||||||
if (pattern.test(/^(thanks|thank you|thx|ty)/i)) category = 'thanks';
|
if (/^(thanks|thank you|thx|ty|appreciate it)/i.test(trimmed)) category = 'thanks';
|
||||||
else if (pattern.test(/^(bye|goodbye|see you|later)/i)) category = 'goodbye';
|
else if (/^(bye|goodbye|see you|later|take care)/i.test(trimmed)) category = 'goodbye';
|
||||||
else if (pattern.test(/^(ok|okay|alright|sure|yes|yeah)/i)) category = 'confirmation';
|
else if (/^(ok|okay|alright|sure|yes|yeah|yep|nope|no)/i.test(trimmed)) category = 'confirmation';
|
||||||
else if (pattern.test(/^(continue|go ahead|proceed)/i)) category = 'continue';
|
else if (/^(continue|go ahead|proceed|do it|carry on|keep going)/i.test(trimmed)) category = 'continue';
|
||||||
else if (pattern.test(/^(good morning|good afternoon|good evening)/i)) category = 'greeting';
|
else if (/^(done|finished|completed|all good|looks good)/i.test(trimmed)) category = 'completion';
|
||||||
|
else if (/^(good morning|good afternoon|good evening)/i.test(trimmed)) category = 'greeting';
|
||||||
|
|
||||||
const list = responses[category] || responses['greeting'];
|
const list = responses[category] || responses['greeting'];
|
||||||
return {
|
return {
|
||||||
@@ -106,21 +107,21 @@ export function detectIntent(message) {
|
|||||||
if (pattern.test(trimmed)) {
|
if (pattern.test(trimmed)) {
|
||||||
if (type === 'instant') {
|
if (type === 'instant') {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (pattern.test(/what time/i)) {
|
if (/what time/i.test(trimmed)) {
|
||||||
return {
|
return {
|
||||||
type: 'instant',
|
type: 'instant',
|
||||||
response: `🕐 ${now.toLocaleTimeString('en-US', { timeZone: 'Asia/Tbilisi' })} (Tbilisi time)`,
|
response: `🕐 ${now.toLocaleTimeString('en-US', { timeZone: 'Asia/Tbilisi' })} (Tbilisi time)`,
|
||||||
bypassAI: true,
|
bypassAI: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (pattern.test(/what date|what day/i)) {
|
if (/(what date|what day)/i.test(trimmed)) {
|
||||||
return {
|
return {
|
||||||
type: 'instant',
|
type: 'instant',
|
||||||
response: `📅 ${now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}`,
|
response: `📅 ${now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}`,
|
||||||
bypassAI: true,
|
bypassAI: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (pattern.test(/who are you|what are you/i)) {
|
if (/(who are you|what are you)/i.test(trimmed)) {
|
||||||
return {
|
return {
|
||||||
type: 'instant',
|
type: 'instant',
|
||||||
response: '⚡ I\'m zCode CLI X — an agentic coding assistant running on Telegram. I can read/write files, run bash commands, manage git repos, search the web, and more.',
|
response: '⚡ I\'m zCode CLI X — an agentic coding assistant running on Telegram. I can read/write files, run bash commands, manage git repos, search the web, and more.',
|
||||||
|
|||||||
Reference in New Issue
Block a user