niahere 0.5.0 → 0.5.2

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 (48) hide show
  1. package/package.json +4 -4
  2. package/src/agent/backends/claude-normalize.ts +41 -1
  3. package/src/agent/backends/claude.ts +2 -1
  4. package/src/agent/backends/codex-normalize.ts +20 -6
  5. package/src/agent/backends/codex.ts +3 -2
  6. package/src/agent/failure.ts +3 -1
  7. package/src/agent/mcp-endpoint.ts +3 -2
  8. package/src/channels/common/chat-session.ts +60 -0
  9. package/src/channels/phone/consult.ts +2 -1
  10. package/src/channels/phone/index.ts +5 -3
  11. package/src/channels/phone/relay.ts +15 -5
  12. package/src/channels/slack.ts +24 -34
  13. package/src/channels/sms.ts +16 -36
  14. package/src/channels/telegram.ts +22 -34
  15. package/src/channels/twilio/media-cache.ts +4 -3
  16. package/src/channels/twilio/rest.ts +0 -31
  17. package/src/channels/twilio/server.ts +0 -5
  18. package/src/channels/twilio/shared.ts +36 -0
  19. package/src/channels/whatsapp.ts +24 -58
  20. package/src/chat/engine.ts +17 -8
  21. package/src/chat/gap-marker.ts +63 -0
  22. package/src/chat/repl.ts +5 -5
  23. package/src/cli/config.ts +71 -0
  24. package/src/cli/index.ts +23 -288
  25. package/src/cli/job.ts +1 -2
  26. package/src/cli/logs.ts +55 -0
  27. package/src/cli/run.ts +74 -0
  28. package/src/cli/skills.ts +13 -0
  29. package/src/cli/status.ts +0 -1
  30. package/src/cli/test.ts +32 -0
  31. package/src/cli/update.ts +79 -0
  32. package/src/commands/backup.ts +1 -2
  33. package/src/commands/init.ts +1 -2
  34. package/src/core/alive.ts +4 -3
  35. package/src/core/consolidator.ts +78 -31
  36. package/src/core/daemon.ts +3 -2
  37. package/src/core/finalizer.ts +9 -5
  38. package/src/core/runner.ts +7 -6
  39. package/src/core/scheduler.ts +19 -4
  40. package/src/core/skills.ts +0 -4
  41. package/src/db/migrations/017_sessions_consolidated_count.ts +9 -0
  42. package/src/db/models/active_engine.ts +0 -7
  43. package/src/db/models/job.ts +3 -2
  44. package/src/db/models/message.ts +10 -0
  45. package/src/db/models/session.ts +69 -15
  46. package/src/mcp/tools/misc.ts +2 -1
  47. package/src/mcp/tools/send.ts +5 -4
  48. package/src/utils/errors.ts +26 -0
@@ -5,6 +5,7 @@ import { Message, Session } from "../../db/models";
5
5
  import { getConfig } from "../../utils/config";
6
6
  import { getChannel } from "../../channels/registry";
7
7
  import { log } from "../../utils/log";
8
+ import { errMsg, ignore } from "../../utils/errors";
8
9
  import type { Recipient } from "../../types";
9
10
  import type { McpSourceContext } from "../index";
10
11
 
@@ -168,7 +169,7 @@ export async function sendMessage(
168
169
  let media: { data: Uint8Array; mimeType: string; filename: string } | undefined;
169
170
  if (mediaPath) {
170
171
  if (!existsSync(mediaPath)) {
171
- if (messageId) await Message.updateDeliveryStatus(messageId, "failed").catch(() => {});
172
+ if (messageId) await ignore(Message.updateDeliveryStatus(messageId, "failed"), "record failed delivery status");
172
173
  return `Failed to send: file not found: ${mediaPath}`;
173
174
  }
174
175
  const buf = readFileSync(mediaPath);
@@ -190,13 +191,13 @@ export async function sendMessage(
190
191
 
191
192
  // Mark as sent
192
193
  if (messageId) {
193
- await Message.updateDeliveryStatus(messageId, "sent").catch(() => {});
194
+ await ignore(Message.updateDeliveryStatus(messageId, "sent"), "record sent delivery status");
194
195
  }
195
196
 
196
197
  return mediaPath ? "Message with media sent." : "Message sent.";
197
198
  } catch (err) {
198
- if (messageId) await Message.updateDeliveryStatus(messageId, "failed").catch(() => {});
199
- const errText = err instanceof Error ? err.message : String(err);
199
+ if (messageId) await ignore(Message.updateDeliveryStatus(messageId, "failed"), "record failed delivery status");
200
+ const errText = errMsg(err);
200
201
  return `Failed to send: ${errText}`;
201
202
  }
202
203
  }
@@ -1,4 +1,30 @@
1
+ import { log } from "./log";
2
+
1
3
  /** Extract a human-readable message from an unknown error value. */
2
4
  export function errMsg(err: unknown): string {
3
5
  return err instanceof Error ? err.message : String(err);
4
6
  }
7
+
8
+ /** Normalize an unknown to an Error, keeping the original when it already is one
9
+ * so its stack survives a rethrow. */
10
+ export function asError(err: unknown): Error {
11
+ return err instanceof Error ? err : new Error(errMsg(err));
12
+ }
13
+
14
+ type Report = (context: string, err: string) => void;
15
+
16
+ const report: Report = (context, err) => log.debug({ err }, `ignored failure: ${context}`);
17
+
18
+ /**
19
+ * Await best-effort work whose failure must not stop the caller — cleanup,
20
+ * bookkeeping, teardown. Use instead of `.catch(() => {})`: the outcome is the
21
+ * same, but a failure leaves a trace rather than vanishing, so a persistent one
22
+ * is discoverable instead of silent.
23
+ */
24
+ export async function ignore(work: Promise<unknown>, context: string, onError: Report = report): Promise<void> {
25
+ try {
26
+ await work;
27
+ } catch (err) {
28
+ onError(context, errMsg(err));
29
+ }
30
+ }