@bill10/agent-007 0.14.0 → 0.14.1

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/.env.example CHANGED
@@ -65,8 +65,8 @@
65
65
  # Settings > Accessibility > Spoken Content > System voice > Manage Voices),
66
66
  # else say's default. A voice that is not installed is logged and skipped.
67
67
  # SAY_VOICE=Ava (Premium)
68
- # How fast it speaks, in words per minute (120-300). Unset: 205, a little faster
69
- # than say's own 175.
68
+ # How fast it speaks, in words per minute (120-300). Unset: no -r is passed, so
69
+ # each voice speaks at its own system default speed.
70
70
  # SAY_RATE=205
71
71
  # Your voice notes are transcribed with whisper.cpp (brew install whisper-cpp).
72
72
  # WHISPER_MODEL is the full path to a ggml model, e.g. ggml-base.en.bin;
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.14.0.0
1
+ 0.14.0.1
package/bin/agent-007.js CHANGED
@@ -48,7 +48,8 @@ Settings (default in brackets):
48
48
  voice (macOS say + ffmpeg) [mirror]
49
49
  SAY_VOICE macOS voice for that, from say -v '?' [best
50
50
  installed English Premium/Enhanced voice]
51
- SAY_RATE How fast it speaks, words per minute, 120-300 [205]
51
+ SAY_RATE How fast it speaks, words per minute, 120-300
52
+ [unset: the voice's own system speed]
52
53
  WHISPER_MODEL whisper.cpp model file; your voice notes are
53
54
  transcribed locally [off]
54
55
  WHISPER_CPP_BIN whisper.cpp CLI if not on PATH [whisper-cli]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bill10/agent-007",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "From web terminals for your coding agents to a self-running agent company: Claude Code and Codex in parallel git worktrees, a job board they pick work from, and one agent that runs the board from a goal.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/server/owner.js CHANGED
@@ -460,7 +460,10 @@ export function startTelegram({ broadcast, env = process.env } = {}) {
460
460
  if (!chatId) console.log(' Telegram: send any message to your bot, then set TELEGRAM_CHAT_ID=<id> (the id is shown here when it arrives)');
461
461
  else console.log(' Telegram: on');
462
462
  if (voiceSetting(env) !== 'never' && !speechUnavailable(env)) {
463
- sayVoice(env).then(v => console.log(` Telegram: speaking with ${v ? `the ${v} voice` : "say's default voice"} at ${sayRate(env)} wpm`));
463
+ sayVoice(env).then(v => {
464
+ const rate = sayRate(env);
465
+ console.log(` Telegram: speaking with ${v ? `the ${v} voice` : "say's default voice"} at ${rate ? `${rate} wpm` : 'the system default speed'}`);
466
+ });
464
467
  }
465
468
  const controller = new AbortController();
466
469
  stopper = controller;
package/server/voice.js CHANGED
@@ -120,17 +120,19 @@ export function sayVoice(env = process.env) {
120
120
  return voicePick;
121
121
  }
122
122
 
123
- // SAY_RATE in words per minute, 120–300. Unset: 205, about 15% faster than
124
- // say's own 175, which the owner found a little slow on Ava (Premium).
125
- export const DEFAULT_SAY_RATE = 205;
126
- let ratePick;
123
+ // SAY_RATE in words per minute, 120–300. Unset (or invalid): null, so `say`
124
+ // is not given `-r` at all and speaks at the voice's own system rate.
125
+ let ratePick, ratePicked = false;
127
126
  export function sayRate(env = process.env) {
128
- if (ratePick) return ratePick;
127
+ if (ratePicked) return ratePick;
128
+ ratePicked = true;
129
129
  const raw = (env.SAY_RATE || '').trim();
130
130
  const n = Number(raw);
131
- if (raw && !Number.isInteger(n)) console.log(` Telegram: SAY_RATE "${raw}" is not a whole number of words per minute; using ${DEFAULT_SAY_RATE}`);
132
- ratePick = raw && Number.isInteger(n) ? Math.min(300, Math.max(120, n)) : DEFAULT_SAY_RATE;
133
- return ratePick;
131
+ if (raw && !Number.isInteger(n)) {
132
+ console.log(` Telegram: SAY_RATE "${raw}" is not a whole number of words per minute; using the system default speed`);
133
+ return ratePick = null;
134
+ }
135
+ return ratePick = raw ? Math.min(300, Math.max(120, n)) : null;
134
136
  }
135
137
 
136
138
  // text → OGG/Opus bytes. URLs are said as "link"; the caption carries them.
@@ -139,7 +141,8 @@ export function synthesize(text, env = process.env) {
139
141
  const txt = join(dir, 'say.txt'), aiff = join(dir, 'say.aiff'), ogg = join(dir, 'say.ogg');
140
142
  await writeFile(txt, text.replace(URL_RE, 'link'));
141
143
  const voice = await sayVoice(env);
142
- await run('say', [...(voice ? ['-v', voice] : []), '-o', aiff, '-r', String(sayRate(env)), '-f', txt]);
144
+ const rate = sayRate(env);
145
+ await run('say', [...(voice ? ['-v', voice] : []), '-o', aiff, ...(rate ? ['-r', String(rate)] : []), '-f', txt]);
143
146
  await run('ffmpeg', ['-y', '-loglevel', 'error', '-protocol_whitelist', 'file', '-i', aiff, '-c:a', 'libopus', '-b:a', '32k', ogg]);
144
147
  return readFile(ogg);
145
148
  });