niahere 0.3.11 → 0.3.12
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 +1 -1
- package/src/channels/slack.ts +26 -3
- package/src/chat/engine.ts +7 -2
- package/src/types/engine.ts +2 -0
package/package.json
CHANGED
package/src/channels/slack.ts
CHANGED
|
@@ -15,6 +15,21 @@ function cleanSentinel(text: string): string {
|
|
|
15
15
|
return text.replace(/`/g, "").trim();
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
interface SlackReactionClient {
|
|
19
|
+
reactions: {
|
|
20
|
+
add(args: { channel: string; timestamp: string; name: string }): Promise<unknown>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function reactToSlackMessage(
|
|
25
|
+
client: SlackReactionClient,
|
|
26
|
+
channel: string,
|
|
27
|
+
timestamp: string,
|
|
28
|
+
name: string,
|
|
29
|
+
): Promise<void> {
|
|
30
|
+
await client.reactions.add({ channel, timestamp, name });
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
class SlackChannel implements Channel {
|
|
19
34
|
name = "slack" as const;
|
|
20
35
|
private app: App | null = null;
|
|
@@ -415,12 +430,11 @@ class SlackChannel implements Channel {
|
|
|
415
430
|
}
|
|
416
431
|
|
|
417
432
|
// Add thinking reaction inside the lock so cleanup is guaranteed
|
|
418
|
-
await client.
|
|
419
|
-
.add({ channel: msg.channel, timestamp: msg.ts, name: "thinking_face" })
|
|
433
|
+
await reactToSlackMessage(client, msg.channel, msg.ts, "thinking_face")
|
|
420
434
|
.catch((err) => log.debug({ err, channel: msg.channel }, "slack: failed to add thinking reaction"));
|
|
421
435
|
|
|
422
436
|
try {
|
|
423
|
-
const { result, messageId } = await state.engine.send(
|
|
437
|
+
const { result, messageId, signal } = await state.engine.send(
|
|
424
438
|
text,
|
|
425
439
|
{
|
|
426
440
|
onActivity(status) {
|
|
@@ -430,6 +444,15 @@ class SlackChannel implements Channel {
|
|
|
430
444
|
attachments,
|
|
431
445
|
);
|
|
432
446
|
|
|
447
|
+
if (signal === "provider_down") {
|
|
448
|
+
await reactToSlackMessage(client, msg.channel, msg.ts, "skull").catch((err) =>
|
|
449
|
+
log.debug({ err, channel: msg.channel }, "slack: failed to add provider-down reaction"),
|
|
450
|
+
);
|
|
451
|
+
if (messageId) await Message.updateDeliveryStatus(messageId, "sent").catch(() => {});
|
|
452
|
+
log.info({ channel: msg.channel, key, reaction: "skull" }, "slack provider failure sent as reaction");
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
433
456
|
const reply = result.trim();
|
|
434
457
|
const cleaned = cleanSentinel(reply);
|
|
435
458
|
|
package/src/chat/engine.ts
CHANGED
|
@@ -101,7 +101,7 @@ export function buildContentBlocks(text: string, attachments?: Attachment[]): Me
|
|
|
101
101
|
/** Convert SDK error text into a channel-safe chat response. */
|
|
102
102
|
export function formatChatError(rawError: string | null | undefined): string {
|
|
103
103
|
const error = rawError?.trim();
|
|
104
|
-
if (
|
|
104
|
+
if (getChatErrorSignal(error) === "provider_down") {
|
|
105
105
|
return GENERIC_CHAT_ERROR;
|
|
106
106
|
}
|
|
107
107
|
if (error === "oauth_org_not_allowed") {
|
|
@@ -110,6 +110,11 @@ export function formatChatError(rawError: string | null | undefined): string {
|
|
|
110
110
|
return `[error] ${error}`;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
export function getChatErrorSignal(rawError: string | null | undefined): SendResult["signal"] | undefined {
|
|
114
|
+
const error = rawError?.trim();
|
|
115
|
+
return !error || error.toLowerCase() === "unknown error" ? "provider_down" : undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
113
118
|
export function resolveSdkModel(contextModel?: string | null): string | undefined {
|
|
114
119
|
const model = contextModel || getConfig().model;
|
|
115
120
|
return model && model !== "default" ? model : undefined;
|
|
@@ -559,7 +564,7 @@ export async function createChatEngine(opts: EngineOptions): Promise<ChatEngine>
|
|
|
559
564
|
);
|
|
560
565
|
await ActiveEngine.unregister(room);
|
|
561
566
|
clearLongRunningTimer();
|
|
562
|
-
pending.resolve({ result: errorText, costUsd: 0, turns: 0 });
|
|
567
|
+
pending.resolve({ result: errorText, costUsd: 0, turns: 0, signal: getChatErrorSignal(rawError) });
|
|
563
568
|
pending = null;
|
|
564
569
|
retryCount = 0;
|
|
565
570
|
resetIdleTimer();
|
package/src/types/engine.ts
CHANGED
|
@@ -2,6 +2,8 @@ export interface SendResult {
|
|
|
2
2
|
result: string;
|
|
3
3
|
costUsd: number;
|
|
4
4
|
turns: number;
|
|
5
|
+
/** Optional channel-level signal for transports with richer UI than plain text. */
|
|
6
|
+
signal?: "provider_down";
|
|
5
7
|
/** DB message ID for delivery status tracking (only set for agent replies) */
|
|
6
8
|
messageId?: number;
|
|
7
9
|
}
|