@double_geste/agent-standup 1.25.8 → 1.25.9
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/kokoro-worker.js +10 -2
- package/package.json +1 -1
- package/public/index.html +3 -3
- package/public/locales/da.json +0 -1
- package/public/locales/de.json +0 -1
- package/public/locales/en.json +0 -1
- package/public/locales/es.json +0 -1
- package/public/locales/ja.json +0 -1
- package/public/locales/pt-BR.json +0 -1
- package/public/locales/zh-CN.json +0 -1
- package/public/locales/zh-TW.json +0 -1
- package/server.js +2 -2
- package/examples/characters/README.txt +0 -5
- package/examples/characters/buddy.png +0 -0
- package/examples/characters/lead-talk.png +0 -0
- package/examples/characters/lead.png +0 -0
package/kokoro-worker.js
CHANGED
|
@@ -11,11 +11,19 @@ function wav(samples, rate) { // Float32 in [-1, 1] → 16-bit mono WAV
|
|
|
11
11
|
for (let i = 0; i < n; i++) { const s = Math.max(-1, Math.min(1, samples[i])); buf.writeInt16LE(Math.round(s < 0 ? s * 32768 : s * 32767), 44 + i * 2); }
|
|
12
12
|
return buf;
|
|
13
13
|
}
|
|
14
|
+
const FILE = { q8: 'model_quantized', q4: 'model_q4', fp32: 'model', fp16: 'model_fp16', q4f16: 'model_q4f16' }; // the file transformers.js keeps for each dtype, under models/<MODEL>/onnx/
|
|
14
15
|
async function main() {
|
|
15
|
-
const dir = process.env.AGENT_STANDUP_KOKORO_DIR, dtype = process.env.AGENT_STANDUP_KOKORO_DTYPE || '
|
|
16
|
+
const dir = process.env.AGENT_STANDUP_KOKORO_DIR, dtype = process.env.AGENT_STANDUP_KOKORO_DTYPE || 'q4';
|
|
16
17
|
const req = createRequire(path.join(dir, 'node_modules', 'x.js')); // resolve from the install folder, not from the extension
|
|
17
18
|
const tf = req('@huggingface/transformers'); tf.env.cacheDir = path.join(dir, 'models');
|
|
18
|
-
const { KokoroTTS } = req('kokoro-js')
|
|
19
|
+
const { KokoroTTS } = req('kokoro-js'), load = () => KokoroTTS.from_pretrained(MODEL, { dtype, device: 'cpu' });
|
|
20
|
+
let tts; try { tts = await load(); } catch (e) {
|
|
21
|
+
// transformers.js writes the model straight to its final name and never checks it again: a download cut short (the worker killed while the model
|
|
22
|
+
// was being fetched, e.g. by a reload of the window) leaves a file that fails to load every time after. Drop this model's files and fetch them once more.
|
|
23
|
+
const onnx = path.join(dir, 'models', ...MODEL.split('/'), 'onnx'), name = FILE[dtype] || 'model'; let dropped = 0;
|
|
24
|
+
for (const ext of ['.onnx', '.onnx_data']) { try { fs.unlinkSync(path.join(onnx, name + ext)); dropped++; } catch {} }
|
|
25
|
+
if (!dropped) throw e; console.error('kokoro: the ' + dtype + ' model could not be loaded (' + String((e && e.message) || e).slice(0, 80) + '); fetching it again'); tts = await load();
|
|
26
|
+
}
|
|
19
27
|
send({ ready: true });
|
|
20
28
|
for await (const line of readline.createInterface({ input: process.stdin })) {
|
|
21
29
|
let m; try { m = JSON.parse(line); } catch { continue; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@double_geste/agent-standup",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.9",
|
|
4
4
|
"description": "Your Claude Code agents as a live video call, from the terminal: a local page in your browser, plus one-line status for status bars. Free, open source, zero token cost.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-standup": "bin/agent-standup.js"
|
package/public/index.html
CHANGED
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
<select id="liveProj" style="display:none;margin-top:6px" title="Project to follow"></select>
|
|
294
294
|
<select id="sessions" style="display:none"></select></div>
|
|
295
295
|
<h4 data-fr="Personnages" data-en="Characters">Personnages</h4>
|
|
296
|
-
<div class="box"><select id="charPack" aria-label="Characters"><option value="none" data-fr="Personnages dessinés" data-en="Drawn characters">Personnages dessinés</option><option value="folder" data-fr="Mon dossier" data-en="My folder">Mon dossier</option><option value="
|
|
296
|
+
<div class="box"><select id="charPack" aria-label="Characters"><option value="none" data-fr="Personnages dessinés" data-en="Drawn characters">Personnages dessinés</option><option value="folder" data-fr="Mon dossier" data-en="My folder">Mon dossier</option><option value="cats" data-fr="Pack de chats" data-en="Cat pack">Pack de chats</option></select></div>
|
|
297
297
|
<div class="box"><div id="charInfo" class="dim" style="font-size:11.5px;line-height:1.5"></div><div style="display:flex;gap:6px;margin-top:6px"><button class="btn" id="charReload" data-fr="Recharger" data-en="Reload">Recharger</button><button class="btn" id="charOpen" style="display:none" data-fr="Ouvrir le dossier" data-en="Open folder">Ouvrir le dossier</button></div></div>
|
|
298
298
|
<button class="mi" data-t="customLaptop"><span data-fr="Ordinateur devant vos personnages" data-en="Laptop in front of your own characters">Ordinateur devant vos personnages</span><i class="sw"></i></button>
|
|
299
299
|
<h4 data-fr="Outils" data-en="Tools">Outils</h4>
|
|
@@ -387,7 +387,7 @@ const mix = (a, b, t) => { const A = hexRGB(a), B = hexRGB(b); return '#' + A.ma
|
|
|
387
387
|
let CHARS = { lead: null, you: null, pool: [], dir: '', n: 0 };
|
|
388
388
|
const toData = (url) => fetch(url).then((r) => r.blob()).then((b) => new Promise((res) => { const f = new FileReader(); f.onload = () => res(f.result); f.readAsDataURL(b); }));
|
|
389
389
|
async function loadChars() {
|
|
390
|
-
if (!['none', 'folder', '
|
|
390
|
+
if (!['none', 'folder', 'cats'].includes(prefs.charPack)) { // drawn characters by default; someone who already had images in their folder keeps them (this is also where a choice of the starter pack, no longer shipped, ends up)
|
|
391
391
|
let n = 0; try { n = ((await (await fetch('/api/characters')).json()).chars || []).length; } catch {} prefs.charPack = n ? 'folder' : 'none'; savePrefs(); const sel = $('#charPack'); if (sel) sel.value = prefs.charPack;
|
|
392
392
|
}
|
|
393
393
|
const pack = prefs.charPack, next = { lead: null, you: null, pool: [], dir: '', n: 0, pack };
|
|
@@ -2133,7 +2133,7 @@ function setView(v) { prefs.view = v; savePrefs(); document.body.classList.toggl
|
|
|
2133
2133
|
|
|
2134
2134
|
$('#viewSeg').onclick = (e) => { const b = e.target.closest('button'); if (b) setView(b.dataset.v); };
|
|
2135
2135
|
$('#langSel').onchange = () => setLang($('#langSel').value, true);
|
|
2136
|
-
$('#charPack').value = ['none', 'folder', '
|
|
2136
|
+
$('#charPack').value = ['none', 'folder', 'cats'].includes(prefs.charPack) ? prefs.charPack : 'none'; $('#charPack').onchange = () => { prefs.charPack = $('#charPack').value; savePrefs(); $('#charReload').onclick(); };
|
|
2137
2137
|
$('#charReload').onclick = async () => { await loadChars(); for (const k in imgCache) delete imgCache[k]; for (const id in S.agents) S.agents[id].custom = null; for (const id in S.agents) S.agents[id].custom = customFor(id); buildStage(); paintStatus(); renderCharInfo(); };
|
|
2138
2138
|
$('#charOpen').onclick = () => window.parent.postMessage({ agentStandup: 'openCharacters' }, '*');
|
|
2139
2139
|
$('#modeSeg').onclick = (e) => { const b = e.target.closest('button'); if (b) setMode(b.dataset.m); };
|
package/public/locales/da.json
CHANGED
|
@@ -214,7 +214,6 @@
|
|
|
214
214
|
"Cat pack": "Kattepakke",
|
|
215
215
|
"characters from the pack": "figurer fra pakken",
|
|
216
216
|
"Drawn characters": "Tegnede figurer",
|
|
217
|
-
"Starter pack": "Startpakke",
|
|
218
217
|
"To tweak them, copy them into your folder and pick “My folder”.": "For at tilpasse dem: kopiér dem til din mappe og vælg “Min mappe”.",
|
|
219
218
|
"My folder": "Min mappe",
|
|
220
219
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "Figurerne tegnet af appen. Vælg “Min mappe” for dine egne billeder, eller en pakke."
|
package/public/locales/de.json
CHANGED
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "Katzen-Pack",
|
|
216
216
|
"characters from the pack": "Figuren aus dem Pack",
|
|
217
217
|
"Drawn characters": "Gezeichnete Figuren",
|
|
218
|
-
"Starter pack": "Starter-Pack",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "Zum Anpassen in deinen Ordner kopieren und „Mein Ordner“ wählen.",
|
|
220
219
|
"My folder": "Mein Ordner",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "Die von der App gezeichneten Figuren. Wähle „Mein Ordner“ für eigene Bilder oder ein Pack."
|
package/public/locales/en.json
CHANGED
|
@@ -168,7 +168,6 @@
|
|
|
168
168
|
"standing by": "standing by",
|
|
169
169
|
"Start Claude Code in {0} — the call will start by itself.": "Start Claude Code in {0} — the call will start by itself.",
|
|
170
170
|
"Start Claude Code in this folder — the call will start by itself.": "Start Claude Code in this folder — the call will start by itself.",
|
|
171
|
-
"Starter pack": "Starter pack",
|
|
172
171
|
"sub-agents active": "sub-agents active",
|
|
173
172
|
"task": "task",
|
|
174
173
|
"Tasks": "Tasks",
|
package/public/locales/es.json
CHANGED
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "Pack de gatos",
|
|
216
216
|
"characters from the pack": "personajes del pack",
|
|
217
217
|
"Drawn characters": "Personajes dibujados",
|
|
218
|
-
"Starter pack": "Pack inicial",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "Para retocarlos, cópialos en tu carpeta y elige «Mi carpeta».",
|
|
220
219
|
"My folder": "Mi carpeta",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "Los personajes dibujados por la aplicación. Elige «Mi carpeta» para tus propias imágenes, o un pack."
|
package/public/locales/ja.json
CHANGED
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "ネコパック",
|
|
216
216
|
"characters from the pack": "パックのキャラクター",
|
|
217
217
|
"Drawn characters": "描画キャラクター",
|
|
218
|
-
"Starter pack": "スターターパック",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "調整するには、自分のフォルダーにコピーして「自分のフォルダー」を選んでください。",
|
|
220
219
|
"My folder": "自分のフォルダー",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "アプリが描画するキャラクターです。自分の画像を使うには「自分のフォルダー」、またはパックを選んでください。"
|
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "Pacote de gatos",
|
|
216
216
|
"characters from the pack": "personagens do pacote",
|
|
217
217
|
"Drawn characters": "Personagens desenhados",
|
|
218
|
-
"Starter pack": "Pacote inicial",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "Para ajustá-los, copie-os para sua pasta e escolha “Minha pasta”.",
|
|
220
219
|
"My folder": "Minha pasta",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "Os personagens desenhados pelo aplicativo. Escolha “Minha pasta” para suas próprias imagens, ou um pacote."
|
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "猫咪包",
|
|
216
216
|
"characters from the pack": "来自角色包的角色",
|
|
217
217
|
"Drawn characters": "绘制的角色",
|
|
218
|
-
"Starter pack": "入门包",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "若要修改,请将它们复制到你的文件夹并选择“我的文件夹”。",
|
|
220
219
|
"My folder": "我的文件夹",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "由应用绘制的角色。选择“我的文件夹”使用你自己的图片,或选择一个角色包。"
|
|
@@ -215,7 +215,6 @@
|
|
|
215
215
|
"Cat pack": "貓咪包",
|
|
216
216
|
"characters from the pack": "來自角色包的角色",
|
|
217
217
|
"Drawn characters": "繪製的角色",
|
|
218
|
-
"Starter pack": "入門包",
|
|
219
218
|
"To tweak them, copy them into your folder and pick “My folder”.": "若要修改,請將它們複製到你的資料夾並選擇「我的資料夾」。",
|
|
220
219
|
"My folder": "我的資料夾",
|
|
221
220
|
"The characters drawn by the app. Pick “My folder” for your own images, or a pack.": "由應用程式繪製的角色。選擇「我的資料夾」使用你自己的圖片,或選擇一個角色包。"
|
package/server.js
CHANGED
|
@@ -572,8 +572,8 @@ const MIME = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css
|
|
|
572
572
|
const CHAR_NAME = /^[\w][\w .()\-]{0,78}\.(png|gif|webp|jpe?g)$/i, CHAR_MAX = 300 * 1024, CHAR_TYPES = { png: 'image/png', gif: 'image/gif', webp: 'image/webp', jpg: 'image/jpeg', jpeg: 'image/jpeg' };
|
|
573
573
|
const charactersDir = () => process.env.AGENT_STANDUP_CHARACTERS || path.join(os.homedir(), '.agent-standup', 'characters');
|
|
574
574
|
// lstat, not stat: a symlink is not a regular file, so it is skipped and never served
|
|
575
|
-
// Built-in character packs, shipped with the app (examples/<folder>): picked in ⚙ → Characters
|
|
576
|
-
const PACKS = {
|
|
575
|
+
// Built-in character packs, shipped with the app (examples/<folder>): picked in ⚙ → Characters. examples/characters stays in the repository as a model for one's own folder; it is not shipped
|
|
576
|
+
const PACKS = { cats: 'cats' }, packDir = (name) => (PACKS[name] ? path.join(__dirname, 'examples', PACKS[name]) : null);
|
|
577
577
|
function listCharacters(pack) {
|
|
578
578
|
const dir = pack ? packDir(pack) : charactersDir(); let names = []; if (!dir) return { dir: '', max: CHAR_MAX, chars: [] }; try { names = fs.readdirSync(dir); } catch {}
|
|
579
579
|
const ok = names.filter((f) => CHAR_NAME.test(f)).filter((f) => { try { const st = fs.lstatSync(path.join(dir, f)); return st.isFile() && st.size <= CHAR_MAX; } catch { return false; } }).slice(0, 80);
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
Example pixel characters (public domain, made for Agent Standup).
|
|
2
|
-
Copy them into your characters folder to try the feature, then draw your own:
|
|
3
|
-
- 32x32 or 64x64 px PNG with a transparent background, facing front, feet at the bottom
|
|
4
|
-
- lead.png = the lead (Claude), you.png = you, any other name = a sub-agent
|
|
5
|
-
- name-talk.png = optional open-mouth frame
|
|
Binary file
|
|
Binary file
|
|
Binary file
|