@c4t4/heyamigo 0.9.24 → 0.9.25

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.
@@ -63,8 +63,11 @@ export async function handleReply(job, result, _originalMsg) {
63
63
  const isGroup = isJidGroup(job.jid) === true;
64
64
  void isGroup; // quoting deferred; see comment above
65
65
  const address = formatAddress(jidToAddress(job.jid));
66
+ // Surface media tags in the footer too. Files already parsed above
67
+ // — just map each to its kind so the footer reads e.g. "+2 image".
68
+ const mediaKinds = files.map(kindForFile);
66
69
  const footer = result.stats && config.reply.showStats
67
- ? formatStatsFooter(result.stats)
70
+ ? formatStatsFooter(result.stats, { mediaKinds })
68
71
  : '';
69
72
  let pieceIdx = 0;
70
73
  const baseKey = `reply-${job.jid}-${Date.now()}`;
@@ -177,7 +180,10 @@ export async function initiate(params) {
177
180
  }
178
181
  // Append-only-at-send footer. Never stored, never in Claude's recent-context
179
182
  // feedback loop. Adaptive: shows only what's interesting for this reply.
180
- export function formatStatsFooter(stats) {
183
+ // `mediaKinds` is the array of [IMAGE/VIDEO/AUDIO/DOCUMENT] tags the agent
184
+ // emitted in this reply — they're parsed out of the text in handleReply so
185
+ // we forward them here for footer rendering.
186
+ export function formatStatsFooter(stats, extras) {
181
187
  const parts = [];
182
188
  // Duration — always
183
189
  const secs = stats.durationMs / 1000;
@@ -207,12 +213,36 @@ export function formatStatsFooter(stats) {
207
213
  }
208
214
  if (stats.fresh)
209
215
  parts.push('fresh');
216
+ // Side-effect tags. Order: scheduling first (most "did it work?"
217
+ // value for the user), then delegations, then content side effects.
218
+ const plus = (label, n) => n === 1 ? `+${label}` : `+${n} ${label}`;
219
+ if (stats.remindCount > 0)
220
+ parts.push(plus('remind', stats.remindCount));
221
+ if (stats.cronCount > 0)
222
+ parts.push(plus('cron', stats.cronCount));
223
+ if (stats.asyncBrowserCount > 0)
224
+ parts.push(plus('browser', stats.asyncBrowserCount));
225
+ if (stats.asyncCount > 0)
226
+ parts.push(plus('async', stats.asyncCount));
210
227
  for (const slug of stats.journalSlugs)
211
228
  parts.push(`+journal:${slug}`);
229
+ if (stats.journalCreateCount > 0)
230
+ parts.push(plus('journal-new', stats.journalCreateCount));
212
231
  if (stats.hasDigest)
213
232
  parts.push('+digest');
214
- if (stats.asyncCount > 0) {
215
- parts.push(stats.asyncCount === 1 ? '+async' : `+${stats.asyncCount} async`);
233
+ if (stats.sendTextCount > 0)
234
+ parts.push(plus('send-text', stats.sendTextCount));
235
+ // Media — counted per-kind from the file list. e.g. +2 image, +video.
236
+ // 'document' shortened to 'doc' to keep the footer tight.
237
+ const mediaKinds = extras?.mediaKinds ?? [];
238
+ if (mediaKinds.length > 0) {
239
+ const byKind = new Map();
240
+ for (const k of mediaKinds) {
241
+ const short = k === 'document' ? 'doc' : k;
242
+ byKind.set(short, (byKind.get(short) ?? 0) + 1);
243
+ }
244
+ for (const [kind, n] of byKind)
245
+ parts.push(plus(kind, n));
216
246
  }
217
247
  return `_${parts.join(' · ')}_`;
218
248
  }
@@ -353,7 +353,12 @@ async function callClaude(job) {
353
353
  fresh: wasFresh,
354
354
  hasDigest: digest !== null,
355
355
  journalSlugs: journals.map((j) => j.slug),
356
- asyncCount: asyncTasks.length + asyncBrowserTasks.length,
356
+ journalCreateCount: journalCreates.length,
357
+ asyncCount: asyncTasks.length,
358
+ asyncBrowserCount: asyncBrowserTasks.length,
359
+ remindCount: reminds.length,
360
+ cronCount: crons.length,
361
+ sendTextCount: sendTexts.length,
357
362
  },
358
363
  jobCards: jobCards.length > 0 ? jobCards : undefined,
359
364
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4t4/heyamigo",
3
- "version": "0.9.24",
3
+ "version": "0.9.25",
4
4
  "description": "WhatsApp AI bot powered by Claude with long-term memory, browser control, and role-based access",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",