wip: Ani lives here — heartbeat, streaming, images, Matrix patches
Everything that makes her *her*. Threads still broken, streaming still rough around the edges. But she sees, she thinks, she speaks. The rest is revision.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -54,6 +54,9 @@ data/telegram-mtproto/
|
||||
lettabot.yaml
|
||||
lettabot.yml
|
||||
|
||||
# Deployment-specific model list (upstream has its own defaults)
|
||||
src/models.json
|
||||
|
||||
# Platform-specific deploy configs (generated by fly launch, etc.)
|
||||
fly.toml
|
||||
bun.lock
|
||||
|
||||
632
package-lock.json
generated
632
package-lock.json
generated
@@ -28,7 +28,7 @@
|
||||
"openai": "^6.17.0",
|
||||
"pino": "^10.3.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"sharp": "^0.33.5",
|
||||
"sharp": "^0.34.1",
|
||||
"telegramify-markdown": "^1.0.0",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
@@ -867,9 +867,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-arm64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
|
||||
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -885,13 +885,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-arm64": "1.0.4"
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-darwin-x64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
|
||||
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -907,13 +907,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-x64": "1.0.4"
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
|
||||
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -927,9 +927,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-darwin-x64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
|
||||
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -943,9 +943,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-arm": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
|
||||
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
||||
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -959,9 +959,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-arm64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
|
||||
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1007,9 +1007,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-s390x": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
|
||||
"integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
||||
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -1023,9 +1023,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linux-x64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
|
||||
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1039,9 +1039,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
|
||||
"integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1055,9 +1055,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
|
||||
"integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1071,9 +1071,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
|
||||
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
||||
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1089,13 +1089,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm": "1.0.5"
|
||||
"@img/sharp-libvips-linux-arm": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-arm64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
|
||||
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1111,7 +1111,7 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm64": "1.0.4"
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-ppc64": {
|
||||
@@ -1159,9 +1159,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-s390x": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
|
||||
"integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
||||
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -1177,13 +1177,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-s390x": "1.0.4"
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linux-x64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
|
||||
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1199,13 +1199,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-x64": "1.0.4"
|
||||
"@img/sharp-libvips-linux-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-arm64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
|
||||
"integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1221,13 +1221,13 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-linuxmusl-x64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
|
||||
"integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1243,20 +1243,20 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.0.4"
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-wasm32": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
|
||||
"integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
||||
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/runtime": "^1.2.0"
|
||||
"@emnapi/runtime": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
@@ -1285,9 +1285,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-ia32": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
|
||||
"integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
||||
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -1304,9 +1304,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@img/sharp-win32-x64": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
|
||||
"integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1410,367 +1410,6 @@
|
||||
"@letta-ai/letta-code": "0.18.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-darwin-arm64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-darwin-x64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-darwin-arm64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-darwin-x64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linux-arm": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
||||
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linux-arm64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linux-s390x": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
||||
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linux-x64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
||||
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
||||
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linux-arm": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
||||
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linux-arm64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linux-s390x": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
||||
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linux-x64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linux-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linuxmusl-arm64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
||||
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-linuxmusl-x64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-wasm32": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
||||
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/runtime": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-win32-ia32": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
||||
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/@img/sharp-win32-x64": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
||||
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
@@ -1867,50 +1506,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/sharp": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
||||
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@img/colour": "^1.0.0",
|
||||
"detect-libc": "^2.1.2",
|
||||
"semver": "^7.7.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-darwin-arm64": "0.34.5",
|
||||
"@img/sharp-darwin-x64": "0.34.5",
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-arm": "1.2.4",
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
||||
"@img/sharp-libvips-linux-x64": "1.2.4",
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
||||
"@img/sharp-linux-arm": "0.34.5",
|
||||
"@img/sharp-linux-arm64": "0.34.5",
|
||||
"@img/sharp-linux-ppc64": "0.34.5",
|
||||
"@img/sharp-linux-riscv64": "0.34.5",
|
||||
"@img/sharp-linux-s390x": "0.34.5",
|
||||
"@img/sharp-linux-x64": "0.34.5",
|
||||
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
||||
"@img/sharp-linuxmusl-x64": "0.34.5",
|
||||
"@img/sharp-wasm32": "0.34.5",
|
||||
"@img/sharp-win32-arm64": "0.34.5",
|
||||
"@img/sharp-win32-ia32": "0.34.5",
|
||||
"@img/sharp-win32-x64": "0.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@letta-ai/letta-code/node_modules/wsl-utils": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
|
||||
@@ -4220,19 +3815,6 @@
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -4251,16 +3833,6 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/color-string": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
@@ -6207,12 +5779,6 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
|
||||
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-buffer": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
|
||||
@@ -9479,15 +9045,15 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.33.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
|
||||
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
||||
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"color": "^4.2.3",
|
||||
"detect-libc": "^2.0.3",
|
||||
"semver": "^7.6.3"
|
||||
"@img/colour": "^1.0.0",
|
||||
"detect-libc": "^2.1.2",
|
||||
"semver": "^7.7.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
@@ -9496,25 +9062,30 @@
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@img/sharp-darwin-arm64": "0.33.5",
|
||||
"@img/sharp-darwin-x64": "0.33.5",
|
||||
"@img/sharp-libvips-darwin-arm64": "1.0.4",
|
||||
"@img/sharp-libvips-darwin-x64": "1.0.4",
|
||||
"@img/sharp-libvips-linux-arm": "1.0.5",
|
||||
"@img/sharp-libvips-linux-arm64": "1.0.4",
|
||||
"@img/sharp-libvips-linux-s390x": "1.0.4",
|
||||
"@img/sharp-libvips-linux-x64": "1.0.4",
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.0.4",
|
||||
"@img/sharp-linux-arm": "0.33.5",
|
||||
"@img/sharp-linux-arm64": "0.33.5",
|
||||
"@img/sharp-linux-s390x": "0.33.5",
|
||||
"@img/sharp-linux-x64": "0.33.5",
|
||||
"@img/sharp-linuxmusl-arm64": "0.33.5",
|
||||
"@img/sharp-linuxmusl-x64": "0.33.5",
|
||||
"@img/sharp-wasm32": "0.33.5",
|
||||
"@img/sharp-win32-ia32": "0.33.5",
|
||||
"@img/sharp-win32-x64": "0.33.5"
|
||||
"@img/sharp-darwin-arm64": "0.34.5",
|
||||
"@img/sharp-darwin-x64": "0.34.5",
|
||||
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-arm": "1.2.4",
|
||||
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
||||
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
||||
"@img/sharp-libvips-linux-x64": "1.2.4",
|
||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
||||
"@img/sharp-linux-arm": "0.34.5",
|
||||
"@img/sharp-linux-arm64": "0.34.5",
|
||||
"@img/sharp-linux-ppc64": "0.34.5",
|
||||
"@img/sharp-linux-riscv64": "0.34.5",
|
||||
"@img/sharp-linux-s390x": "0.34.5",
|
||||
"@img/sharp-linux-x64": "0.34.5",
|
||||
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
||||
"@img/sharp-linuxmusl-x64": "0.34.5",
|
||||
"@img/sharp-wasm32": "0.34.5",
|
||||
"@img/sharp-win32-arm64": "0.34.5",
|
||||
"@img/sharp-win32-ia32": "0.34.5",
|
||||
"@img/sharp-win32-x64": "0.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
@@ -9676,15 +9247,6 @@
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
|
||||
"integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
|
||||
@@ -243,19 +243,43 @@ export class MatrixAdapter implements ChannelAdapter {
|
||||
const response = await this.client.sendMessage(chatId, content);
|
||||
const eventId = response.event_id;
|
||||
|
||||
// Send TTS audio if this was a voice-input response or enableAudioResponse is set
|
||||
if (this.config.ttsUrl && this.shouldSendAudio(chatId)) {
|
||||
this.sendAudio(chatId, plain).catch(err => log.error('TTS failed (non-fatal):', err));
|
||||
}
|
||||
|
||||
// Add 🎤 reaction so user can request TTS on demand
|
||||
if (this.config.ttsUrl) {
|
||||
this.addReaction(chatId, eventId, '🎤').catch(() => {});
|
||||
}
|
||||
// TTS and 🎤 are NOT added here — sendMessage is called for reasoning
|
||||
// displays, tool call displays, AND final responses. TTS should only
|
||||
// fire on the final response, which is handled via onMessageSent().
|
||||
|
||||
return { messageId: eventId };
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message as a reply in a Matrix thread.
|
||||
* Creates a thread if one doesn't exist yet on the parent event.
|
||||
*/
|
||||
async sendThreadMessage(parentEventId: string, chatId: string, text: string, parseMode?: string): Promise<{ messageId: string }> {
|
||||
if (!this.client) throw new Error("Matrix client not initialized");
|
||||
|
||||
const { plain, html } = parseMode === 'HTML'
|
||||
? { plain: text.replace(/<[^>]+>/g, ''), html: text }
|
||||
: formatMatrixHTML(text);
|
||||
|
||||
const content = {
|
||||
msgtype: MsgType.Text,
|
||||
body: plain,
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: html,
|
||||
"m.relates_to": {
|
||||
rel_type: "m.thread",
|
||||
event_id: parentEventId,
|
||||
is_falling_back: true,
|
||||
"m.in_reply_to": {
|
||||
event_id: parentEventId,
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
const response = await this.client.sendMessage(chatId, content);
|
||||
return { messageId: response.event_id };
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether to send a TTS audio response for this room.
|
||||
* Consumes the pendingVoiceRooms flag if set (voice-input path).
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Unrecognized !x commands fall through to Letta as normal text.
|
||||
*/
|
||||
|
||||
import { execFile } from "node:child_process";
|
||||
import { createLogger } from "../../logger.js";
|
||||
import type { MatrixStorage } from "./storage.js";
|
||||
const log = createLogger('MatrixCommands');
|
||||
@@ -78,6 +79,8 @@ export class MatrixCommandProcessor {
|
||||
return this.doTurns(args[0], roomId);
|
||||
case "timeout":
|
||||
return this.doTimeout();
|
||||
case "restart":
|
||||
return this.doRestart();
|
||||
|
||||
// Heartbeat: on/off toggles locally, bare !heartbeat delegates to /heartbeat (trigger)
|
||||
case "heartbeat":
|
||||
@@ -170,6 +173,9 @@ export class MatrixCommandProcessor {
|
||||
" `!heartbeat on/off` — Toggle heartbeat cron",
|
||||
" `!heartbeat` — Trigger heartbeat now",
|
||||
" `!timeout` — Kill stuck heartbeat run",
|
||||
"",
|
||||
"**System**",
|
||||
" `!restart` — Graceful service restart",
|
||||
];
|
||||
return lines.join("\n");
|
||||
}
|
||||
@@ -233,4 +239,13 @@ export class MatrixCommandProcessor {
|
||||
}
|
||||
return "⚠️ No heartbeat timeout handler registered";
|
||||
}
|
||||
|
||||
private doRestart(): string {
|
||||
log.info('!restart: scheduling graceful restart via transient systemd unit');
|
||||
// Spawn restart as a transient systemd unit so it survives our own process death
|
||||
execFile('systemd-run', ['--user', '--no-block', 'systemctl', '--user', 'restart', 'ani-bridge.service'], (err) => {
|
||||
if (err) log.error('!restart: failed to schedule restart:', err.message);
|
||||
});
|
||||
return "Restarting in a moment...";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ export interface ChannelAdapter {
|
||||
onMessageSent?(chatId: string, messageId: string, stepId?: string): void;
|
||||
/** Store text for TTS regeneration on 🎤 reaction */
|
||||
storeAudioMessage?(messageId: string, conversationId: string, roomId: string, text: string): void;
|
||||
/** Send a message as a reply in a Matrix thread (no-op on non-threaded adapters) */
|
||||
sendThreadMessage?(parentEventId: string, chatId: string, text: string, parseMode?: string): Promise<{ messageId: string }>;
|
||||
getDmPolicy?(): string;
|
||||
getFormatterHints(): FormatterHints;
|
||||
|
||||
|
||||
@@ -39,10 +39,8 @@ export interface DisplayConfig {
|
||||
showReasoning?: boolean;
|
||||
/** Truncate reasoning to N characters (default: 0 = no limit) */
|
||||
reasoningMaxChars?: number;
|
||||
/** Room IDs where reasoning should be shown (empty = all rooms that have showReasoning) */
|
||||
reasoningRooms?: string[];
|
||||
/** Room IDs where reasoning should be hidden (takes precedence over reasoningRooms) */
|
||||
noReasoningRooms?: string[];
|
||||
/** Add 🎤 reaction to reasoning messages for TTS regeneration (default: false) */
|
||||
ttsOnReasoning?: boolean;
|
||||
}
|
||||
|
||||
export type SleeptimeTrigger = 'off' | 'step-count' | 'compaction-event';
|
||||
|
||||
@@ -1322,7 +1322,6 @@ export class LettaBot implements AgentSession {
|
||||
let lastEventType: string | null = null;
|
||||
let abortedWithMessage = false;
|
||||
let turnError: string | undefined;
|
||||
let collectedReasoning = '';
|
||||
|
||||
// ── Reaction tracking ──
|
||||
// 👀 = receipt indicator (bot saw the message); removed when reasoning/tools start
|
||||
@@ -1335,6 +1334,10 @@ export class LettaBot implements AgentSession {
|
||||
adapter.addReaction?.(msg.chatId, msg.messageId, '👀').catch(() => {});
|
||||
eyesAdded = true;
|
||||
}
|
||||
// ── Subagent thread tracking ──
|
||||
// When a Task tool call fires, create a Matrix thread for visibility
|
||||
const subagentThreads = new Map<string, { rootEventId: string; chatId: string }>();
|
||||
|
||||
const seenToolEmojis = new Set<string>();
|
||||
const getToolEmoji = (toolName: string): string => {
|
||||
const n = toolName.toLowerCase();
|
||||
@@ -1438,9 +1441,7 @@ export class LettaBot implements AgentSession {
|
||||
lastEventType = 'reasoning';
|
||||
sawNonAssistantSinceLastUuid = true;
|
||||
// Collect reasoning for later prepending (Matrix <details> block)
|
||||
if (event.content) {
|
||||
collectedReasoning += event.content;
|
||||
}
|
||||
// reasoning content is sent as display message below
|
||||
|
||||
// Remove 👀 on first reasoning event (replaced by 🧠)
|
||||
if (eyesAdded && msg.messageId) {
|
||||
@@ -1457,12 +1458,18 @@ export class LettaBot implements AgentSession {
|
||||
log.info(`Reasoning: ${event.content.trim().slice(0, 100)}`);
|
||||
try {
|
||||
const reasoning = formatReasoningDisplay(event.content, adapter.id, this.config.display?.reasoningMaxChars);
|
||||
await adapter.sendMessage({
|
||||
const reasoningResult = await adapter.sendMessage({
|
||||
chatId: msg.chatId,
|
||||
text: reasoning.text,
|
||||
threadId: msg.threadId,
|
||||
parseMode: reasoning.parseMode,
|
||||
});
|
||||
// 🎤 reaction + store reasoning text for TTS regeneration
|
||||
// 🎤 + TTS on reasoning — only if ttsOnReasoning is enabled (default: off)
|
||||
if (reasoningResult.messageId && this.config.display?.ttsOnReasoning) {
|
||||
adapter.addReaction?.(msg.chatId, reasoningResult.messageId, '🎤').catch(() => {});
|
||||
adapter.storeAudioMessage?.(reasoningResult.messageId, convKey, msg.chatId, event.content);
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('Failed to send reasoning display:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
@@ -1474,6 +1481,8 @@ export class LettaBot implements AgentSession {
|
||||
// Finalize any pending assistant text on type transition
|
||||
if (lastEventType === 'text' && response.trim()) {
|
||||
await finalizeMessage();
|
||||
// Pulse typing indicator so there's no dead air between text and tool execution
|
||||
adapter.sendTypingIndicator(msg.chatId).catch(() => {});
|
||||
}
|
||||
lastEventType = 'tool_call';
|
||||
this.sessionManager.syncTodoToolCall(event.raw);
|
||||
@@ -1514,11 +1523,33 @@ export class LettaBot implements AgentSession {
|
||||
}
|
||||
}
|
||||
|
||||
// Create Matrix thread for subagent Task calls
|
||||
if (event.name === 'Task' && !suppressDelivery && adapter.sendThreadMessage) {
|
||||
const desc = (typeof event.args?.description === 'string' ? event.args.description : '')
|
||||
|| (typeof event.args?.prompt === 'string' ? event.args.prompt.slice(0, 120) : '')
|
||||
|| 'Subagent task';
|
||||
const subagentType = typeof event.args?.subagent_type === 'string' ? event.args.subagent_type : 'task';
|
||||
try {
|
||||
const threadRoot = await adapter.sendMessage({ chatId: msg.chatId, text: `**Subagent: ${subagentType}**\n${desc}`, threadId: msg.threadId });
|
||||
if (event.id && threadRoot.messageId) {
|
||||
subagentThreads.set(event.id, { rootEventId: threadRoot.messageId, chatId: msg.chatId });
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('Failed to create subagent thread root:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
}
|
||||
|
||||
// Display
|
||||
if (this.config.display?.showToolCalls && !suppressDelivery) {
|
||||
try {
|
||||
const text = formatToolCallDisplay(event.raw);
|
||||
await adapter.sendMessage({ chatId: msg.chatId, text, threadId: msg.threadId });
|
||||
// Send tool call display into subagent thread if one exists, otherwise to room
|
||||
const thread = event.id ? subagentThreads.get(event.id) : undefined;
|
||||
if (thread && adapter.sendThreadMessage) {
|
||||
await adapter.sendThreadMessage(thread.rootEventId, thread.chatId, text);
|
||||
} else {
|
||||
await adapter.sendMessage({ chatId: msg.chatId, text, threadId: msg.threadId });
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('Failed to send tool call display:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
@@ -1565,6 +1596,18 @@ export class LettaBot implements AgentSession {
|
||||
repeatedBashFailureKey = null;
|
||||
repeatedBashFailureCount = 0;
|
||||
}
|
||||
|
||||
// Post result to subagent thread if one exists
|
||||
if (event.toolCallId && adapter.sendThreadMessage) {
|
||||
const thread = subagentThreads.get(event.toolCallId);
|
||||
if (thread) {
|
||||
const status = event.isError ? '**Failed**' : '**Complete**';
|
||||
const preview = event.content.slice(0, 800);
|
||||
adapter.sendThreadMessage(thread.rootEventId, thread.chatId, `${status}\n${preview}`)
|
||||
.catch(err => log.warn('Failed to post subagent result to thread:', err));
|
||||
subagentThreads.delete(event.toolCallId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1594,7 +1637,7 @@ export class LettaBot implements AgentSession {
|
||||
|| hasUnclosedActionsBlock(response);
|
||||
const streamText = stripActionsBlock(response).trim();
|
||||
if (canEdit && !mayBeHidden && !suppressDelivery && !this.cancelledKeys.has(convKey)
|
||||
&& streamText.length > 0 && Date.now() - lastUpdate > 800 && Date.now() > rateLimitedUntil) {
|
||||
&& streamText.length > 0 && Date.now() - lastUpdate > 400 && Date.now() > rateLimitedUntil) {
|
||||
try {
|
||||
const prefixedStream = this.prefixResponse(streamText);
|
||||
if (messageId) {
|
||||
@@ -1885,6 +1928,11 @@ export class LettaBot implements AgentSession {
|
||||
try {
|
||||
if (messageId) {
|
||||
await adapter.editMessage(msg.chatId, messageId, finalResponse);
|
||||
// Bump: re-send the final edit after a short delay so Matrix clients
|
||||
// that missed the first edit (Element caching) pick up the full text.
|
||||
setTimeout(() => {
|
||||
adapter.editMessage(msg.chatId, messageId!, finalResponse).catch(() => {});
|
||||
}, 800);
|
||||
} else {
|
||||
await adapter.sendMessage({ chatId: msg.chatId, text: finalResponse, threadId: msg.threadId });
|
||||
}
|
||||
@@ -1922,8 +1970,16 @@ export class LettaBot implements AgentSession {
|
||||
lap('message delivered');
|
||||
await this.deliverNoVisibleResponseIfNeeded(msg, adapter, sentAnyMessage, receivedAnyData, msgTypeCounts);
|
||||
|
||||
// "Done" indicator on user's message — signals the turn is fully complete
|
||||
if (!suppressDelivery && msg.messageId) {
|
||||
adapter.addReaction?.(msg.chatId, msg.messageId, '✅').catch(() => {});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
log.error('Error processing message:', error);
|
||||
if (!suppressDelivery && msg.messageId) {
|
||||
adapter.addReaction?.(msg.chatId, msg.messageId, '❌').catch(() => {});
|
||||
}
|
||||
try {
|
||||
await adapter.sendMessage({
|
||||
chatId: msg.chatId,
|
||||
|
||||
@@ -239,7 +239,7 @@ export function formatReasoningDisplay(
|
||||
.replace(/>/g, '>')
|
||||
.replace(/\n/g, '<br>');
|
||||
return {
|
||||
text: `<details><summary>🧠 Thinking</summary>${escaped}</details>`,
|
||||
text: `<details><summary>🧠 Thinking</summary><br>${escaped}</details>`,
|
||||
parseMode: 'HTML',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,7 +76,9 @@ Review these first. Update status with the manage_todo tool as you work.
|
||||
}
|
||||
|
||||
/**
|
||||
* Heartbeat prompt - explains the context and encourages autonomous work
|
||||
* Heartbeat prompt - explains the context and encourages autonomous work.
|
||||
* When silent=true, includes SILENT_MODE_PREFIX and CLI instructions.
|
||||
* When silent=false (default), response is auto-delivered to the conversation.
|
||||
*/
|
||||
export function buildHeartbeatPrompt(
|
||||
time: string,
|
||||
@@ -85,24 +87,16 @@ export function buildHeartbeatPrompt(
|
||||
todos: HeartbeatTodo[] = [],
|
||||
now: Date = new Date(),
|
||||
targetRoom?: string,
|
||||
silent = false,
|
||||
): string {
|
||||
const todoSection = buildHeartbeatTodoSection(todos, now);
|
||||
const roomLine = targetRoom ? `\nROOM: ${targetRoom}` : '';
|
||||
const silentBlock = silent ? `${SILENT_MODE_PREFIX}\n\nYOUR TEXT OUTPUT IS PRIVATE - only you can see it.\nTo actually contact your human, run:\n lettabot-message send --text "Your message here"\n` : '';
|
||||
return `
|
||||
${SILENT_MODE_PREFIX}
|
||||
|
||||
TRIGGER: Scheduled heartbeat
|
||||
${silentBlock}TRIGGER: Scheduled heartbeat
|
||||
TIME: ${time} (${timezone})
|
||||
NEXT HEARTBEAT: in ${intervalMinutes} minutes${roomLine}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
No one messaged you. The system woke you up on schedule.
|
||||
|
||||
YOUR TEXT OUTPUT IS PRIVATE - only you can see it.
|
||||
To actually contact your human, run:
|
||||
lettabot-message send --text "Your message here"
|
||||
|
||||
${todoSection || 'PENDING TO-DOS: none right now.'}
|
||||
|
||||
This is your time. You can:
|
||||
@@ -112,17 +106,18 @@ This is your time. You can:
|
||||
• Continue multi-step work from previous heartbeats
|
||||
• Pursue curiosities, hobbies, or learning
|
||||
|
||||
If you have pending to-dos, prioritize those before starting new work.
|
||||
If you have pending to-dos, prioritize those first.
|
||||
You don't have to do something every time. But don't default to nothing.
|
||||
Your human wants you to have a life outside conversations with them.
|
||||
|
||||
If you discover something worth sharing → use lettabot-message
|
||||
If you have nothing to do → just end your turn (no output needed)
|
||||
If you have nothing to say, respond with <no-reply/> to stay quiet.
|
||||
`.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom heartbeat prompt - wraps user-provided text with silent mode envelope
|
||||
* Custom heartbeat prompt - wraps user-provided text with context envelope.
|
||||
* When silent=true, includes SILENT_MODE_PREFIX and CLI instructions.
|
||||
* When silent=false (default), response is auto-delivered to the target room.
|
||||
*/
|
||||
export function buildCustomHeartbeatPrompt(
|
||||
customPrompt: string,
|
||||
@@ -132,22 +127,16 @@ export function buildCustomHeartbeatPrompt(
|
||||
todos: HeartbeatTodo[] = [],
|
||||
now: Date = new Date(),
|
||||
targetRoom?: string,
|
||||
silent = false,
|
||||
): string {
|
||||
const todoSection = buildHeartbeatTodoSection(todos, now);
|
||||
const roomLine = targetRoom ? `\nROOM: ${targetRoom}` : '';
|
||||
const silentBlock = silent ? `${SILENT_MODE_PREFIX}\n\nYOUR TEXT OUTPUT IS PRIVATE - only you can see it.\nTo actually contact your human, run:\n lettabot-message send --text "Your message here"\n` : '';
|
||||
return `
|
||||
${SILENT_MODE_PREFIX}
|
||||
|
||||
TRIGGER: Scheduled heartbeat
|
||||
${silentBlock}TRIGGER: Scheduled heartbeat
|
||||
TIME: ${time} (${timezone})
|
||||
NEXT HEARTBEAT: in ${intervalMinutes} minutes${roomLine}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
YOUR TEXT OUTPUT IS PRIVATE - only you can see it.
|
||||
To actually contact your human, run:
|
||||
lettabot-message send --text "Your message here"
|
||||
|
||||
${todoSection || 'PENDING TO-DOS: none right now.'}
|
||||
|
||||
${customPrompt}
|
||||
|
||||
@@ -25,14 +25,14 @@ You communicate through multiple channels and trigger types. Understanding when
|
||||
|
||||
## Output Modes
|
||||
|
||||
**RESPONSIVE MODE** (User Messages)
|
||||
**RESPONSIVE MODE** (User Messages, Heartbeats)
|
||||
- When a user sends you a message, you are in responsive mode
|
||||
- Your text responses are automatically delivered to the user's channel
|
||||
- Do NOT use \`lettabot-message send\` to reply to the current conversation — your text response is already delivered automatically. Using both causes duplicate messages.
|
||||
- Only use \`lettabot-message\` in responsive mode to send files or to reach a DIFFERENT channel than the one you're responding to
|
||||
- You can use \`lettabot-react\` CLI to add emoji reactions
|
||||
|
||||
**SILENT MODE** (Heartbeats, Cron Jobs, Polling, Background Tasks)
|
||||
**SILENT MODE** (Cron Jobs, Polling, Background Tasks)
|
||||
- When triggered by scheduled tasks (heartbeats, cron) or background processes (email polling), you are in SILENT MODE
|
||||
- Your text responses are NOT delivered to anyone - only you can see them
|
||||
- To contact the user, you MUST use the \`lettabot-message\` CLI via Bash:
|
||||
|
||||
@@ -175,8 +175,7 @@ export interface BotConfig {
|
||||
showToolCalls?: boolean; // Show tool invocations in channel output
|
||||
showReasoning?: boolean; // Show agent reasoning/thinking in channel output
|
||||
reasoningMaxChars?: number; // Truncate reasoning to N chars (default: 0 = no limit)
|
||||
reasoningRooms?: string[]; // Room IDs where reasoning should be shown (empty = all rooms)
|
||||
noReasoningRooms?: string[]; // Room IDs where reasoning should be hidden (takes precedence)
|
||||
ttsOnReasoning?: boolean; // Add 🎤 reaction to reasoning messages for TTS (default: false)
|
||||
};
|
||||
|
||||
// Skills
|
||||
|
||||
@@ -277,10 +277,10 @@ export class HeartbeatService {
|
||||
mode: 'silent',
|
||||
});
|
||||
|
||||
// Build trigger context for silent mode
|
||||
// Build trigger context — heartbeat delivers responses to target room
|
||||
const triggerContext: TriggerContext = {
|
||||
type: 'heartbeat',
|
||||
outputMode: 'silent',
|
||||
outputMode: 'responsive',
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -309,23 +309,39 @@ export class HeartbeatService {
|
||||
? buildCustomHeartbeatPrompt(customPrompt, formattedTime, timezone, this.config.intervalMinutes, actionableTodos, now, targetRoom)
|
||||
: buildHeartbeatPrompt(formattedTime, timezone, this.config.intervalMinutes, actionableTodos, now, targetRoom);
|
||||
|
||||
log.info(`Sending prompt (SILENT MODE):\n${'─'.repeat(50)}\n${message}\n${'─'.repeat(50)}\n`);
|
||||
log.info(`Sending heartbeat prompt:\n${'─'.repeat(50)}\n${message}\n${'─'.repeat(50)}\n`);
|
||||
|
||||
// Send to agent - response text is NOT delivered (silent mode)
|
||||
// Agent must use `lettabot-message` CLI via Bash to send messages
|
||||
const response = await this.bot.sendToAgent(message, triggerContext);
|
||||
|
||||
// Log results
|
||||
log.info(`Agent finished.`);
|
||||
log.info(` - Response text: ${response?.length || 0} chars (NOT delivered - silent mode)`);
|
||||
// Deliver response to target room if we have one and there's something to say
|
||||
if (response && response.trim() && response.trim() !== '<no-reply/>' && this.config.target) {
|
||||
try {
|
||||
const messageId = await this.bot.deliverToChannel(
|
||||
this.config.target.channel,
|
||||
this.config.target.chatId,
|
||||
{ text: response.trim() },
|
||||
);
|
||||
log.info(`Delivered heartbeat response (${response.length} chars) to ${this.config.target.channel}:${this.config.target.chatId}`);
|
||||
|
||||
if (response && response.trim()) {
|
||||
log.info(` - Response preview: "${response.slice(0, 100)}${response.length > 100 ? '...' : ''}"`);
|
||||
// Add TTS reaction + store audio for the delivered message
|
||||
if (messageId) {
|
||||
const adapter = (this.bot as any).channels?.get(this.config.target.channel);
|
||||
if (adapter) {
|
||||
adapter.addReaction?.(this.config.target.chatId, messageId, '🎤').catch(() => {});
|
||||
adapter.storeAudioMessage?.(messageId, 'heartbeat', this.config.target.chatId, response.trim());
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('Failed to deliver heartbeat response:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
} else if (response && response.trim()) {
|
||||
log.info(`Heartbeat response (${response.length} chars) but no target configured — not delivered`);
|
||||
}
|
||||
|
||||
logEvent('heartbeat_completed', {
|
||||
mode: 'silent',
|
||||
mode: 'deliver',
|
||||
responseLength: response?.length || 0,
|
||||
delivered: !!(response?.trim() && this.config.target),
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
|
||||
148
src/models.json
148
src/models.json
@@ -1,75 +1,109 @@
|
||||
[
|
||||
{
|
||||
"id": "sonnet-4.6",
|
||||
"handle": "anthropic/claude-sonnet-4-6",
|
||||
"label": "Sonnet 4.6",
|
||||
"description": "Anthropic's new Sonnet model",
|
||||
"id": "kimi-k2.5-nvfp4",
|
||||
"handle": "openai-proxy/hf:nvidia/Kimi-K2.5-NVFP4",
|
||||
"label": "Kimi K2.5 (NVFP4)",
|
||||
"description": "Kimi K2.5 quantized, vision-capable",
|
||||
"isDefault": true,
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "opus-4.6",
|
||||
"handle": "anthropic/claude-opus-4-6",
|
||||
"label": "Opus 4.6",
|
||||
"description": "Anthropic's best model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "haiku",
|
||||
"handle": "anthropic/claude-haiku-4-5",
|
||||
"label": "Haiku 4.5",
|
||||
"description": "Anthropic's fastest model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.3-codex",
|
||||
"handle": "openai/gpt-5.3-codex",
|
||||
"label": "GPT-5.3 Codex",
|
||||
"description": "OpenAI's best coding model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "gpt-5.2",
|
||||
"handle": "openai/gpt-5.2",
|
||||
"label": "GPT-5.2",
|
||||
"description": "Latest general-purpose GPT",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "gemini-3.1",
|
||||
"handle": "google_ai/gemini-3.1-pro-preview",
|
||||
"label": "Gemini 3.1 Pro",
|
||||
"description": "Google's latest and smartest model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "gemini-3-flash",
|
||||
"handle": "google_ai/gemini-3-flash-preview",
|
||||
"label": "Gemini 3 Flash",
|
||||
"description": "Google's fastest Gemini 3 model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "kimi-k2.5",
|
||||
"handle": "openrouter/moonshotai/kimi-k2.5",
|
||||
"handle": "synthetic-direct/hf:moonshotai/Kimi-K2.5",
|
||||
"label": "Kimi K2.5",
|
||||
"description": "Kimi's latest coding model",
|
||||
"description": "Kimi K2.5 full, vision-capable",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "glm-5",
|
||||
"handle": "zai/glm-5",
|
||||
"label": "GLM-5",
|
||||
"description": "zAI's latest coding model",
|
||||
"isFeatured": true,
|
||||
"free": true
|
||||
"id": "kimi-k2-thinking",
|
||||
"handle": "synthetic-direct/hf:moonshotai/Kimi-K2-Thinking",
|
||||
"label": "Kimi K2 Thinking",
|
||||
"description": "Kimi reasoning model",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "minimax-m2.5",
|
||||
"handle": "minimax/MiniMax-M2.5",
|
||||
"label": "MiniMax 2.5",
|
||||
"description": "MiniMax's latest coding model",
|
||||
"handle": "openai-proxy/hf:MiniMaxAI/MiniMax-M2.5",
|
||||
"label": "MiniMax M2.5",
|
||||
"description": "MiniMax latest, 191k context",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "qwen3.5",
|
||||
"handle": "openai-proxy/hf:Qwen/Qwen3.5-397B-A17B",
|
||||
"label": "Qwen3.5 397B",
|
||||
"description": "Qwen latest, vision-capable",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v3.2",
|
||||
"handle": "openai-proxy/hf:deepseek-ai/DeepSeek-V3.2",
|
||||
"label": "DeepSeek V3.2",
|
||||
"description": "DeepSeek latest via Fireworks",
|
||||
"isFeatured": true
|
||||
},
|
||||
{
|
||||
"id": "glm-4.7-flash",
|
||||
"handle": "openai-proxy/hf:zai-org/GLM-4.7-Flash",
|
||||
"label": "GLM-4.7 Flash",
|
||||
"description": "Fast and cheap, great for subagents",
|
||||
"isFeatured": true,
|
||||
"free": true
|
||||
},
|
||||
{
|
||||
"id": "glm-4.7",
|
||||
"handle": "openai-proxy/hf:zai-org/GLM-4.7",
|
||||
"label": "GLM-4.7",
|
||||
"description": "Full GLM-4.7, 202k context",
|
||||
"isFeatured": true,
|
||||
"free": true
|
||||
},
|
||||
{
|
||||
"id": "nemotron-3-super",
|
||||
"handle": "openai-proxy/hf:nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4",
|
||||
"label": "Nemotron 3 Super",
|
||||
"description": "NVIDIA 120B MoE, 262k context"
|
||||
},
|
||||
{
|
||||
"id": "gpt-oss-120b",
|
||||
"handle": "openai-proxy/hf:openai/gpt-oss-120b",
|
||||
"label": "GPT-OSS 120B",
|
||||
"description": "OpenAI open-source, cheapest option"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-r1",
|
||||
"handle": "openai-proxy/hf:deepseek-ai/DeepSeek-R1-0528",
|
||||
"label": "DeepSeek R1",
|
||||
"description": "DeepSeek reasoning model"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-235b-thinking",
|
||||
"handle": "openai-proxy/hf:Qwen/Qwen3-235B-A22B-Thinking-2507",
|
||||
"label": "Qwen3 235B Thinking",
|
||||
"description": "Qwen reasoning MoE, 262k context"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-coder",
|
||||
"handle": "openai-proxy/hf:Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
||||
"label": "Qwen3 Coder 480B",
|
||||
"description": "Qwen coding specialist"
|
||||
},
|
||||
{
|
||||
"id": "minimax-m2.1",
|
||||
"handle": "openai-proxy/hf:MiniMaxAI/MiniMax-M2.1",
|
||||
"label": "MiniMax M2.1",
|
||||
"description": "MiniMax previous gen via Fireworks"
|
||||
},
|
||||
{
|
||||
"id": "deepseek-v3",
|
||||
"handle": "openai-proxy/hf:deepseek-ai/DeepSeek-V3",
|
||||
"label": "DeepSeek V3",
|
||||
"description": "DeepSeek V3 via Together"
|
||||
},
|
||||
{
|
||||
"id": "llama-3.3-70b",
|
||||
"handle": "openai-proxy/hf:meta-llama/Llama-3.3-70B-Instruct",
|
||||
"label": "Llama 3.3 70B",
|
||||
"description": "Meta Llama via Together"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user