@inetafrica/open-claudia 1.14.0 → 1.14.1
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 +65 -0
- package/bot.js +65 -0
- package/package.json +1 -1
package/bot-agent.js
CHANGED
|
@@ -830,6 +830,66 @@ function preflightClaudeAuthMessage() {
|
|
|
830
830
|
}
|
|
831
831
|
|
|
832
832
|
|
|
833
|
+
function isClaudeUsageLimitText(text) {
|
|
834
|
+
const lower = String(text || "").toLowerCase();
|
|
835
|
+
return lower.includes("usage limit") ||
|
|
836
|
+
lower.includes("you've hit your usage limit") ||
|
|
837
|
+
lower.includes("you have hit your usage limit") ||
|
|
838
|
+
lower.includes("spend limit") ||
|
|
839
|
+
lower.includes("monthly cycle") ||
|
|
840
|
+
lower.includes("rate limit") && lower.includes("model");
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
function claudeUsageLimitMessage(details = "") {
|
|
844
|
+
return [
|
|
845
|
+
"Claude ran, but the selected model is unavailable/limited right now.",
|
|
846
|
+
details ? `\nDetails:\n${redactSensitive(details)}` : "",
|
|
847
|
+
"",
|
|
848
|
+
"Try from Telegram:",
|
|
849
|
+
"1. /model sonnet",
|
|
850
|
+
"2. Then send your message again",
|
|
851
|
+
"",
|
|
852
|
+
"If you specifically need Opus, wait for the usage window to reset or increase the spend/usage limit."
|
|
853
|
+
].filter(Boolean).join("\n");
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
function runClaudeAuthStatusDiagnostic() {
|
|
857
|
+
try {
|
|
858
|
+
const output = execSync(`"${CLAUDE_PATH}" auth status`, {
|
|
859
|
+
cwd: process.env.HOME || require("os").homedir(),
|
|
860
|
+
env: claudeSubprocessEnv(),
|
|
861
|
+
encoding: "utf8",
|
|
862
|
+
timeout: 10000,
|
|
863
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
864
|
+
});
|
|
865
|
+
return output.trim();
|
|
866
|
+
} catch (e) {
|
|
867
|
+
return `${e.stdout || ""}\n${e.stderr || ""}\n${e.message || ""}`.trim();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function claudeEmptyFailureMessage(code, stderrText = "") {
|
|
872
|
+
const stderr = redactSensitive(String(stderrText || "").trim());
|
|
873
|
+
if (isClaudeUsageLimitText(stderr)) return claudeUsageLimitMessage(stderr.slice(-1200));
|
|
874
|
+
if (isClaudeAuthErrorText(stderr)) return claudeAuthRecoveryMessage(stderr.slice(-1200));
|
|
875
|
+
|
|
876
|
+
const authStatus = runClaudeAuthStatusDiagnostic();
|
|
877
|
+
if (isClaudeAuthErrorText(authStatus)) return claudeAuthRecoveryMessage(authStatus.slice(-1200));
|
|
878
|
+
if (isClaudeUsageLimitText(authStatus)) return claudeUsageLimitMessage(authStatus.slice(-1200));
|
|
879
|
+
|
|
880
|
+
return [
|
|
881
|
+
`Claude exited with code ${code} but produced no assistant output.`,
|
|
882
|
+
stderr ? `\nStderr:\n${stderr.slice(-1200)}` : "\nStderr: (empty)",
|
|
883
|
+
authStatus ? `\nAuth status:\n${redactSensitive(authStatus).slice(-1200)}` : "",
|
|
884
|
+
"",
|
|
885
|
+
"Useful next steps:",
|
|
886
|
+
"• /auth_status — verify Claude auth",
|
|
887
|
+
"• /model sonnet — switch away from Opus if usage-limited",
|
|
888
|
+
"• /setup_token — create a launchd-safe OAuth token if Keychain is the issue"
|
|
889
|
+
].filter(Boolean).join("\n");
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
|
|
833
893
|
function summarizeClaudeAuthStatus(output, exitCode, tokenInfo) {
|
|
834
894
|
const text = String(output || "");
|
|
835
895
|
const lower = text.toLowerCase();
|
|
@@ -1172,6 +1232,11 @@ async function runClaude(prompt, cwd, replyToMsgId, opts = {}) {
|
|
|
1172
1232
|
return;
|
|
1173
1233
|
}
|
|
1174
1234
|
try {
|
|
1235
|
+
if (code !== 0 && code !== null && !assistantText.trim()) {
|
|
1236
|
+
await send(claudeEmptyFailureMessage(code, stderrBuffer), { replyTo: replyToMsgId });
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1175
1240
|
const finalText = redactSensitive(assistantText || "(no output)");
|
|
1176
1241
|
const chunks = splitMessage(finalText);
|
|
1177
1242
|
const firstChunk = chunks[0];
|
package/bot.js
CHANGED
|
@@ -892,6 +892,66 @@ function preflightClaudeAuthMessage() {
|
|
|
892
892
|
}
|
|
893
893
|
|
|
894
894
|
|
|
895
|
+
function isClaudeUsageLimitText(text) {
|
|
896
|
+
const lower = String(text || "").toLowerCase();
|
|
897
|
+
return lower.includes("usage limit") ||
|
|
898
|
+
lower.includes("you've hit your usage limit") ||
|
|
899
|
+
lower.includes("you have hit your usage limit") ||
|
|
900
|
+
lower.includes("spend limit") ||
|
|
901
|
+
lower.includes("monthly cycle") ||
|
|
902
|
+
lower.includes("rate limit") && lower.includes("model");
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function claudeUsageLimitMessage(details = "") {
|
|
906
|
+
return [
|
|
907
|
+
"Claude ran, but the selected model is unavailable/limited right now.",
|
|
908
|
+
details ? `\nDetails:\n${redactSensitive(details)}` : "",
|
|
909
|
+
"",
|
|
910
|
+
"Try from Telegram:",
|
|
911
|
+
"1. /model sonnet",
|
|
912
|
+
"2. Then send your message again",
|
|
913
|
+
"",
|
|
914
|
+
"If you specifically need Opus, wait for the usage window to reset or increase the spend/usage limit."
|
|
915
|
+
].filter(Boolean).join("\n");
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function runClaudeAuthStatusDiagnostic() {
|
|
919
|
+
try {
|
|
920
|
+
const output = execSync(`"${CLAUDE_PATH}" auth status`, {
|
|
921
|
+
cwd: process.env.HOME || require("os").homedir(),
|
|
922
|
+
env: claudeSubprocessEnv(),
|
|
923
|
+
encoding: "utf8",
|
|
924
|
+
timeout: 10000,
|
|
925
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
926
|
+
});
|
|
927
|
+
return output.trim();
|
|
928
|
+
} catch (e) {
|
|
929
|
+
return `${e.stdout || ""}\n${e.stderr || ""}\n${e.message || ""}`.trim();
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
function claudeEmptyFailureMessage(code, stderrText = "") {
|
|
934
|
+
const stderr = redactSensitive(String(stderrText || "").trim());
|
|
935
|
+
if (isClaudeUsageLimitText(stderr)) return claudeUsageLimitMessage(stderr.slice(-1200));
|
|
936
|
+
if (isClaudeAuthErrorText(stderr)) return claudeAuthRecoveryMessage(stderr.slice(-1200));
|
|
937
|
+
|
|
938
|
+
const authStatus = runClaudeAuthStatusDiagnostic();
|
|
939
|
+
if (isClaudeAuthErrorText(authStatus)) return claudeAuthRecoveryMessage(authStatus.slice(-1200));
|
|
940
|
+
if (isClaudeUsageLimitText(authStatus)) return claudeUsageLimitMessage(authStatus.slice(-1200));
|
|
941
|
+
|
|
942
|
+
return [
|
|
943
|
+
`Claude exited with code ${code} but produced no assistant output.`,
|
|
944
|
+
stderr ? `\nStderr:\n${stderr.slice(-1200)}` : "\nStderr: (empty)",
|
|
945
|
+
authStatus ? `\nAuth status:\n${redactSensitive(authStatus).slice(-1200)}` : "",
|
|
946
|
+
"",
|
|
947
|
+
"Useful next steps:",
|
|
948
|
+
"• /auth_status — verify Claude auth",
|
|
949
|
+
"• /model sonnet — switch away from Opus if usage-limited",
|
|
950
|
+
"• /setup_token — create a launchd-safe OAuth token if Keychain is the issue"
|
|
951
|
+
].filter(Boolean).join("\n");
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
|
|
895
955
|
function summarizeClaudeAuthStatus(output, exitCode, tokenInfo) {
|
|
896
956
|
const text = String(output || "");
|
|
897
957
|
const lower = text.toLowerCase();
|
|
@@ -1193,6 +1253,11 @@ async function runClaude(prompt, cwd, replyToMsgId, opts = {}) {
|
|
|
1193
1253
|
}
|
|
1194
1254
|
|
|
1195
1255
|
try {
|
|
1256
|
+
if (code !== 0 && code !== null && !assistantText.trim()) {
|
|
1257
|
+
await send(claudeEmptyFailureMessage(code, stderrBuffer), { replyTo: replyToMsgId });
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1196
1261
|
const finalText = redactSensitive(assistantText || "(no output)");
|
|
1197
1262
|
const chunks = splitMessage(finalText);
|
|
1198
1263
|
const firstChunk = chunks[0];
|