* flip title and name in recent scenes

* fix issue where a message could not be regenerated after applying continuity error fixes

* prompt tweaks

* allow json parameters for commands

* autocomplete improvements

* dialogue cleanup fixes

* fix issue with narrate after dialogue and llama3 (and other models that don't have a line break after the user prompt in their prompt template.

* expose ability to auto generate dialogue instructions to wsm character ux

* use b64_json response type

* move tag checks up so they match first

* fix typo

* prompt tweak

* api key support

* prompt tweaks

* editable parameters in prompt debugger / tester

* allow reseting of prompt params

* codemirror for prompt editor

* prompt tweaks

* more prompt debug tool tweaks

* some extra control for `context_history`

* new analytical preset (testing)

* add `join` and `llm_can_be_coerced` to jinja env

* support factual list summaries

* prompt tweaks to continuity check and fix

* new summarization method `facts` exposed to ux

* clamp mistral ai temperature according to their new requirements

* prompt tweaks

* better parsing of fixed dialogue response

* prompt tweaks

* fix intermittent empty meta issue

* history regen status progression and small ux tweaks

* summary entries should always be condensed

* google gemini support

* relock to install google-cloud-aiplatform for vertex ai inference

* fix instruction link

* better error handling of google safety validation and allow disabling of safety validation

* docs

* clarify credentials path requirements

* tweak error line identification

* handle quota limit error

* autocomplete ux wired to assistant plugin instead of command

* autocomplete narrative editing and fixes to autocomplete during dialog edit

* main input autocomplete tweaks

* allow new lines in main input

* 0.25.0 and relock

* fix issue with autocomplete elsewhere locking out main input

* better way to determine remote service

* prompt tweak

* fix rubberbanding issue when editing character attributes

* add open mistral 8x22

* fix continuity error check summary inclusion of target entry

* docs

* default context length to 8192

* linting
This commit is contained in:
veguAI
2024-05-05 22:16:03 +03:00
committed by GitHub
parent f0b627b900
commit 39bd02722d
60 changed files with 2639 additions and 594 deletions

View File

@@ -1,18 +1,22 @@
{
"name": "talemate_frontend",
"version": "0.24.0",
"version": "0.25.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "talemate_frontend",
"version": "0.24.0",
"version": "0.25.0",
"dependencies": {
"@codemirror/lang-markdown": "^6.2.5",
"@codemirror/theme-one-dark": "^6.1.2",
"@mdi/font": "7.4.47",
"codemirror": "^6.0.1",
"core-js": "^3.8.3",
"dot-prop": "^8.0.2",
"roboto-fontface": "*",
"vue": "^3.2.13",
"vue-codemirror": "^6.1.1",
"vuetify": "^3.5.0",
"webfontloader": "^1.0.0"
},
@@ -1823,6 +1827,149 @@
"node": ">=6.9.0"
}
},
"node_modules/@codemirror/autocomplete": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz",
"integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0"
},
"peerDependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0"
}
},
"node_modules/@codemirror/commands": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz",
"integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.1.0"
}
},
"node_modules/@codemirror/lang-css": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.0.2",
"@lezer/css": "^1.0.0"
}
},
"node_modules/@codemirror/lang-html": {
"version": "6.4.9",
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/lang-css": "^6.0.0",
"@codemirror/lang-javascript": "^6.0.0",
"@codemirror/language": "^6.4.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/css": "^1.1.0",
"@lezer/html": "^1.3.0"
}
},
"node_modules/@codemirror/lang-javascript": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/javascript": "^1.0.0"
}
},
"node_modules/@codemirror/lang-markdown": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz",
"integrity": "sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==",
"dependencies": {
"@codemirror/autocomplete": "^6.7.1",
"@codemirror/lang-html": "^6.0.0",
"@codemirror/language": "^6.3.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.2.1",
"@lezer/markdown": "^1.0.0"
}
},
"node_modules/@codemirror/language": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz",
"integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
"@lezer/common": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"node_modules/@codemirror/lint": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.0.tgz",
"integrity": "sha512-LTLOL2nT41ADNSCCCCw8Q/UmdAFzB23OUYSjsHTdsVaH0XEo+orhuqbDNWzrzodm14w6FOxqxpmy4LF8Lixqjw==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/search": {
"version": "6.5.6",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
},
"node_modules/@codemirror/theme-one-dark": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.26.3",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
"integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
"dependencies": {
"@codemirror/state": "^6.4.0",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@@ -1986,6 +2133,66 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
"node_modules/@lezer/common": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
},
"node_modules/@lezer/css": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/highlight": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/html": {
"version": "1.3.9",
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz",
"integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/javascript": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.15.tgz",
"integrity": "sha512-B082ZdjI0vo2AgLqD834GlRTE9gwRX8NzHzKq5uDwEnQ9Dq+A/CEhd3nf68tiNA2f9O+8jS1NeSTUYT9IAqcTw==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.1.3",
"@lezer/lr": "^1.3.0"
}
},
"node_modules/@lezer/lr": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz",
"integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/markdown": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz",
"integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==",
"dependencies": {
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@mdi/font": {
"version": "7.4.47",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz",
@@ -4097,6 +4304,20 @@
"node": ">=6"
}
},
"node_modules/codemirror": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -4331,6 +4552,11 @@
"node": ">=10"
}
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
},
"node_modules/cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -9870,6 +10096,11 @@
"node": ">=8"
}
},
"node_modules/style-mod": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
},
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -10401,6 +10632,21 @@
}
}
},
"node_modules/vue-codemirror": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz",
"integrity": "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==",
"dependencies": {
"@codemirror/commands": "6.x",
"@codemirror/language": "6.x",
"@codemirror/state": "6.x",
"@codemirror/view": "6.x"
},
"peerDependencies": {
"codemirror": "6.x",
"vue": "3.x"
}
},
"node_modules/vue-eslint-parser": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
@@ -10614,6 +10860,11 @@
}
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz",
@@ -12590,6 +12841,143 @@
"to-fast-properties": "^2.0.0"
}
},
"@codemirror/autocomplete": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz",
"integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0"
}
},
"@codemirror/commands": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz",
"integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.1.0"
}
},
"@codemirror/lang-css": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.0.2",
"@lezer/css": "^1.0.0"
}
},
"@codemirror/lang-html": {
"version": "6.4.9",
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/lang-css": "^6.0.0",
"@codemirror/lang-javascript": "^6.0.0",
"@codemirror/language": "^6.4.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/css": "^1.1.0",
"@lezer/html": "^1.3.0"
}
},
"@codemirror/lang-javascript": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/javascript": "^1.0.0"
}
},
"@codemirror/lang-markdown": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz",
"integrity": "sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==",
"requires": {
"@codemirror/autocomplete": "^6.7.1",
"@codemirror/lang-html": "^6.0.0",
"@codemirror/language": "^6.3.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.2.1",
"@lezer/markdown": "^1.0.0"
}
},
"@codemirror/language": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz",
"integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
"@lezer/common": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"@codemirror/lint": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.0.tgz",
"integrity": "sha512-LTLOL2nT41ADNSCCCCw8Q/UmdAFzB23OUYSjsHTdsVaH0XEo+orhuqbDNWzrzodm14w6FOxqxpmy4LF8Lixqjw==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"@codemirror/search": {
"version": "6.5.6",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
"requires": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
},
"@codemirror/theme-one-dark": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
"requires": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"@codemirror/view": {
"version": "6.26.3",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
"integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
"requires": {
"@codemirror/state": "^6.4.0",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@@ -12730,6 +13118,66 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
"@lezer/common": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
},
"@lezer/css": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
"requires": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"@lezer/highlight": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
"requires": {
"@lezer/common": "^1.0.0"
}
},
"@lezer/html": {
"version": "1.3.9",
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz",
"integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==",
"requires": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"@lezer/javascript": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.15.tgz",
"integrity": "sha512-B082ZdjI0vo2AgLqD834GlRTE9gwRX8NzHzKq5uDwEnQ9Dq+A/CEhd3nf68tiNA2f9O+8jS1NeSTUYT9IAqcTw==",
"requires": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.1.3",
"@lezer/lr": "^1.3.0"
}
},
"@lezer/lr": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz",
"integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==",
"requires": {
"@lezer/common": "^1.0.0"
}
},
"@lezer/markdown": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz",
"integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==",
"requires": {
"@lezer/common": "^1.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"@mdi/font": {
"version": "7.4.47",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz",
@@ -14490,6 +14938,20 @@
"shallow-clone": "^3.0.0"
}
},
"codemirror": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"requires": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
@@ -14690,6 +15152,11 @@
"yaml": "^1.10.0"
}
},
"crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -18998,6 +19465,11 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"style-mod": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
},
"stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -19402,6 +19874,17 @@
"shelljs": "^0.8.3"
}
},
"vue-codemirror": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz",
"integrity": "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==",
"requires": {
"@codemirror/commands": "6.x",
"@codemirror/language": "6.x",
"@codemirror/state": "6.x",
"@codemirror/view": "6.x"
}
},
"vue-eslint-parser": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
@@ -19550,6 +20033,11 @@
"integrity": "sha512-zpZFZoJE9c8QlHc8s9zowKzMUTjytdzz2PQpZPezVENm0Jp+KBi+KooZGxvj7l+YfeFdKOcSjht7nEptSSMPMg==",
"requires": {}
},
"w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
},
"watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "talemate_frontend",
"version": "0.24.0",
"version": "0.25.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
@@ -8,11 +8,15 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@codemirror/lang-markdown": "^6.2.5",
"@codemirror/theme-one-dark": "^6.1.2",
"@mdi/font": "7.4.47",
"codemirror": "^6.0.1",
"core-js": "^3.8.3",
"dot-prop": "^8.0.2",
"roboto-fontface": "*",
"vue": "^3.2.13",
"vue-codemirror": "^6.1.1",
"vuetify": "^3.5.0",
"webfontloader": "^1.0.0"
},

View File

@@ -99,7 +99,7 @@ export default {
type: '',
api_url: '',
model_name: '',
max_token_length: 4096,
max_token_length: 8192,
double_coercion: null,
data: {
has_prompt_template: false,
@@ -156,7 +156,7 @@ export default {
type: 'textgenwebui',
api_url: 'http://localhost:5000',
model_name: '',
max_token_length: 4096,
max_token_length: 8192,
data: {
has_prompt_template: false,
}

View File

@@ -191,6 +191,35 @@
</v-row>
</div>
<!-- GOOGLE API
THis adds fields for
gcloud_credentials_path
gcloud_project_id
gcloud_location
-->
<div v-if="applicationPageSelected === 'google_api'">
<v-alert color="white" variant="text" icon="mdi-google-cloud" density="compact">
<v-alert-title>Google Cloud</v-alert-title>
<div class="text-grey">
In order for you to use Google Cloud services like the vertexi ai api for Gemini inference you will need to set up a Google Cloud project and credentials.
Please follow the instructions <a href="https://cloud.google.com/vertex-ai/docs/start/client-libraries">here</a> and then fill in the fields below.
</div>
</v-alert>
<v-divider class="mb-2"></v-divider>
<v-row>
<v-col cols="12">
<v-text-field v-model="app_config.google.gcloud_credentials_path"
label="Google Cloud Credentials Path" messages="This should be a path to the credentials JSON file you downloaded through the setup above. This path needs to be accessible by the computer that is running the Talemate backend. If you are running Talemate on a server, you can upload the file to the server and the path should be the path to the file on the server."></v-text-field>
</v-col>
<v-col cols="6">
<v-combobox v-model="app_config.google.gcloud_location"
label="Google Cloud Location" :items="googleCloudLocations" messages="Pick something close to you" :return-object="false"></v-combobox>
</v-col>
</v-row>
</div>
<!-- ELEVENLABS API -->
<div v-if="applicationPageSelected === 'elevenlabs_api'">
<v-alert color="white" variant="text" icon="mdi-api" density="compact">
@@ -315,6 +344,7 @@ export default {
{title: 'Anthropic', icon: 'mdi-api', value: 'anthropic_api'},
{title: 'Cohere', icon: 'mdi-api', value: 'cohere_api'},
{title: 'groq', icon: 'mdi-api', value: 'groq_api'},
{title: 'Google Cloud', icon: 'mdi-google-cloud', value: 'google_api'},
{title: 'ElevenLabs', icon: 'mdi-api', value: 'elevenlabs_api'},
{title: 'RunPod', icon: 'mdi-api', value: 'runpod_api'},
],
@@ -325,6 +355,40 @@ export default {
gamePageSelected: 'general',
applicationPageSelected: 'openai_api',
creatorPageSelected: 'content_context',
googleCloudLocations: [
{"value": 'us-central1', "title": 'US Central - Iowa'},
{"value": 'us-west4', "title": 'US West 4 - Las Vegas'},
{"value": 'us-east1', "title": 'US East 1 - South Carolina'},
{"value": 'us-east4', "title": 'US East 4 - Northern Virginia'},
{"value": 'us-west1', "title": 'US West 1 - Oregon'},
{"value": 'northamerica-northeast1', "title": 'North America Northeast 1 - Montreal'},
{"value": 'southamerica-east1', "title": 'South America East 1 - Sao Paulo'},
{"value": 'europe-west1', "title": 'Europe West 1 - Belgium'},
{"value": 'europe-north1', "title": 'Europe North 1 - Finland'},
{"value": 'europe-west3', "title": 'Europe West 3 - Frankfurt'},
{"value": 'europe-west2', "title": 'Europe West 2 - London'},
{"value": 'europe-southwest1', "title": 'Europe Southwest 1 - Zurich'},
{"value": 'europe-west8', "title": 'Europe West 8 - Netherlands'},
{"value": 'europe-west4', "title": 'Europe West 4 - London'},
{"value": 'europe-west9', "title": 'Europe West 9 - Stockholm'},
{"value": 'europe-central2', "title": 'Europe Central 2 - Warsaw'},
{"value": 'europe-west6', "title": 'Europe West 6 - Zurich'},
{"value": 'asia-east1', "title": 'Asia East 1 - Taiwan'},
{"value": 'asia-east2', "title": 'Asia East 2 - Hong Kong'},
{"value": 'asia-south1', "title": 'Asia South 1 - Mumbai'},
{"value": 'asia-northeast1', "title": 'Asia Northeast 1 - Tokyo'},
{"value": 'asia-northeast3', "title": 'Asia Northeast 3 - Seoul'},
{"value": 'asia-southeast1', "title": 'Asia Southeast 1 - Singapore'},
{"value": 'asia-southeast2', "title": 'Asia Southeast 2 - Jakarta'},
{"value": 'australia-southeast1', "title": 'Australia Southeast 1 - Sydney'},
{"value": 'australia-southeast2', "title": 'Australia Southeast 2 - Melbourne'},
{"value": 'me-west1', "title": 'Middle East West 1 - Dammam'},
{"value": 'asia-northeast2', "title": 'Asia Northeast 2 - Osaka'},
{"value": 'asia-northeast3', "title": 'Asia Northeast 3 - Seoul'},
{"value": 'asia-south1', "title": 'Asia South 1 - Mumbai'},
{"value": 'asia-southeast1', "title": 'Asia Southeast 1 - Singapore'},
{"value": 'asia-southeast2', "title": 'Asia Southeast 2 - Jakarta'}
].sort((a, b) => a.title.localeCompare(b.title))
}
},
inject: ['getWebsocket', 'registerMessageHandler', 'setWaitingForInput', 'requestSceneAssets', 'requestAppConfig'],

View File

@@ -12,7 +12,21 @@
<div class="character-avatar">
<!-- Placeholder for character avatar -->
</div>
<v-textarea ref="textarea" v-if="editing" v-model="editing_text" @keydown.enter.prevent="submitEdit()" @blur="cancelEdit()" @keydown.escape.prevent="cancelEdit()">
<v-textarea
ref="textarea"
v-if="editing"
v-model="editing_text"
auto-grow
:hint="autocompleteInfoMessage(autocompleting) + ', Shift+Enter for newline'"
:loading="autocompleting"
:disabled="autocompleting"
@keydown.enter.prevent="handleEnter"
@blur="autocompleting ? null : cancelEdit()"
@keydown.escape.prevent="cancelEdit()"
>
</v-textarea>
<div v-else class="character-text" @dblclick="startEdit()">
<span v-for="(part, index) in parts" :key="index" :class="{ highlight: part.isNarrative }">
@@ -45,7 +59,7 @@
<script>
export default {
props: ['character', 'text', 'color', 'message_id'],
inject: ['requestDeleteMessage', 'getWebsocket', 'createPin', 'fixMessageContinuityErrors'],
inject: ['requestDeleteMessage', 'getWebsocket', 'createPin', 'fixMessageContinuityErrors', 'autocompleteRequest', 'autocompleteInfoMessage'],
computed: {
parts() {
const parts = [];
@@ -68,11 +82,42 @@ export default {
data() {
return {
editing: false,
autocompleting: false,
editing_text: "",
hovered: false,
}
},
methods: {
handleEnter(event) {
// if ctrl -> autocomplete
// else -> submit
// shift -> newline
if (event.ctrlKey) {
this.autocompleteEdit();
} else if (event.shiftKey) {
this.editing_text += "\n";
} else {
this.submitEdit();
}
},
autocompleteEdit() {
this.autocompleting = true;
this.autocompleteRequest(
{
partial: this.editing_text,
context: "dialogue:npc",
character: this.character,
},
(completion) => {
this.editing_text += completion;
this.autocompleting = false;
},
this.$refs.textarea
)
},
cancelEdit() {
console.log('cancelEdit', this.message_id);
this.editing = false;

View File

@@ -200,7 +200,7 @@ export default {
if (defaults) {
this.client.model = defaults.model || '';
this.client.api_url = defaults.api_url || '';
this.client.max_token_length = defaults.max_token_length || 4096;
this.client.max_token_length = defaults.max_token_length || 8192;
this.client.double_coercion = defaults.double_coercion || null;
// loop and build name from prefix, checking against current clients
let name = this.clientTypes[this.client.type].name_prefix;

View File

@@ -99,6 +99,10 @@ export default {
time: parseInt(data.data.time),
num: this.total++,
generation_parameters: data.data.generation_parameters,
// immutable copy of original generation parameters
original_generation_parameters: JSON.parse(JSON.stringify(data.data.generation_parameters)),
original_prompt: data.data.prompt,
original_response: data.data.response,
})
while(this.prompts.length > this.max_prompts) {

View File

@@ -27,31 +27,42 @@
</v-list-item>
<v-list-subheader>
<v-icon>mdi-details</v-icon>Parameters
<v-btn size="x-small" variant="text" v-if="promptHasDirtyParams" color="orange" @click.stop="resetParams" prepend-icon="mdi-restore">Reset</v-btn>
</v-list-subheader>
<v-list-item v-for="(value, name) in filteredParameters" :key="name">
<v-list-item-subtitle color="grey-lighten-1">{{ name }}</v-list-item-subtitle>
<p class="text-caption text-grey">
{{ value }}
</p>
<v-list-item>
<v-text-field class="mt-1" v-for="(value, name) in filteredParameters" :key="name" v-model="prompt.generation_parameters[name]" :label="name" density="compact" variant="plain" placeholder="Value" :type="parameterType(name)">
<template v-slot:prepend-inner>
<v-icon class="mt-1" size="x-small">mdi-pencil</v-icon>
</template>
</v-text-field>
</v-list-item>
</v-list>
</v-col>
<v-col :cols="details ? 5 : 6">
<v-col :cols="details ? 6 : 7">
<v-card flat>
<v-card-title>Prompt</v-card-title>
<v-card-title>Prompt
<v-btn size="x-small" variant="text" v-if="promptHasDirtyPrompt" color="orange" @click.stop="resetPrompt" prepend-icon="mdi-restore">Reset</v-btn>
</v-card-title>
<v-card-text>
<!--
<div class="prompt-view">{{ prompt.prompt }}</div>
-->
<v-textarea :disabled="busy" density="compact" v-model="prompt.prompt" rows="10" auto-grow max-rows="22"></v-textarea>
-->
<Codemirror
v-model="prompt.prompt"
:extensions="extensions"
:style="promptEditorStyle"
></Codemirror>
</v-card-text>
</v-card>
</v-col>
<v-col :cols="details ? 5 : 6">
<v-col :cols="details ? 4 : 5">
<v-card elevation="10" color="grey-darken-3">
<v-card-title>Response
<v-progress-circular class="ml-1 mr-3" size="20" v-if="busy" indeterminate="disable-shrink"
color="primary"></v-progress-circular>
color="primary"></v-progress-circular>
<v-btn size="x-small" variant="text" v-else-if="promptHasDirtyResponse" color="orange" @click.stop="resetResponse" prepend-icon="mdi-restore">Reset</v-btn>
</v-card-title>
<v-card-text style="max-height:600px; overflow-y:auto;" :class="busy ? 'text-grey' : 'text-white'">
<div class="prompt-view">{{ prompt.response }}</div>
@@ -75,8 +86,16 @@
</template>
<script>
import { Codemirror } from 'vue-codemirror'
import { markdown } from '@codemirror/lang-markdown'
import { oneDark } from '@codemirror/theme-one-dark'
import { EditorView } from '@codemirror/view'
export default {
name: 'DebugToolPromptView',
components: {
Codemirror,
},
data() {
return {
prompt: null,
@@ -102,6 +121,17 @@ export default {
return filtered;
},
promptHasDirtyParams() {
// compoare prompt.generation_parameters with prompt.original_generation_parameters
// use json string comparison
return JSON.stringify(this.prompt.generation_parameters) !== JSON.stringify(this.prompt.original_generation_parameters);
},
promptHasDirtyPrompt() {
return this.prompt.prompt !== this.prompt.original_prompt;
},
promptHasDirtyResponse() {
return this.prompt.response !== this.prompt.original_response;
},
},
inject: [
"getWebsocket",
@@ -109,6 +139,30 @@ export default {
],
methods: {
parameterType(name) {
// to vuetify text-field type
const typ = typeof this.prompt.original_generation_parameters[name];
if(typ === 'number') {
return 'number';
} else if(typ === 'boolean') {
return 'boolean';
} else {
return 'text';
}
},
resetParams() {
this.prompt.generation_parameters = JSON.parse(JSON.stringify(this.prompt.original_generation_parameters));
},
resetPrompt() {
this.prompt.prompt = this.prompt.original_prompt;
},
resetResponse() {
this.prompt.response = this.prompt.original_response;
},
toggleDetailsLabel() {
return this.details ? 'Hide Details' : 'Show Details';
},
@@ -185,6 +239,23 @@ export default {
created() {
this.registerMessageHandler(this.handleMessage);
},
setup() {
const extensions = [
markdown(),
oneDark,
EditorView.lineWrapping
];
const promptEditorStyle = {
maxHeight: "600px"
}
return {
extensions,
promptEditorStyle,
}
}
}
</script>

View File

@@ -19,10 +19,10 @@
<div class="tile" v-for="(scene, index) in recentScenes()" :key="index">
<v-card density="compact" elevation="7" @click="loadScene(scene)" color="primary" variant="outlined">
<v-card-title>
{{ scene.name }}
{{ filenameToTitle(scene.filename) }}
</v-card-title>
<v-card-subtitle>
{{ scene.filename }}
{{ scene.name }}
</v-card-subtitle>
<v-card-text>
<div class="cover-image-placeholder">
@@ -60,6 +60,14 @@ export default {
},
methods: {
filenameToTitle(filename) {
// remove .json extension, replace _ with space, and capitalize first letter of each word
filename = filename.replace('.json', '');
return filename.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
},
hasRecentScenes() {
return this.config != null && this.config.recent_scenes != null && this.config.recent_scenes.scenes != null && this.config.recent_scenes.scenes.length > 0;
},

View File

@@ -6,7 +6,20 @@
</v-btn>
</template>
<div class="narrator-message">
<v-textarea ref="textarea" v-if="editing" v-model="editing_text" @keydown.enter.prevent="submitEdit()" @blur="cancelEdit()" @keydown.escape.prevent="cancelEdit()">
<v-textarea
ref="textarea"
v-if="editing"
v-model="editing_text"
auto-grow
:hint="autocompleteInfoMessage(autocompleting) + ', Shift+Enter for newline'"
:loading="autocompleting"
:disabled="autocompleting"
@keydown.enter.prevent="handleEnter"
@blur="autocompleting ? null : cancelEdit()"
@keydown.escape.prevent="cancelEdit()">
</v-textarea>
<div v-else class="narrator-text" @dblclick="startEdit()">
<span v-for="(part, index) in parts" :key="index" :class="{ highlight: part.isNarrative }">
@@ -36,7 +49,7 @@
<script>
export default {
props: ['text', 'message_id'],
inject: ['requestDeleteMessage', 'getWebsocket', 'createPin'],
inject: ['requestDeleteMessage', 'getWebsocket', 'createPin', 'fixMessageContinuityErrors', 'autocompleteRequest', 'autocompleteInfoMessage'],
computed: {
parts() {
const parts = [];
@@ -60,11 +73,41 @@ export default {
data() {
return {
editing: false,
autocompleting: false,
editing_text: "",
hovered: false,
}
},
methods: {
handleEnter(event) {
// if ctrl -> autocomplete
// else -> submit
// shift -> newline
if (event.ctrlKey) {
this.autocompleteEdit();
} else if (event.shiftKey) {
this.editing_text += "\n";
} else {
this.submitEdit();
}
},
autocompleteEdit() {
this.autocompleting = true;
this.autocompleteRequest(
{
partial: this.editing_text,
context: "narrative:continue",
},
(completion) => {
this.editing_text += completion;
this.autocompleting = false;
},
this.$refs.textarea
)
},
cancelEdit() {
console.log('cancelEdit', this.message_id);
this.editing = false;

View File

@@ -6,7 +6,10 @@
</v-card-title>
<v-card-text style="max-height:600px; overflow-y:scroll;">
<v-list-item v-for="(entry, index) in history" :key="index" class="text-body-2">
{{ entry.ts }} {{ entry.text }}
<v-list-item-subtitle>{{ entry.ts }}</v-list-item-subtitle>
<div class="history-entry">
{{ entry.text }}
</div>
<v-divider class="mt-1"></v-divider>
</v-list-item>
</v-card-text>
@@ -63,4 +66,8 @@ export default {
}
</script>
<style scoped></style>
<style scoped>
.history-entry {
white-space: pre-wrap;
}
</style>

View File

@@ -140,13 +140,17 @@
<CharacterSheet ref="characterSheet" />
<SceneHistory ref="sceneHistory" />
<v-text-field
<v-textarea
v-model="messageInput"
:label="inputHint"
rows="1"
auto-grow
outlined
ref="messageInput"
@keyup.enter="sendMessage"
@keydown.enter.prevent="sendMessage"
hint="Ctrl+Enter to autocomplete, Shift+Enter for newline"
:disabled="isInputDisabled()"
:loading="autocompleting"
:prepend-inner-icon="messageInputIcon()"
:color="messageInputColor()">
<template v-slot:append>
@@ -155,7 +159,7 @@
<v-icon v-else>mdi-skip-next</v-icon>
</v-btn>
</template>
</v-text-field>
</v-textarea>
</div>
<IntroView v-else
@@ -244,6 +248,10 @@ export default {
messageHandlers: [],
scene: {},
appConfig: {},
autcompleting: false,
autocompletePartialInput: "",
autocompleteCallback: null,
autocompleteFocusElement: null,
}
},
mounted() {
@@ -281,6 +289,8 @@ export default {
getTrackedWorldState: (question) => this.$refs.worldState.trackedWorldState(question),
getPlayerCharacterName: () => this.getPlayerCharacterName(),
formatWorldStateTemplateString: (templateString, chracterName) => this.formatWorldStateTemplateString(templateString, chracterName),
autocompleteRequest: (partialInput, callback, focus_element) => this.autocompleteRequest(partialInput, callback, focus_element),
autocompleteInfoMessage: (active) => this.autocompleteInfoMessage(active),
};
},
methods: {
@@ -383,6 +393,9 @@ export default {
if (data.type === 'autocomplete_suggestion') {
if(!this.autocompleteCallback)
return;
const completion = data.message;
// append completion to messageInput, add a space if
@@ -391,11 +404,23 @@ export default {
const completionStartsWithSentenceEnd = completion.startsWith('!') || completion.startsWith('.') || completion.startsWith('?') || completion.startsWith(')') || completion.startsWith(']') || completion.startsWith('}') || completion.startsWith('"') || completion.startsWith("'") || completion.startsWith("*") || completion.startsWith(",")
if (this.messageInput.endsWith(' ') || completion.startsWith(' ') || completionStartsWithSentenceEnd) {
this.messageInput += completion;
if (this.autocompletePartialInput.endsWith(' ') || completion.startsWith(' ') || completionStartsWithSentenceEnd) {
this.autocompleteCallback(completion);
} else {
this.messageInput += ' ' + completion;
this.autocompleteCallback(' ' + completion);
}
if (this.autocompleteFocusElement) {
let focus_element = this.autocompleteFocusElement;
setTimeout(() => {
focus_element.focus();
}, 200);
this.autocompleteFocusElement = null;
}
this.autocompleteCallback = null;
this.autocompletePartialInput = "";
return;
}
if (data.type === 'request_input') {
@@ -439,7 +464,26 @@ export default {
// if ctrl+enter is pressed, request autocomplete
if (event.ctrlKey && event.key === 'Enter') {
this.websocket.send(JSON.stringify({ type: 'interact', text: `!acdlg: ${this.messageInput}` }));
this.autocompleting = true
this.inputDisabled = true;
this.autocompleteRequest(
{
partial: this.messageInput,
context: "dialogue:player"
},
(completion) => {
this.inputDisabled = false
this.autocompleting = false
this.messageInput += completion;
},
this.$refs.messageInput
);
return;
}
// if shift+enter is pressed, add a newline
if (event.shiftKey && event.key === 'Enter') {
this.messageInput += "\n";
return;
}
@@ -450,6 +494,26 @@ export default {
this.waitingForInput = false;
}
},
autocompleteRequest(param, callback, focus_element) {
this.autocompleteCallback = callback;
this.autocompleteFocusElement = focus_element;
this.autocompletePartialInput = param.partial;
const param_copy = JSON.parse(JSON.stringify(param));
param_copy.type = "assistant";
param_copy.action = "autocomplete";
this.websocket.send(JSON.stringify(param_copy));
//this.websocket.send(JSON.stringify({ type: 'interact', text: `!autocomplete:${JSON.stringify(param)}` }));
},
autocompleteInfoMessage(active) {
return active ? 'Generating ...' : "Ctrl+Enter to autocomplete";
},
requestAppConfig() {
this.websocket.send(JSON.stringify({ type: 'request_app_config' }));
},

View File

@@ -107,11 +107,16 @@
@generate="content => setAndUpdateCharacterDescription(content)"
/>
<v-textarea rows="5" auto-grow v-model="characterDetails.description"
<v-textarea ref="characterDescription" rows="5" auto-grow v-model="characterDetails.description"
:color="characterDescriptionDirty ? 'info' : ''"
:disabled="characterDescriptionBusy"
:loading="characterDescriptionBusy"
@keyup.ctrl.enter.stop="autocompleteRequestCharacterDescription"
@update:model-value="queueUpdateCharacterDescription"
label="Description"
hint="A short description of the character."></v-textarea>
:hint="'A short description of the character. '+autocompleteInfoMessage(characterDescriptionBusy)"></v-textarea>
</div>
<!-- CHARACTER ATTRIBUTES -->
@@ -166,11 +171,14 @@
:label="selectedCharacterAttribute"
:color="characterAttributeDirty ? 'info' : ''"
:disabled="characterAttributeBusy"
:loading="characterAttributeBusy"
:hint="autocompleteInfoMessage(characterAttributeBusy)"
@keyup.ctrl.enter.stop="autocompleteRequestCharacterAttribute"
@update:modelValue="queueUpdateCharacterAttribute(selectedCharacterAttribute)"
v-model="characterDetails.base_attributes[selectedCharacterAttribute]">
</v-textarea>
</div>
@@ -253,6 +261,13 @@
<v-textarea rows="5" max-rows="10" auto-grow
ref="characterDetail"
:color="characterDetailDirty ? 'info' : ''"
:disabled="characterDetailBusy"
:loading="characterDetailBusy"
:hint="autocompleteInfoMessage(characterDetailBusy)"
@keyup.ctrl.enter.stop="autocompleteRequestCharacterDetail"
@update:modelValue="queueUpdateCharacterDetail(selectedCharacterDetail)"
:label="selectedCharacterDetail"
v-model="characterDetails.details[selectedCharacterDetail]">
@@ -888,6 +903,10 @@ export default {
characterDescriptionDirty: false,
characterStateReinforcerDirty: false,
characterAttributeBusy: false,
characterDetailBusy: false,
characterDescriptionBusy: false,
characterAttributeUpdateTimeout: null,
characterDetailUpdateTimeout: null,
characterDescriptionUpdateTimeout: null,
@@ -1003,6 +1022,8 @@ export default {
'openCharacterSheet',
'characterSheet',
'isInputDisabled',
'autocompleteRequest',
'autocompleteInfoMessage',
],
methods: {
show(tab, sub1, sub2, sub3) {
@@ -1083,6 +1104,8 @@ export default {
this.removePinConfirm = false;
this.deferedNavigation = null;
this.isBusy = false;
this.characterAttributeBusy = false;
this.characterDetailBusy = false;
},
exit() {
this.dialog = false;
@@ -1645,7 +1668,33 @@ export default {
this.characterList = message.data;
}
else if (message.action === 'character_details') {
// if we are currently editing an attribute, override it in the incoming data
// this fixes the annoying rubberbanding when editing an attribute
if (this.selectedCharacterAttribute) {
message.data.base_attributes[this.selectedCharacterAttribute] = this.characterDetails.base_attributes[this.selectedCharacterAttribute];
}
// if we are currently editing a detail, override it in the incoming data
// this fixes the annoying rubberbanding when editing a detail
if (this.selectedCharacterDetail) {
message.data.details[this.selectedCharacterDetail] = this.characterDetails.details[this.selectedCharacterDetail];
}
// if we are currently editing a description, override it in the incoming data
// this fixes the annoying rubberbanding when editing a description
if (this.characterDescriptionDirty) {
message.data.description = this.characterDetails.description;
}
// if we are currently editing a state reinforcement, override it in the incoming data
// this fixes the annoying rubberbanding when editing a state reinforcement
if (this.characterStateReinforcerDirty) {
message.data.reinforcements[this.selectedCharacterStateReinforcer] = this.characterDetails.reinforcements[this.selectedCharacterStateReinforcer];
}
this.characterDetails = message.data;
// select first attribute
if (!this.selectedCharacterAttribute)
this.selectedCharacterAttribute = Object.keys(this.characterDetails.base_attributes)[0];
@@ -1712,6 +1761,46 @@ export default {
}
},
// autocomplete handlers
autocompleteRequestCharacterAttribute() {
this.characterAttributeBusy = true;
this.autocompleteRequest({
partial: this.characterDetails.base_attributes[this.selectedCharacterAttribute],
context: `character attribute:${this.selectedCharacterAttribute}`,
character: this.characterDetails.name
}, (completion) => {
this.characterDetails.base_attributes[this.selectedCharacterAttribute] += completion;
this.characterAttributeBusy = false;
}, this.$refs.characterAttribute);
},
autocompleteRequestCharacterDetail() {
this.characterDetailBusy = true;
this.autocompleteRequest({
partial: this.characterDetails.details[this.selectedCharacterDetail],
context: `character detail:${this.selectedCharacterDetail}`,
character: this.characterDetails.name
}, (completion) => {
this.characterDetails.details[this.selectedCharacterDetail] += completion;
this.characterDetailBusy = false;
}, this.$refs.characterDetail);
},
autocompleteRequestCharacterDescription() {
this.characterDescriptionBusy = true;
this.autocompleteRequest({
partial: this.characterDetails.description,
context: `character detail:description`,
character: this.characterDetails.name
}, (completion) => {
this.characterDetails.description += completion;
this.characterDescriptionBusy = false;
}, this.$refs.characterDescription);
},
},
created() {
this.registerMessageHandler(this.handleMessage);

View File

@@ -14,7 +14,17 @@
<v-col cols="9">
<div v-if="tab == 'instructions'">
<v-sheet class="text-right">
<v-spacer></v-spacer>
<v-tooltip class="pre-wrap" :text="tooltipText" max-width="250" >
<template v-slot:activator="{ props }">
<v-btn v-bind="props" color="primary" @click.stop="generateCharacterDialogueInstructions" variant="text" size="x-small" prepend-icon="mdi-auto-fix">Generate</v-btn>
</template>
</v-tooltip>
</v-sheet>
<v-textarea
:loading="dialogueInstructionsBusy"
:disabled="dialogueInstructionsBusy"
placeholder="speak less formally, use more contractions, and be more casual."
v-model="dialogueInstructions" label="Acting Instructions"
:color="dialogueInstructionsDirty ? 'primary' : null"
@@ -78,6 +88,7 @@ export default {
dialogueExample: "",
dialogueInstructions: null,
dialogueInstructionsDirty: false,
dialogueInstructionsBusy: false,
updateCharacterActorTimeout: null,
}
},
@@ -86,6 +97,9 @@ export default {
return this.dialogueExamples.map((example) => {
return example.replace(this.character.name + ': ', '');
});
},
tooltipText() {
return `Automatically generate dialogue instructions for ${this.character.name}, based on their attributes and description`;
}
},
props: {
@@ -111,11 +125,24 @@ export default {
dialogue_examples: this.dialogueExamples,
}));
},
generateCharacterDialogueInstructions() {
this.dialogueInstructionsBusy = true;
this.getWebsocket().send(JSON.stringify({
type: "world_state_manager",
action: "generate_character_dialogue_instructions",
name: this.character.name,
}));
},
handleMessage(data) {
if(data.type === 'world_state_manager') {
console.log("WORLD STATE MANAGER", data);
if(data.action === 'character_actor_updated') {
this.dialogueInstructionsDirty = false;
} else if (data.action === 'character_dialogue_instructions_generated') {
this.dialogueInstructions = data.data.instructions;
this.dialogueInstructionsBusy = false;
}
}
},