@heylemon/lemonade 2026.2.20 → 2026.2.21

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.2.20",
3
- "commit": "e49805d8488591840c53c697252f44ddfa686424",
4
- "builtAt": "2026-02-19T10:41:08.140Z"
2
+ "version": "2026.2.21",
3
+ "commit": "f1adf7fa5b1b100dc4f58d4325177d6e5b5b8a7d",
4
+ "builtAt": "2026-02-19T11:32:30.329Z"
5
5
  }
@@ -1 +1 @@
1
- 097295da59112a03be00996fb0b774b800b315f4a291f6253930f4d42aa9a1ac
1
+ 61cedf672a2f645b8bc0c25ed3098af955cc9ee4c0a98935bd816883b972f478
@@ -426,6 +426,12 @@ async function resolveAutoEntries(params) {
426
426
  return [keys];
427
427
  return [];
428
428
  }
429
+ function isWhatsAppContext(ctx) {
430
+ const candidates = [ctx.Surface, ctx.Provider, ctx.OriginatingChannel]
431
+ .map((value) => value?.trim().toLowerCase())
432
+ .filter((value) => Boolean(value));
433
+ return candidates.some((value) => value === "whatsapp");
434
+ }
429
435
  export async function resolveAutoImageModel(params) {
430
436
  const providerRegistry = buildProviderRegistry();
431
437
  const toActive = (entry) => {
@@ -1001,6 +1007,70 @@ export async function runCapability(params) {
1001
1007
  };
1002
1008
  }
1003
1009
  }
1010
+ // For WhatsApp audio, force local Parakeet transcription only.
1011
+ // Do not fall back to whisper/provider-based transcription paths.
1012
+ if (capability === "audio" && isWhatsAppContext(ctx)) {
1013
+ const parakeetEntry = await resolveLocalParakeetEntry();
1014
+ if (!parakeetEntry) {
1015
+ if (shouldLogVerbose()) {
1016
+ logVerbose("audio understanding skipped for WhatsApp: local Parakeet is unavailable");
1017
+ }
1018
+ return {
1019
+ outputs: [],
1020
+ decision: {
1021
+ capability,
1022
+ outcome: "skipped",
1023
+ attachments: selected.map((item) => ({
1024
+ attachmentIndex: item.index,
1025
+ attempts: [
1026
+ {
1027
+ type: "cli",
1028
+ provider: "local-parakeet",
1029
+ model: "parakeet",
1030
+ outcome: "skipped",
1031
+ reason: "local Parakeet unavailable",
1032
+ },
1033
+ ],
1034
+ chosen: undefined,
1035
+ })),
1036
+ },
1037
+ };
1038
+ }
1039
+ const outputs = [];
1040
+ const attachmentDecisions = [];
1041
+ for (const attachment of selected) {
1042
+ const { output, attempts } = await runAttachmentEntries({
1043
+ capability,
1044
+ cfg,
1045
+ ctx,
1046
+ attachmentIndex: attachment.index,
1047
+ agentDir: params.agentDir,
1048
+ providerRegistry: params.providerRegistry,
1049
+ cache: params.attachments,
1050
+ entries: [parakeetEntry],
1051
+ config,
1052
+ });
1053
+ if (output)
1054
+ outputs.push(output);
1055
+ attachmentDecisions.push({
1056
+ attachmentIndex: attachment.index,
1057
+ attempts,
1058
+ chosen: attempts.find((attempt) => attempt.outcome === "success"),
1059
+ });
1060
+ }
1061
+ const decision = {
1062
+ capability,
1063
+ outcome: outputs.length > 0 ? "success" : "skipped",
1064
+ attachments: attachmentDecisions,
1065
+ };
1066
+ if (shouldLogVerbose()) {
1067
+ logVerbose(`Media understanding ${formatDecisionSummary(decision)} (forced local Parakeet)`);
1068
+ }
1069
+ return {
1070
+ outputs,
1071
+ decision,
1072
+ };
1073
+ }
1004
1074
  const entries = resolveModelEntries({
1005
1075
  cfg,
1006
1076
  capability,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heylemon/lemonade",
3
- "version": "2026.2.20",
3
+ "version": "2026.2.21",
4
4
  "description": "AI gateway CLI for Lemon - local AI assistant with integrations",
5
5
  "publishConfig": {
6
6
  "access": "restricted"