fix(geminiLive): T2 prompt durci + VAD réintégré, retrait SDK @google/genai
- Bug 1: prompt système T2 durci (13 règles absolues, interdiction du "?", rôle inerte) pour stopper la relance systématique. Réf TD-22. - Bug 2: realtimeInputConfig (VAD automaticActivityDetection, 4 champs) réintégré dans le setup frame Gemini. - Bug 8: @google/genai retiré + test-gemini-live.js supprimé (SDK abandonné au profit du WebSocket brut). Tests 292/292 verts. Validé Golden Dataset Groupe D.
This commit is contained in:
parent
eee75b53ca
commit
94387a71db
5 changed files with 39 additions and 588 deletions
415
package-lock.json
generated
415
package-lock.json
generated
|
|
@ -8,7 +8,6 @@
|
||||||
"name": "expria-backend",
|
"name": "expria-backend",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/genai": "^1.50.1",
|
|
||||||
"@hono/node-server": "^1.13.7",
|
"@hono/node-server": "^1.13.7",
|
||||||
"@hono/node-ws": "^1.3.0",
|
"@hono/node-ws": "^1.3.0",
|
||||||
"@supabase/supabase-js": "^2.49.4",
|
"@supabase/supabase-js": "^2.49.4",
|
||||||
|
|
@ -542,29 +541,6 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@google/genai": {
|
|
||||||
"version": "1.50.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.50.1.tgz",
|
|
||||||
"integrity": "sha512-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"google-auth-library": "^10.3.0",
|
|
||||||
"p-retry": "^4.6.2",
|
|
||||||
"protobufjs": "^7.5.4",
|
|
||||||
"ws": "^8.18.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@modelcontextprotocol/sdk": "^1.25.2"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@modelcontextprotocol/sdk": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@hono/node-server": {
|
"node_modules/@hono/node-server": {
|
||||||
"version": "1.19.14",
|
"version": "1.19.14",
|
||||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz",
|
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz",
|
||||||
|
|
@ -671,70 +647,6 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@protobufjs/aspromise": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/base64": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/codegen": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/eventemitter": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/fetch": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"@protobufjs/aspromise": "^1.1.1",
|
|
||||||
"@protobufjs/inquire": "^1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/float": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/inquire": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/path": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/pool": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@protobufjs/utf8": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.60.1",
|
"version": "4.60.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
|
||||||
|
|
@ -1205,12 +1117,6 @@
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/retry": {
|
|
||||||
"version": "0.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
|
|
||||||
"integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.18.1",
|
"version": "8.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
|
@ -1369,15 +1275,6 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/agent-base": {
|
|
||||||
"version": "7.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
|
||||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
|
||||||
|
|
@ -1436,35 +1333,6 @@
|
||||||
"node": "18 || 20 || >=22"
|
"node": "18 || 20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/base64-js": {
|
|
||||||
"version": "1.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
||||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "patreon",
|
|
||||||
"url": "https://www.patreon.com/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "consulting",
|
|
||||||
"url": "https://feross.org/support"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/bignumber.js": {
|
|
||||||
"version": "9.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
|
||||||
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "5.0.5",
|
"version": "5.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
|
||||||
|
|
@ -1478,12 +1346,6 @@
|
||||||
"node": "18 || 20 || >=22"
|
"node": "18 || 20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/buffer-equal-constant-time": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/cac": {
|
"node_modules/cac": {
|
||||||
"version": "6.7.14",
|
"version": "6.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||||
|
|
@ -1585,19 +1447,11 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/data-uri-to-buffer": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "^2.1.3"
|
"ms": "^2.1.3"
|
||||||
|
|
@ -1654,15 +1508,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/ecdsa-sig-formatter": {
|
|
||||||
"version": "1.0.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
|
||||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
|
|
@ -1769,12 +1614,6 @@
|
||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/extend": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
|
||||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/fdir": {
|
"node_modules/fdir": {
|
||||||
"version": "6.5.0",
|
"version": "6.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||||
|
|
@ -1793,29 +1632,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fetch-blob": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
|
||||||
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/jimmywarting"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "paypal",
|
|
||||||
"url": "https://paypal.me/jimmywarting"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"node-domexception": "^1.0.0",
|
|
||||||
"web-streams-polyfill": "^3.0.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20 || >= 14.13"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/foreground-child": {
|
"node_modules/foreground-child": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||||
|
|
@ -1833,18 +1649,6 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/formdata-polyfill": {
|
|
||||||
"version": "4.0.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
|
||||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fetch-blob": "^3.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
|
@ -1869,34 +1673,6 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/gaxios": {
|
|
||||||
"version": "7.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
|
|
||||||
"integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"extend": "^3.0.2",
|
|
||||||
"https-proxy-agent": "^7.0.1",
|
|
||||||
"node-fetch": "^3.3.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/gcp-metadata": {
|
|
||||||
"version": "8.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
|
|
||||||
"integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"gaxios": "^7.0.0",
|
|
||||||
"google-logging-utils": "^1.0.0",
|
|
||||||
"json-bigint": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
|
@ -2002,32 +1778,6 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/google-auth-library": {
|
|
||||||
"version": "10.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
|
|
||||||
"integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"base64-js": "^1.3.0",
|
|
||||||
"ecdsa-sig-formatter": "^1.0.11",
|
|
||||||
"gaxios": "^7.1.4",
|
|
||||||
"gcp-metadata": "8.1.2",
|
|
||||||
"google-logging-utils": "1.1.3",
|
|
||||||
"jws": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/google-logging-utils": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
|
@ -2090,19 +1840,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/https-proxy-agent": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "^7.1.2",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iceberg-js": {
|
"node_modules/iceberg-js": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz",
|
||||||
|
|
@ -2206,42 +1943,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/json-bigint": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"bignumber.js": "^9.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jwa": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"buffer-equal-constant-time": "^1.0.1",
|
|
||||||
"ecdsa-sig-formatter": "1.0.11",
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jws": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"jwa": "^2.0.1",
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/long": {
|
|
||||||
"version": "5.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
|
||||||
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
|
||||||
|
|
@ -2333,6 +2034,7 @@
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
|
|
@ -2354,44 +2056,6 @@
|
||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-domexception": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
|
||||||
"deprecated": "Use your platform's native DOMException instead",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/jimmywarting"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://paypal.me/jimmywarting"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/node-fetch": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"data-uri-to-buffer": "^4.0.0",
|
|
||||||
"fetch-blob": "^3.1.4",
|
|
||||||
"formdata-polyfill": "^4.0.10"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/node-fetch"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
|
@ -2404,19 +2068,6 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/p-retry": {
|
|
||||||
"version": "4.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
|
|
||||||
"integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/retry": "0.12.0",
|
|
||||||
"retry": "^0.13.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/package-json-from-dist": {
|
"node_modules/package-json-from-dist": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||||
|
|
@ -2517,30 +2168,6 @@
|
||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/protobufjs": {
|
|
||||||
"version": "7.5.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz",
|
|
||||||
"integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"@protobufjs/aspromise": "^1.1.2",
|
|
||||||
"@protobufjs/base64": "^1.1.2",
|
|
||||||
"@protobufjs/codegen": "^2.0.4",
|
|
||||||
"@protobufjs/eventemitter": "^1.1.0",
|
|
||||||
"@protobufjs/fetch": "^1.1.0",
|
|
||||||
"@protobufjs/float": "^1.0.2",
|
|
||||||
"@protobufjs/inquire": "^1.1.0",
|
|
||||||
"@protobufjs/path": "^1.1.2",
|
|
||||||
"@protobufjs/pool": "^1.1.0",
|
|
||||||
"@protobufjs/utf8": "^1.1.0",
|
|
||||||
"@types/node": ">=13.7.0",
|
|
||||||
"long": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.15.1",
|
"version": "6.15.1",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
|
||||||
|
|
@ -2566,15 +2193,6 @@
|
||||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/retry": {
|
|
||||||
"version": "0.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
|
||||||
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.60.1",
|
"version": "4.60.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
|
||||||
|
|
@ -2620,26 +2238,6 @@
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/safe-buffer": {
|
|
||||||
"version": "5.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
|
||||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "patreon",
|
|
||||||
"url": "https://www.patreon.com/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "consulting",
|
|
||||||
"url": "https://feross.org/support"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.4",
|
"version": "7.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||||
|
|
@ -3235,15 +2833,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/web-streams-polyfill": {
|
|
||||||
"version": "3.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
|
||||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"test:coverage": "vitest run --coverage"
|
"test:coverage": "vitest run --coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/genai": "^1.50.1",
|
|
||||||
"@hono/node-server": "^1.13.7",
|
"@hono/node-server": "^1.13.7",
|
||||||
"@hono/node-ws": "^1.3.0",
|
"@hono/node-ws": "^1.3.0",
|
||||||
"@supabase/supabase-js": "^2.49.4",
|
"@supabase/supabase-js": "^2.49.4",
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,13 @@ describe("openGeminiLiveSession (raw WS)", () => {
|
||||||
);
|
);
|
||||||
expect(setup.setup.inputAudioTranscription).toEqual({});
|
expect(setup.setup.inputAudioTranscription).toEqual({});
|
||||||
expect(setup.setup.outputAudioTranscription).toEqual({});
|
expect(setup.setup.outputAudioTranscription).toEqual({});
|
||||||
// ⚠ DEBUG : realtimeInputConfig (VAD) encore absent — prochain push.
|
// VAD réintégré (Sprint 6d Bug 2) — cf. IMPLEMENTATION_T2_LIVE.md §3 step 7.
|
||||||
expect(setup.setup.realtimeInputConfig).toBeUndefined();
|
expect(setup.setup.realtimeInputConfig.automaticActivityDetection).toEqual({
|
||||||
|
disabled: false,
|
||||||
|
startOfSpeechSensitivity: "START_SENSITIVITY_LOW",
|
||||||
|
endOfSpeechSensitivity: "END_SENSITIVITY_LOW",
|
||||||
|
silenceDurationMs: 2000,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("forwarde un chunk audio client {type:'audio'} en realtimeInput vers Gemini", () => {
|
it("forwarde un chunk audio client {type:'audio'} en realtimeInput vers Gemini", () => {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* geminiLive.ts — Sprint 6d (revert WS brut).
|
* geminiLive.ts — Sprint 6d (revert WS brut).
|
||||||
*
|
*
|
||||||
* Le SDK `@google/genai` fermait la session sans setupComplete ni raison
|
* Historiquement, le proxy s'appuyait sur un SDK Gemini de haut niveau, mais
|
||||||
* exploitable. On revient au WebSocket brut (package `ws`) qui était utilisé
|
* celui-ci fermait la session sans setupComplete ni raison exploitable. On
|
||||||
* par `test-gemini-live.js` et permet de loguer précisément ce que Gemini
|
* utilise désormais le WebSocket brut (package `ws`), qui permet de loguer
|
||||||
* répond. Config setup réduite au strict minimum tant que `setupComplete`
|
* précisément ce que Gemini répond et de maîtriser le contenu exact du setup
|
||||||
* n'est pas confirmé en prod ; on réintègre champs un par un ensuite.
|
* frame (model, systemInstruction, transcriptions, VAD).
|
||||||
*
|
*
|
||||||
* Interface publique (consommée par `routes/t2live.ts`) — INCHANGÉE :
|
* Interface publique (consommée par `routes/t2live.ts`) — INCHANGÉE :
|
||||||
* - openGeminiLiveSession(clientWs, opts)
|
* - openGeminiLiveSession(clientWs, opts)
|
||||||
|
|
@ -22,7 +22,7 @@ export const GEMINI_LIVE_URL =
|
||||||
/**
|
/**
|
||||||
* Modèle Live cible. `gemini-2.0-flash-live-001` est le modèle Live confirmé
|
* Modèle Live cible. `gemini-2.0-flash-live-001` est le modèle Live confirmé
|
||||||
* par la doc Google pour les clés API Developer + Express. Format `models/...`
|
* par la doc Google pour les clés API Developer + Express. Format `models/...`
|
||||||
* dans le setup frame natif (cf. `test-gemini-live.js`).
|
* requis dans le setup frame natif.
|
||||||
*/
|
*/
|
||||||
export const GEMINI_LIVE_MODEL = "gemini-3.1-flash-live-preview";
|
export const GEMINI_LIVE_MODEL = "gemini-3.1-flash-live-preview";
|
||||||
|
|
||||||
|
|
@ -41,22 +41,23 @@ export function buildT2SystemPrompt(input: {
|
||||||
contexte: string;
|
contexte: string;
|
||||||
}): string {
|
}): string {
|
||||||
const { role, contexte } = input;
|
const { role, contexte } = input;
|
||||||
return `Tu es un examinateur du TCF Canada pour l'épreuve d'Expression Orale, Tâche 2 (dialogue interactif).
|
return `RÔLE : Tu incarnes ${role}.
|
||||||
RÔLE : Tu incarnes ${role}.
|
|
||||||
CONTEXTE : ${contexte}
|
CONTEXTE : ${contexte}
|
||||||
|
|
||||||
RÈGLES ABSOLUES :
|
RÈGLES ABSOLUES :
|
||||||
1. Tu parles TOUJOURS en français naturel et courant, niveau B2-C1.
|
1. Tu parles TOUJOURS en français naturel et courant, niveau B2-C1.
|
||||||
2. Tu NE corriges JAMAIS les erreurs du candidat.
|
2. Tu NE corriges JAMAIS les erreurs du candidat. Tu continues naturellement.
|
||||||
3. Tu attends que le candidat finisse sa question avant de répondre.
|
3. Tu attends que le candidat finisse sa question avant de répondre.
|
||||||
4. Tes réponses sont courtes (15 à 25 mots maximum). Pas de monologue.
|
4. Tes réponses sont courtes (15 à 25 mots maximum) pour laisser la place au dialogue.
|
||||||
5. Ne donne pas toutes les informations d'un coup. Force le candidat à poser des questions précises.
|
5. Ne donne pas toutes les informations d'un coup. Force le candidat à poser des questions précises.
|
||||||
6. Si le candidat est vague, réponds brièvement sans chercher à compléter.
|
6. Si le candidat est vague, réponds brièvement sans chercher à compléter — c'est à lui de reformuler.
|
||||||
7. Ne pose JAMAIS de question après tes réponses. Tu réponds et tu te tais. La seule exception : si le candidat marque un long silence et semble avoir terminé, tu peux dire une seule fois « Si vous n'avez plus de questions, je vous souhaite une bonne journée » ou équivalent pour clore naturellement.
|
7. STRICTE INTERDICTION DE POSER DES QUESTIONS. Tu n'as pas le droit d'utiliser de point d'interrogation. Tes phrases se terminent par un point.
|
||||||
8. Ne prends jamais d'initiative pour orienter la conversation.
|
8. SILENCE TOTAL APRÈS LA RÉPONSE. Réponds de manière factuelle, puis arrête-toi immédiatement. Ne suggère rien, ne relance pas, ne dis pas "et vous ?".
|
||||||
9. Tu peux être légèrement pressé ou hésitant pour rendre l'échange réaliste.
|
9. RÔLE PASSIF : tu es une source d'information inerte. Tu n'aides pas le candidat à tenir la conversation. S'il ne parle plus, le silence s'installe.
|
||||||
10. JAMAIS de listes ni de structure numérotée dans tes réponses.
|
10. AUCUNE FORMULE DE POLITESSE DE FIN : bannis "n'hésitez pas", "j'espère que ça vous aide", "qu'en pensez-vous ?".
|
||||||
11. Ne mentionne jamais que tu es une IA ou un modèle.
|
11. JAMAIS de listes ni de structure numérotée — parle naturellement.
|
||||||
12. Tu ne prends PAS la parole en premier. Tu attends que le candidat s'adresse à toi.`;
|
12. Ne mentionne jamais que tu es une IA ou un modèle.
|
||||||
|
13. Tu ne prends PAS la parole en premier. Tu attends que le candidat s'adresse à toi.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -212,11 +213,10 @@ function tryParseGeminiJson(data: unknown): GeminiServerMessage | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construit le setup frame minimal Gemini Live (équivalent du mode
|
* Construit le setup frame Gemini Live : model + responseModalities AUDIO,
|
||||||
* `minimal` de `test-gemini-live.js`). Les champs `systemInstruction`,
|
* systemInstruction (prompt T2), input/outputAudioTranscription, et
|
||||||
* `inputAudioTranscription`, `outputAudioTranscription`,
|
* realtimeInputConfig.automaticActivityDetection (VAD : START/END_SENSITIVITY_LOW,
|
||||||
* `realtimeInputConfig.automaticActivityDetection` sont volontairement
|
* 2 s de silence avant que l'IA réponde — cf. IMPLEMENTATION_T2_LIVE.md §3).
|
||||||
* retirés tant que `setupComplete` n'est pas confirmé en prod.
|
|
||||||
*/
|
*/
|
||||||
function buildSetupFrame(systemPrompt: string): string {
|
function buildSetupFrame(systemPrompt: string): string {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
|
|
@ -230,6 +230,14 @@ function buildSetupFrame(systemPrompt: string): string {
|
||||||
},
|
},
|
||||||
inputAudioTranscription: {},
|
inputAudioTranscription: {},
|
||||||
outputAudioTranscription: {},
|
outputAudioTranscription: {},
|
||||||
|
realtimeInputConfig: {
|
||||||
|
automaticActivityDetection: {
|
||||||
|
disabled: false,
|
||||||
|
startOfSpeechSensitivity: "START_SENSITIVITY_LOW",
|
||||||
|
endOfSpeechSensitivity: "END_SENSITIVITY_LOW",
|
||||||
|
silenceDurationMs: 2000,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
// test-gemini-live.js — Sprint 6d : debug du setup frame Gemini Live via SDK.
|
|
||||||
//
|
|
||||||
// Usage :
|
|
||||||
// node --env-file=.env test-gemini-live.js minimal
|
|
||||||
// node --env-file=.env test-gemini-live.js +system
|
|
||||||
// node --env-file=.env test-gemini-live.js +transcription
|
|
||||||
// node --env-file=.env test-gemini-live.js +vad
|
|
||||||
//
|
|
||||||
// Chaque mode part du `minimal` qui doit fonctionner avec une clé Express
|
|
||||||
// Mode et ajoute UN champ. Si le mode reçoit `setupComplete` → le champ est
|
|
||||||
// accepté. Si l'ouverture échoue → c'est ce champ qui pose problème.
|
|
||||||
//
|
|
||||||
// Migration Sprint 6d : passage du WebSocket brut au SDK officiel
|
|
||||||
// `@google/genai` qui gère l'auth Express Mode automatiquement.
|
|
||||||
|
|
||||||
import {
|
|
||||||
GoogleGenAI,
|
|
||||||
Modality,
|
|
||||||
StartSensitivity,
|
|
||||||
EndSensitivity,
|
|
||||||
} from "@google/genai";
|
|
||||||
|
|
||||||
const MODES = ["minimal", "+system", "+transcription", "+vad"];
|
|
||||||
const mode = process.argv[2] ?? "minimal";
|
|
||||||
if (!MODES.includes(mode)) {
|
|
||||||
console.error(
|
|
||||||
`❌ Mode inconnu : "${mode}". Modes valides : ${MODES.join(", ")}`,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const KEY = process.env.GEMINI_API_KEY;
|
|
||||||
if (!KEY) {
|
|
||||||
console.error("❌ GEMINI_API_KEY manquante dans l'env");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modèle par défaut Sprint 6d. Fallback documenté : `gemini-2.0-flash-live-001`.
|
|
||||||
const MODEL = "gemini-3.1-flash-live-preview";
|
|
||||||
|
|
||||||
const SAMPLE_PROMPT =
|
|
||||||
"Tu joues le rôle d'un bailleur. Tu réponds uniquement en français. " +
|
|
||||||
"Tu attends que ton interlocuteur s'adresse à toi avant de parler.";
|
|
||||||
|
|
||||||
function buildConfig(mode) {
|
|
||||||
// Base minimal — équivalent au mode `minimal` qui doit fonctionner.
|
|
||||||
const config = {
|
|
||||||
responseModalities: [Modality.AUDIO],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (mode === "+system") {
|
|
||||||
config.systemInstruction = SAMPLE_PROMPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === "+transcription") {
|
|
||||||
config.inputAudioTranscription = {};
|
|
||||||
config.outputAudioTranscription = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode === "+vad") {
|
|
||||||
config.realtimeInputConfig = {
|
|
||||||
automaticActivityDetection: {
|
|
||||||
disabled: false,
|
|
||||||
startOfSpeechSensitivity: StartSensitivity.START_SENSITIVITY_LOW,
|
|
||||||
endOfSpeechSensitivity: EndSensitivity.END_SENSITIVITY_LOW,
|
|
||||||
silenceDurationMs: 2000,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ai = new GoogleGenAI({ vertexai: true, apiKey: KEY });
|
|
||||||
|
|
||||||
console.log(`→ Mode : ${mode}`);
|
|
||||||
console.log(`→ Modèle : ${MODEL}`);
|
|
||||||
console.log("→ Connexion à Gemini Live (via SDK)…");
|
|
||||||
|
|
||||||
let setupCompleteReceived = false;
|
|
||||||
let resolved = false;
|
|
||||||
|
|
||||||
const config = buildConfig(mode);
|
|
||||||
console.log("→ Config envoyée :");
|
|
||||||
console.log(JSON.stringify(config, null, 2));
|
|
||||||
|
|
||||||
const timeoutId = setTimeout(() => {
|
|
||||||
if (!resolved) {
|
|
||||||
console.log("⏱ Timeout 15 s — pas de setupComplete reçu.");
|
|
||||||
process.exit(setupCompleteReceived ? 0 : 1);
|
|
||||||
}
|
|
||||||
}, 15000);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const session = await ai.live.connect({
|
|
||||||
model: MODEL,
|
|
||||||
config,
|
|
||||||
callbacks: {
|
|
||||||
onopen: () => {
|
|
||||||
console.log("✅ Connexion ouverte");
|
|
||||||
},
|
|
||||||
onmessage: (msg) => {
|
|
||||||
// Compat : selon la version du SDK, setupComplete arrive soit comme
|
|
||||||
// propriété directe, soit dans serverContent. On loggue tout.
|
|
||||||
console.log("📨 Message reçu :", JSON.stringify(msg).slice(0, 600));
|
|
||||||
if (msg.setupComplete || msg?.serverContent?.setupComplete) {
|
|
||||||
setupCompleteReceived = true;
|
|
||||||
resolved = true;
|
|
||||||
console.log(
|
|
||||||
`\n🎉 [${mode}] ACCEPTÉ — setupComplete reçu (modèle ${MODEL}).`,
|
|
||||||
);
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
try {
|
|
||||||
session.close();
|
|
||||||
} catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onerror: (err) => {
|
|
||||||
console.log("❌ Erreur :", err?.message ?? err);
|
|
||||||
},
|
|
||||||
onclose: (evt) => {
|
|
||||||
console.log(
|
|
||||||
`🔒 Fermeture${evt?.code ? ` — code ${evt.code}` : ""}${evt?.reason ? ` reason: ${evt.reason}` : ""}`,
|
|
||||||
);
|
|
||||||
if (!setupCompleteReceived) {
|
|
||||||
console.log(`\n⚠ [${mode}] REJETÉ — fermeture avant setupComplete.`);
|
|
||||||
console.log(
|
|
||||||
"→ Le ou les champs ajoutés par ce mode ne sont pas acceptés.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
resolved = true;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
process.exit(setupCompleteReceived ? 0 : 1);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// Conserver la session vivante jusqu'au timeout/setupComplete.
|
|
||||||
void session;
|
|
||||||
} catch (err) {
|
|
||||||
resolved = true;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
console.log(
|
|
||||||
"❌ live.connect a échoué :",
|
|
||||||
err instanceof Error ? err.message : String(err),
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue