@inetafrica/open-claudia 1.14.5 → 1.14.7

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.
Files changed (3) hide show
  1. package/bot-agent.js +36 -6
  2. package/bot.js +36 -6
  3. package/package.json +1 -1
package/bot-agent.js CHANGED
@@ -719,6 +719,29 @@ function redactSensitive(value) {
719
719
  .replace(/([?&](?:token|access_token|refresh_token)=)[^\s&]+/gi, "$1[REDACTED]");
720
720
  }
721
721
 
722
+
723
+ function stripTerminalControls(value) {
724
+ return String(value || "")
725
+ // OSC 8 hyperlinks and other OSC sequences
726
+ .replace(/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g, "")
727
+ // CSI ANSI sequences
728
+ .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "")
729
+ // remaining non-printing controls except newline/tab
730
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
731
+ }
732
+
733
+ function isClaudeAuthUrl(url) {
734
+ try {
735
+ const u = new URL(url);
736
+ const host = u.hostname.toLowerCase();
737
+ return host === "claude.com" || host.endsWith(".claude.com") ||
738
+ host === "anthropic.com" || host.endsWith(".anthropic.com") ||
739
+ host === "localhost" || host === "127.0.0.1";
740
+ } catch (e) {
741
+ return false;
742
+ }
743
+ }
744
+
722
745
  function looksLikeClaudeToken(value) {
723
746
  const text = String(value || "").trim();
724
747
  return /^sk-ant-[A-Za-z0-9._-]+$/.test(text) || text.length >= 80 && /^[A-Za-z0-9._=-]+$/.test(text);
@@ -786,7 +809,7 @@ function extractClaudeToken(text) {
786
809
  }
787
810
 
788
811
  function extractUrls(text) {
789
- return [...String(text || "").matchAll(/https?:\/\/[^\s)]+/g)].map((m) => m[0]);
812
+ return [...stripTerminalControls(text).matchAll(/https?:\/\/[^\s)]+/g)].map((m) => m[0]);
790
813
  }
791
814
 
792
815
 
@@ -966,14 +989,16 @@ async function runClaudeAuthCommand(args, label, opts = {}) {
966
989
  await send(tokenStored ? "Claude OAuth token captured and stored. I did not print it." : "Claude OAuth token appeared, but I could not store it.");
967
990
  }
968
991
  for (const url of extractUrls(chunk)) {
992
+ if (!isClaudeAuthUrl(url)) continue;
969
993
  if (!sentUrls.has(url)) {
970
994
  sentUrls.add(url);
971
995
  await send(`${label} URL:\n${redactSensitive(url)}\n\nOpen it, complete the flow, then paste any code Claude asks for here.`);
972
996
  }
973
997
  }
974
- const redacted = redactSensitive(chunk).trim();
998
+ const redacted = redactSensitive(stripTerminalControls(chunk)).trim();
975
999
  const now = Date.now();
976
- if (redacted && now - lastSnippetAt > 3000 && !looksLikeClaudeToken(redacted)) {
1000
+ const usefulAuthLine = /opening browser|paste code|enter code|login|auth|token|error|failed/i.test(redacted);
1001
+ if (redacted && usefulAuthLine && now - lastSnippetAt > 3000 && !looksLikeClaudeToken(redacted) && !/github\.com\/vadimdemedes\/ink/i.test(redacted)) {
977
1002
  lastSnippetAt = now;
978
1003
  await send(redacted.length > 1200 ? redacted.slice(-1200) : redacted);
979
1004
  }
@@ -986,12 +1011,17 @@ async function runClaudeAuthCommand(args, label, opts = {}) {
986
1011
  pendingClaudeAuthLabel = null;
987
1012
  const token = opts.captureToken ? extractClaudeToken(output) : null;
988
1013
  if (token && !tokenStored) tokenStored = saveClaudeOAuthToken(token);
989
- const final = redactSensitive(output.trim());
1014
+ const cleaned = redactSensitive(stripTerminalControls(output))
1015
+ .replace(/https?:\/\/github\.com\/vadimdemedes\/ink\S*/gi, "")
1016
+ .trim();
1017
+ const isTtyError = /raw mode is not supported|process\.stdin/i.test(output);
990
1018
  if (tokenStored) {
991
1019
  await send(`${label} finished. OAuth token stored for launchd/non-interactive Claude runs.`);
992
1020
  await sendClaudeAuthStatusSummary("Post-auth check:");
993
- } else if (final) {
994
- await send(`${label} finished (exit ${code}).\n\n${final.slice(-2500)}`);
1021
+ } else if (isTtyError && opts.captureToken) {
1022
+ await send(`${label} cannot complete from this bot — the Claude CLI needs an interactive terminal for setup-token.\n\nRun this in your Mac terminal:\n claude setup-token\n\nThen paste the token here with:\n /use_oauth_token <token>`);
1023
+ } else if (cleaned) {
1024
+ await send(`${label} finished (exit ${code}).\n\n${cleaned.slice(-2500)}`);
995
1025
  await sendClaudeAuthStatusSummary("Post-auth check:");
996
1026
  } else {
997
1027
  await send(`${label} finished (exit ${code}).`);
package/bot.js CHANGED
@@ -781,6 +781,29 @@ function redactSensitive(value) {
781
781
  .replace(/([?&](?:token|access_token|refresh_token)=)[^\s&]+/gi, "$1[REDACTED]");
782
782
  }
783
783
 
784
+
785
+ function stripTerminalControls(value) {
786
+ return String(value || "")
787
+ // OSC 8 hyperlinks and other OSC sequences
788
+ .replace(/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g, "")
789
+ // CSI ANSI sequences
790
+ .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "")
791
+ // remaining non-printing controls except newline/tab
792
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
793
+ }
794
+
795
+ function isClaudeAuthUrl(url) {
796
+ try {
797
+ const u = new URL(url);
798
+ const host = u.hostname.toLowerCase();
799
+ return host === "claude.com" || host.endsWith(".claude.com") ||
800
+ host === "anthropic.com" || host.endsWith(".anthropic.com") ||
801
+ host === "localhost" || host === "127.0.0.1";
802
+ } catch (e) {
803
+ return false;
804
+ }
805
+ }
806
+
784
807
  function looksLikeClaudeToken(value) {
785
808
  const text = String(value || "").trim();
786
809
  return /^sk-ant-[A-Za-z0-9._-]+$/.test(text) || text.length >= 80 && /^[A-Za-z0-9._=-]+$/.test(text);
@@ -848,7 +871,7 @@ function extractClaudeToken(text) {
848
871
  }
849
872
 
850
873
  function extractUrls(text) {
851
- return [...String(text || "").matchAll(/https?:\/\/[^\s)]+/g)].map((m) => m[0]);
874
+ return [...stripTerminalControls(text).matchAll(/https?:\/\/[^\s)]+/g)].map((m) => m[0]);
852
875
  }
853
876
 
854
877
 
@@ -1028,14 +1051,16 @@ async function runClaudeAuthCommand(args, label, opts = {}) {
1028
1051
  await send(tokenStored ? "Claude OAuth token captured and stored. I did not print it." : "Claude OAuth token appeared, but I could not store it.");
1029
1052
  }
1030
1053
  for (const url of extractUrls(chunk)) {
1054
+ if (!isClaudeAuthUrl(url)) continue;
1031
1055
  if (!sentUrls.has(url)) {
1032
1056
  sentUrls.add(url);
1033
1057
  await send(`${label} URL:\n${redactSensitive(url)}\n\nOpen it, complete the flow, then paste any code Claude asks for here.`);
1034
1058
  }
1035
1059
  }
1036
- const redacted = redactSensitive(chunk).trim();
1060
+ const redacted = redactSensitive(stripTerminalControls(chunk)).trim();
1037
1061
  const now = Date.now();
1038
- if (redacted && now - lastSnippetAt > 3000 && !looksLikeClaudeToken(redacted)) {
1062
+ const usefulAuthLine = /opening browser|paste code|enter code|login|auth|token|error|failed/i.test(redacted);
1063
+ if (redacted && usefulAuthLine && now - lastSnippetAt > 3000 && !looksLikeClaudeToken(redacted) && !/github\.com\/vadimdemedes\/ink/i.test(redacted)) {
1039
1064
  lastSnippetAt = now;
1040
1065
  await send(redacted.length > 1200 ? redacted.slice(-1200) : redacted);
1041
1066
  }
@@ -1048,12 +1073,17 @@ async function runClaudeAuthCommand(args, label, opts = {}) {
1048
1073
  pendingClaudeAuthLabel = null;
1049
1074
  const token = opts.captureToken ? extractClaudeToken(output) : null;
1050
1075
  if (token && !tokenStored) tokenStored = saveClaudeOAuthToken(token);
1051
- const final = redactSensitive(output.trim());
1076
+ const cleaned = redactSensitive(stripTerminalControls(output))
1077
+ .replace(/https?:\/\/github\.com\/vadimdemedes\/ink\S*/gi, "")
1078
+ .trim();
1079
+ const isTtyError = /raw mode is not supported|process\.stdin/i.test(output);
1052
1080
  if (tokenStored) {
1053
1081
  await send(`${label} finished. OAuth token stored for launchd/non-interactive Claude runs.`);
1054
1082
  await sendClaudeAuthStatusSummary("Post-auth check:");
1055
- } else if (final) {
1056
- await send(`${label} finished (exit ${code}).\n\n${final.slice(-2500)}`);
1083
+ } else if (isTtyError && opts.captureToken) {
1084
+ await send(`${label} cannot complete from this bot — the Claude CLI needs an interactive terminal for setup-token.\n\nRun this in your Mac terminal:\n claude setup-token\n\nThen paste the token here with:\n /use_oauth_token <token>`);
1085
+ } else if (cleaned) {
1086
+ await send(`${label} finished (exit ${code}).\n\n${cleaned.slice(-2500)}`);
1057
1087
  await sendClaudeAuthStatusSummary("Post-auth check:");
1058
1088
  } else {
1059
1089
  await send(`${label} finished (exit ${code}).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inetafrica/open-claudia",
3
- "version": "1.14.5",
3
+ "version": "1.14.7",
4
4
  "description": "Your always-on AI coding assistant — Claude Code via Telegram",
5
5
  "main": "bot.js",
6
6
  "bin": {