arisa 4.0.2 → 4.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "4.0.2",
3
+ "version": "4.0.4",
4
4
  "description": "Telegram + Pi Agent modular assistant",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -23,6 +23,25 @@ function requiresProviderAuth(model) {
23
23
  return !isLocalBaseUrl(model?.baseUrl);
24
24
  }
25
25
 
26
+ async function promptAndThrowOnAssistantError(session, prompt) {
27
+ let assistantErrorMessage = "";
28
+ const unsubscribe = session.subscribe((event) => {
29
+ if (event.type === "message_end" && event.message?.stopReason === "error") {
30
+ assistantErrorMessage = event.message.errorMessage || "assistant message ended with error";
31
+ }
32
+ });
33
+
34
+ try {
35
+ await session.prompt(prompt);
36
+ } finally {
37
+ unsubscribe();
38
+ }
39
+
40
+ if (assistantErrorMessage) {
41
+ throw new Error(assistantErrorMessage);
42
+ }
43
+ }
44
+
26
45
  function mimeMatches(pattern, mimeType = "") {
27
46
  if (!pattern || !mimeType) return false;
28
47
  if (pattern === mimeType) return true;
@@ -72,6 +91,10 @@ export class AgentManager {
72
91
  this.pendingNewSessions.add(sessionKey);
73
92
  }
74
93
 
94
+ clearSessionCache(chatId) {
95
+ this.sessions.delete(String(chatId));
96
+ }
97
+
75
98
  createSessionManager(chatId) {
76
99
  const sessionKey = String(chatId);
77
100
  const sessionDir = getChatPiSessionsDir(sessionKey);
@@ -103,7 +126,7 @@ export class AgentManager {
103
126
  model,
104
127
  sessionManager: SessionManager.inMemory(),
105
128
  });
106
- await withTimeout(session.prompt("Reply with exactly: OK"), {
129
+ await withTimeout(promptAndThrowOnAssistantError(session, "Reply with exactly: OK"), {
107
130
  timeoutMs: piValidationTimeoutMs,
108
131
  label: "Pi validation prompt"
109
132
  });
@@ -46,27 +46,40 @@ export function getPiAuthStatus(config) {
46
46
  };
47
47
  }
48
48
 
49
- export function buildPiAuthTelegramMessage({ config, issue = null }) {
49
+ export function buildPiAuthTelegramMessage({ config, issue = null, verified = false }) {
50
50
  const status = getPiAuthStatus(config);
51
- const lines = [
52
- issue
53
- ? `Pi authentication needs attention for ${status.provider}/${status.model}.`
54
- : `Pi authentication status for ${status.provider}/${status.model}.`
55
- ];
51
+ let title = `Pi authentication status for ${status.provider}/${status.model}.`;
52
+ if (issue) {
53
+ title = `Pi authentication needs attention for ${status.provider}/${status.model}.`;
54
+ } else if (verified) {
55
+ title = `Pi authentication is working for ${status.provider}/${status.model}.`;
56
+ }
57
+ const lines = [title];
56
58
 
57
59
  if (issue?.kind === "invalidated-token") {
58
60
  lines.push("The provider says the current authentication token was invalidated.");
59
61
  } else if (issue?.kind === "missing-auth") {
60
62
  lines.push("Arisa could not find usable authentication for this provider.");
63
+ } else if (issue?.kind === "validation-failed") {
64
+ lines.push("Arisa could not validate the current Pi authentication.");
65
+ } else if (verified) {
66
+ lines.push(status.hasApiKey
67
+ ? "The configured Pi API key was accepted by the provider."
68
+ : "The stored auth was accepted by the provider.");
61
69
  } else {
62
- lines.push(`Stored auth: ${status.hasStoredAuth ? "detected" : "not detected"}.`);
70
+ lines.push(`Stored auth record: ${status.hasStoredAuth ? "detected" : "not detected"}.`);
71
+ lines.push("This only checks whether credentials are stored, not whether the provider will accept them.");
63
72
  }
64
73
 
65
74
  if (issue?.message) {
66
75
  lines.push(`Details: ${issue.message}`);
67
76
  }
68
77
 
69
- if (status.hasApiKey) {
78
+ if (verified) {
79
+ lines.push("No action needed.");
80
+ } else if (!issue) {
81
+ lines.push("Run `/auth` to validate these credentials against the provider.");
82
+ } else if (status.hasApiKey) {
70
83
  lines.push("A Pi API key is configured, but the provider rejected the current request. Update the key and restart Arisa.");
71
84
  } else if (status.supportsOAuth) {
72
85
  lines.push("For now, re-run `arisa --bootstrap` on the host and complete Pi login again.");
@@ -74,6 +87,8 @@ export function buildPiAuthTelegramMessage({ config, issue = null }) {
74
87
  lines.push("This provider needs a Pi API key. Re-run `arisa --bootstrap`, provide a key, and restart Arisa.");
75
88
  }
76
89
 
77
- lines.push("Telegram-based renewal is not wired yet, but this /auth path is ready for that flow.");
90
+ if (issue) {
91
+ lines.push("Telegram-based renewal is not wired yet, but this /auth path is ready for that flow.");
92
+ }
78
93
  return lines.join("\n");
79
94
  }
@@ -529,7 +529,16 @@ export async function createTelegramBot({ config, artifactStore, toolRegistry, t
529
529
  bot.command("auth", async (ctx) => {
530
530
  const auth = await authorizeChat({ config, chatId: ctx.chat.id, saveConfig, chatMeta: getIncomingChatMeta(ctx) });
531
531
  if (!auth.ok) return;
532
- await ctx.reply(buildPiAuthTelegramMessage({ config }));
532
+ await withTyping(ctx, async () => {
533
+ try {
534
+ await agentManager.validatePiAgent();
535
+ agentManager.clearSessionCache(ctx.chat.id);
536
+ await ctx.reply(buildPiAuthTelegramMessage({ config, verified: true }));
537
+ } catch (error) {
538
+ const issue = getPiAuthIssue(error) || { kind: "validation-failed", message: getErrorMessage(error) };
539
+ await ctx.reply(buildPiAuthTelegramMessage({ config, issue }));
540
+ }
541
+ });
533
542
  });
534
543
 
535
544
  bot.on("message", async (ctx) => {