@inetafrica/open-claudia 1.14.2 → 1.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bot-agent.js +61 -20
- package/bot.js +61 -20
- package/package.json +1 -1
package/bot-agent.js
CHANGED
|
@@ -724,6 +724,25 @@ function looksLikeClaudeToken(value) {
|
|
|
724
724
|
return /^sk-ant-[A-Za-z0-9._-]+$/.test(text) || text.length >= 80 && /^[A-Za-z0-9._=-]+$/.test(text);
|
|
725
725
|
}
|
|
726
726
|
|
|
727
|
+
|
|
728
|
+
function looksLikeClaudeAuthReply(value) {
|
|
729
|
+
const text = String(value || "").trim();
|
|
730
|
+
if (!text) return false;
|
|
731
|
+
if (looksLikeClaudeToken(text)) return true;
|
|
732
|
+
if (/^https?:\/\//i.test(text) && /claude|anthropic/i.test(text)) return true;
|
|
733
|
+
// OAuth callback/login codes are usually long, dense strings. Do not consume normal chat.
|
|
734
|
+
if (text.length >= 24 && !/\s/.test(text) && /^[A-Za-z0-9._~:/?#[\]@!$&'()*+,;=%-]+$/.test(text)) return true;
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function clearPendingClaudeAuth() {
|
|
739
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthProcess.kill) {
|
|
740
|
+
try { pendingClaudeAuthProcess.kill("SIGTERM"); } catch (e) {}
|
|
741
|
+
}
|
|
742
|
+
pendingClaudeAuthProcess = null;
|
|
743
|
+
pendingClaudeAuthLabel = null;
|
|
744
|
+
}
|
|
745
|
+
|
|
727
746
|
function getClaudeOAuthToken() {
|
|
728
747
|
if (config[CLAUDE_OAUTH_TOKEN_KEY]) return { value: config[CLAUDE_OAUTH_TOKEN_KEY], source: ".env" };
|
|
729
748
|
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) return { value: process.env.CLAUDE_CODE_OAUTH_TOKEN, source: "process env" };
|
|
@@ -1452,7 +1471,7 @@ bot.onText(/\/upgrade$/, async (msg) => {
|
|
|
1452
1471
|
await send("Upgrading...");
|
|
1453
1472
|
}
|
|
1454
1473
|
try {
|
|
1455
|
-
execSync(
|
|
1474
|
+
execSync(`npm install -g @inetafrica/open-claudia@${latest} 2>&1`, {
|
|
1456
1475
|
encoding: "utf-8", timeout: 120000,
|
|
1457
1476
|
cwd: process.env.HOME || require("os").homedir(),
|
|
1458
1477
|
env: { ...process.env, PATH: FULL_PATH, HOME: process.env.HOME || require("os").homedir() },
|
|
@@ -1463,8 +1482,9 @@ bot.onText(/\/upgrade$/, async (msg) => {
|
|
|
1463
1482
|
let whatsNew = "";
|
|
1464
1483
|
try {
|
|
1465
1484
|
const changelog = fs.readFileSync(path.join(root, "@inetafrica", "open-claudia", "CHANGELOG.md"), "utf-8");
|
|
1466
|
-
|
|
1467
|
-
|
|
1485
|
+
let versionHeader = `## v${newPkg.version}`;
|
|
1486
|
+
let start = changelog.indexOf(versionHeader);
|
|
1487
|
+
if (start < 0) { versionHeader = `## ${newPkg.version}`; start = changelog.indexOf(versionHeader); }
|
|
1468
1488
|
if (start >= 0) {
|
|
1469
1489
|
const afterHeader = changelog.slice(start + versionHeader.length);
|
|
1470
1490
|
const nextVersion = afterHeader.indexOf("\n## ");
|
|
@@ -1691,6 +1711,32 @@ bot.onText(/\/(?:auth_status|auth status)$/, async (msg) => {
|
|
|
1691
1711
|
proc.on("error", async (err) => send(`Claude auth status failed: ${redactSensitive(err.message)}`));
|
|
1692
1712
|
});
|
|
1693
1713
|
|
|
1714
|
+
bot.onText(/\/cancel_auth$/, async (msg) => {
|
|
1715
|
+
if (!isAuthorized(msg)) return;
|
|
1716
|
+
if (!pendingClaudeAuthProcess) return send("No Claude auth flow is pending.");
|
|
1717
|
+
clearPendingClaudeAuth();
|
|
1718
|
+
await send("Claude auth flow cancelled. Normal messages will go to the assistant again.");
|
|
1719
|
+
});
|
|
1720
|
+
|
|
1721
|
+
bot.onText(/\/auth_code(?:\s+(.+))?$/, async (msg, match) => {
|
|
1722
|
+
if (!isAuthorized(msg)) return;
|
|
1723
|
+
const code = (match[1] || "").trim();
|
|
1724
|
+
await deleteMessage(msg.message_id);
|
|
1725
|
+
if (!pendingClaudeAuthProcess || pendingClaudeAuthLabel === "manual OAuth token save") {
|
|
1726
|
+
return send("No Claude login flow is waiting for an auth code. Start with /login, or use /use_oauth_token for tokens.");
|
|
1727
|
+
}
|
|
1728
|
+
if (!code || !looksLikeClaudeAuthReply(code)) {
|
|
1729
|
+
return send("That does not look like a Claude auth code/callback. Use /cancel_auth to cancel the login flow.");
|
|
1730
|
+
}
|
|
1731
|
+
try {
|
|
1732
|
+
pendingClaudeAuthProcess.stdin.write(code + "\n");
|
|
1733
|
+
await send("Auth code sent to Claude. I’ll confirm with auth status when Claude finishes.");
|
|
1734
|
+
} catch (e) {
|
|
1735
|
+
clearPendingClaudeAuth();
|
|
1736
|
+
await send(`Could not send auth code to Claude: ${redactSensitive(e.message)}`);
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1694
1740
|
bot.onText(/\/login$/, async (msg) => {
|
|
1695
1741
|
if (!isAuthorized(msg)) return;
|
|
1696
1742
|
await runClaudeAuthCommand(["auth", "login", "--claudeai", "--email", "sumeet@inet.africa"], "Claude login");
|
|
@@ -1959,28 +2005,23 @@ bot.on("message", async (msg) => {
|
|
|
1959
2005
|
if (msg.voice || msg.audio || msg.photo || msg.document || msg.video || msg.sticker) return;
|
|
1960
2006
|
if (isDuplicate(msg.message_id)) return;
|
|
1961
2007
|
|
|
1962
|
-
// Handle pending
|
|
1963
|
-
|
|
2008
|
+
// Handle pending manual OAuth token paste mode. Login codes must be sent explicitly
|
|
2009
|
+
// with /auth_code so normal chat can never be deleted/consumed accidentally.
|
|
2010
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthLabel === "manual OAuth token save") {
|
|
1964
2011
|
const text = msg.text.trim();
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
pendingClaudeAuthLabel = null;
|
|
1969
|
-
if (!looksLikeClaudeToken(text)) { await send("That doesn't look like a Claude OAuth token. Not saved."); return; }
|
|
2012
|
+
if (looksLikeClaudeToken(text)) {
|
|
2013
|
+
await deleteMessage(msg.message_id);
|
|
2014
|
+
clearPendingClaudeAuth();
|
|
1970
2015
|
saveClaudeOAuthToken(text);
|
|
1971
2016
|
await send(`Claude OAuth token stored in .env${vault.isUnlocked() ? " and vault" : ""}. Restart the bot so launchd picks it up, or use /restart.`);
|
|
1972
|
-
|
|
2017
|
+
await sendClaudeAuthStatusSummary("Stored token. Current Claude auth status:");
|
|
1973
2018
|
return;
|
|
1974
2019
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
pendingClaudeAuthLabel = null;
|
|
1981
|
-
await send(`Could not send to Claude auth process: ${redactSensitive(e.message)}`);
|
|
1982
|
-
}
|
|
1983
|
-
return;
|
|
2020
|
+
await send("Token paste mode is active, but that does not look like a Claude OAuth token. I left your message visible and will handle it normally. Send /cancel_auth to stop token paste mode.");
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthLabel !== "manual OAuth token save") {
|
|
2024
|
+
await send("Claude login is still waiting. I will not delete normal messages. If Claude gave you a code, send it as `/auth_code YOUR_CODE`, or use /cancel_auth.");
|
|
1984
2025
|
}
|
|
1985
2026
|
|
|
1986
2027
|
// Handle onboarding
|
package/bot.js
CHANGED
|
@@ -786,6 +786,25 @@ function looksLikeClaudeToken(value) {
|
|
|
786
786
|
return /^sk-ant-[A-Za-z0-9._-]+$/.test(text) || text.length >= 80 && /^[A-Za-z0-9._=-]+$/.test(text);
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
+
|
|
790
|
+
function looksLikeClaudeAuthReply(value) {
|
|
791
|
+
const text = String(value || "").trim();
|
|
792
|
+
if (!text) return false;
|
|
793
|
+
if (looksLikeClaudeToken(text)) return true;
|
|
794
|
+
if (/^https?:\/\//i.test(text) && /claude|anthropic/i.test(text)) return true;
|
|
795
|
+
// OAuth callback/login codes are usually long, dense strings. Do not consume normal chat.
|
|
796
|
+
if (text.length >= 24 && !/\s/.test(text) && /^[A-Za-z0-9._~:/?#[\]@!$&'()*+,;=%-]+$/.test(text)) return true;
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function clearPendingClaudeAuth() {
|
|
801
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthProcess.kill) {
|
|
802
|
+
try { pendingClaudeAuthProcess.kill("SIGTERM"); } catch (e) {}
|
|
803
|
+
}
|
|
804
|
+
pendingClaudeAuthProcess = null;
|
|
805
|
+
pendingClaudeAuthLabel = null;
|
|
806
|
+
}
|
|
807
|
+
|
|
789
808
|
function getClaudeOAuthToken() {
|
|
790
809
|
if (config[CLAUDE_OAUTH_TOKEN_KEY]) return { value: config[CLAUDE_OAUTH_TOKEN_KEY], source: ".env" };
|
|
791
810
|
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) return { value: process.env.CLAUDE_CODE_OAUTH_TOKEN, source: "process env" };
|
|
@@ -1483,7 +1502,7 @@ bot.onText(/\/upgrade$/, async (msg) => {
|
|
|
1483
1502
|
await send("Upgrading...");
|
|
1484
1503
|
}
|
|
1485
1504
|
try {
|
|
1486
|
-
execSync(
|
|
1505
|
+
execSync(`npm install -g @inetafrica/open-claudia@${latest} 2>&1`, {
|
|
1487
1506
|
encoding: "utf-8", timeout: 120000,
|
|
1488
1507
|
cwd: process.env.HOME || require("os").homedir(),
|
|
1489
1508
|
env: { ...process.env, PATH: FULL_PATH, HOME: process.env.HOME || require("os").homedir() },
|
|
@@ -1500,8 +1519,9 @@ bot.onText(/\/upgrade$/, async (msg) => {
|
|
|
1500
1519
|
let whatsNew = "";
|
|
1501
1520
|
try {
|
|
1502
1521
|
const changelog = fs.readFileSync(path.join(root, "@inetafrica", "open-claudia", "CHANGELOG.md"), "utf-8");
|
|
1503
|
-
|
|
1504
|
-
|
|
1522
|
+
let versionHeader = `## v${newPkg.version}`;
|
|
1523
|
+
let start = changelog.indexOf(versionHeader);
|
|
1524
|
+
if (start < 0) { versionHeader = `## ${newPkg.version}`; start = changelog.indexOf(versionHeader); }
|
|
1505
1525
|
if (start >= 0) {
|
|
1506
1526
|
const afterHeader = changelog.slice(start + versionHeader.length);
|
|
1507
1527
|
const nextVersion = afterHeader.indexOf("\n## ");
|
|
@@ -1722,6 +1742,32 @@ bot.onText(/\/(?:auth_status|auth status)$/, async (msg) => {
|
|
|
1722
1742
|
proc.on("error", async (err) => send(`Claude auth status failed: ${redactSensitive(err.message)}`));
|
|
1723
1743
|
});
|
|
1724
1744
|
|
|
1745
|
+
bot.onText(/\/cancel_auth$/, async (msg) => {
|
|
1746
|
+
if (!isAuthorized(msg)) return;
|
|
1747
|
+
if (!pendingClaudeAuthProcess) return send("No Claude auth flow is pending.");
|
|
1748
|
+
clearPendingClaudeAuth();
|
|
1749
|
+
await send("Claude auth flow cancelled. Normal messages will go to the assistant again.");
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
bot.onText(/\/auth_code(?:\s+(.+))?$/, async (msg, match) => {
|
|
1753
|
+
if (!isAuthorized(msg)) return;
|
|
1754
|
+
const code = (match[1] || "").trim();
|
|
1755
|
+
await deleteMessage(msg.message_id);
|
|
1756
|
+
if (!pendingClaudeAuthProcess || pendingClaudeAuthLabel === "manual OAuth token save") {
|
|
1757
|
+
return send("No Claude login flow is waiting for an auth code. Start with /login, or use /use_oauth_token for tokens.");
|
|
1758
|
+
}
|
|
1759
|
+
if (!code || !looksLikeClaudeAuthReply(code)) {
|
|
1760
|
+
return send("That does not look like a Claude auth code/callback. Use /cancel_auth to cancel the login flow.");
|
|
1761
|
+
}
|
|
1762
|
+
try {
|
|
1763
|
+
pendingClaudeAuthProcess.stdin.write(code + "\n");
|
|
1764
|
+
await send("Auth code sent to Claude. I’ll confirm with auth status when Claude finishes.");
|
|
1765
|
+
} catch (e) {
|
|
1766
|
+
clearPendingClaudeAuth();
|
|
1767
|
+
await send(`Could not send auth code to Claude: ${redactSensitive(e.message)}`);
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
|
|
1725
1771
|
bot.onText(/\/login$/, async (msg) => {
|
|
1726
1772
|
if (!isAuthorized(msg)) return;
|
|
1727
1773
|
await runClaudeAuthCommand(["auth", "login", "--claudeai", "--email", "sumeet@inet.africa"], "Claude login");
|
|
@@ -1998,28 +2044,23 @@ bot.on("message", async (msg) => {
|
|
|
1998
2044
|
if (msg.voice || msg.audio || msg.photo || msg.document || msg.video || msg.sticker) return;
|
|
1999
2045
|
if (isDuplicate(msg.message_id)) return;
|
|
2000
2046
|
|
|
2001
|
-
// Handle pending
|
|
2002
|
-
|
|
2047
|
+
// Handle pending manual OAuth token paste mode. Login codes must be sent explicitly
|
|
2048
|
+
// with /auth_code so normal chat can never be deleted/consumed accidentally.
|
|
2049
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthLabel === "manual OAuth token save") {
|
|
2003
2050
|
const text = msg.text.trim();
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
pendingClaudeAuthLabel = null;
|
|
2008
|
-
if (!looksLikeClaudeToken(text)) { await send("That doesn't look like a Claude OAuth token. Not saved."); return; }
|
|
2051
|
+
if (looksLikeClaudeToken(text)) {
|
|
2052
|
+
await deleteMessage(msg.message_id);
|
|
2053
|
+
clearPendingClaudeAuth();
|
|
2009
2054
|
saveClaudeOAuthToken(text);
|
|
2010
2055
|
await send(`Claude OAuth token stored in .env${vault.isUnlocked() ? " and vault" : ""}. Restart the bot so launchd picks it up, or use /restart.`);
|
|
2011
|
-
|
|
2056
|
+
await sendClaudeAuthStatusSummary("Stored token. Current Claude auth status:");
|
|
2012
2057
|
return;
|
|
2013
2058
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
pendingClaudeAuthLabel = null;
|
|
2020
|
-
await send(`Could not send to Claude auth process: ${redactSensitive(e.message)}`);
|
|
2021
|
-
}
|
|
2022
|
-
return;
|
|
2059
|
+
await send("Token paste mode is active, but that does not look like a Claude OAuth token. I left your message visible and will handle it normally. Send /cancel_auth to stop token paste mode.");
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
if (pendingClaudeAuthProcess && pendingClaudeAuthLabel !== "manual OAuth token save") {
|
|
2063
|
+
await send("Claude login is still waiting. I will not delete normal messages. If Claude gave you a code, send it as `/auth_code YOUR_CODE`, or use /cancel_auth.");
|
|
2023
2064
|
}
|
|
2024
2065
|
|
|
2025
2066
|
// Handle onboarding
|