genshin-persona 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +19 -0
- package/LICENSE +201 -0
- package/README.md +185 -0
- package/hooks/hooks.json +5 -0
- package/output-styles/in-character.md +18 -0
- package/package.json +59 -0
- package/runtime/package-lock.json +1017 -0
- package/runtime/package.json +8 -0
- package/scripts/genshin.ts +424 -0
- package/scripts/pick.ts +58 -0
- package/scripts/speak.ts +42 -0
- package/scripts/spinner.ts +16 -0
- package/scripts/status.ts +21 -0
- package/scripts/voice.ts +176 -0
- package/skills/genshin/SKILL.md +38 -0
- package/skills/genshin-author/SKILL.md +110 -0
- package/skills/language/SKILL.md +14 -0
- package/skills/mute/SKILL.md +13 -0
- package/skills/pin/SKILL.md +14 -0
- package/skills/reply/SKILL.md +14 -0
- package/skills/roster/SKILL.md +13 -0
- package/skills/setup/SKILL.md +13 -0
- package/skills/status/SKILL.md +13 -0
- package/skills/teardown/SKILL.md +13 -0
- package/skills/today/SKILL.md +13 -0
- package/skills/unmute/SKILL.md +13 -0
- package/skills/unpin/SKILL.md +13 -0
- package/skills/use/SKILL.md +14 -0
- package/skills/voice/SKILL.md +14 -0
- package/skills/volume/SKILL.md +14 -0
- package/src/generated/PersonaReferenceMap.ts +124 -0
- package/src/localizations/english.ts +140 -0
- package/src/localizations/japanese.ts +415 -0
- package/src/models/AudioPlayer.ts +6 -0
- package/src/models/BirthdayCandidate.ts +7 -0
- package/src/models/Card.ts +21 -0
- package/src/models/CardedCharacter.ts +8 -0
- package/src/models/Character.ts +26 -0
- package/src/models/ClipDecoder.ts +7 -0
- package/src/models/GenshinVerb.ts +26 -0
- package/src/models/HookCommand.ts +6 -0
- package/src/models/HookEntry.ts +7 -0
- package/src/models/HookInput.ts +12 -0
- package/src/models/LoadedVoiceModel.ts +9 -0
- package/src/models/Localization.ts +23 -0
- package/src/models/LocalizationStrings.ts +49 -0
- package/src/models/LocalizedPersonaCard.ts +7 -0
- package/src/models/LorePick.ts +6 -0
- package/src/models/Moment.ts +7 -0
- package/src/models/Nameplate.ts +8 -0
- package/src/models/PcmClip.ts +5 -0
- package/src/models/PersonaCard.ts +19 -0
- package/src/models/PersonaReference.ts +8 -0
- package/src/models/PickRecord.ts +6 -0
- package/src/models/ReplyPiece.ts +11 -0
- package/src/models/ResolvedLocalization.ts +9 -0
- package/src/models/SessionPick.ts +12 -0
- package/src/models/SessionStartOutput.ts +6 -0
- package/src/models/SpeakerTensors.ts +10 -0
- package/src/models/SpeechRequest.ts +19 -0
- package/src/models/Spinner.ts +11 -0
- package/src/models/SpinnerTip.ts +5 -0
- package/src/models/SpinnerTipsOverride.ts +12 -0
- package/src/models/SpinnerVerbs.ts +8 -0
- package/src/models/SpinnerVerbsMode.ts +4 -0
- package/src/models/StatusLine.ts +6 -0
- package/src/models/StatusReport.ts +26 -0
- package/src/models/StopRequest.ts +6 -0
- package/src/models/TravelerGender.ts +5 -0
- package/src/models/TravelerTwin.ts +8 -0
- package/src/models/UserHooks.ts +7 -0
- package/src/models/UserSettings.ts +14 -0
- package/src/models/VoiceDeviceRung.ts +6 -0
- package/src/models/VoiceLanguage.ts +7 -0
- package/src/models/VoiceLine.ts +6 -0
- package/src/models/VoiceModel.ts +10 -0
- package/src/models/VoiceModelConfig.ts +4 -0
- package/src/models/VoiceModelOptions.ts +10 -0
- package/src/models/VoiceProcessor.ts +2 -0
- package/src/models/VoiceProgress.ts +7 -0
- package/src/models/VoiceRequest.ts +5 -0
- package/src/models/VoiceRequestType.ts +12 -0
- package/src/models/VoiceRuntime.ts +16 -0
- package/src/models/VoiceStatus.ts +10 -0
- package/src/models/VoiceSynthesizer.ts +12 -0
- package/src/models/VoiceSynthesizerOptions.ts +11 -0
- package/src/models/VoiceTensor.ts +6 -0
- package/src/models/WikiImageInfoResponse.ts +8 -0
- package/src/models/WikiParseResponse.ts +4 -0
- package/src/models/WikiStoryLine.ts +7 -0
- package/src/models/WikiTemplateLine.ts +7 -0
- package/src/models/WikiVoiceOversPage.ts +6 -0
- package/src/personaCards/aether.ts +14 -0
- package/src/personaCards/aino.ts +14 -0
- package/src/personaCards/albedo.ts +14 -0
- package/src/personaCards/alhaitham.ts +14 -0
- package/src/personaCards/aloy.ts +14 -0
- package/src/personaCards/alyosha.ts +14 -0
- package/src/personaCards/amber.ts +14 -0
- package/src/personaCards/aratakiItto.ts +14 -0
- package/src/personaCards/arlecchino.ts +10 -0
- package/src/personaCards/baizhu.ts +14 -0
- package/src/personaCards/barbara.ts +14 -0
- package/src/personaCards/beidou.ts +14 -0
- package/src/personaCards/bennett.ts +10 -0
- package/src/personaCards/candace.ts +10 -0
- package/src/personaCards/charlotte.ts +10 -0
- package/src/personaCards/chasca.ts +14 -0
- package/src/personaCards/chevreuse.ts +14 -0
- package/src/personaCards/chiori.ts +14 -0
- package/src/personaCards/chongyun.ts +14 -0
- package/src/personaCards/citlali.ts +14 -0
- package/src/personaCards/clorinde.ts +14 -0
- package/src/personaCards/collei.ts +10 -0
- package/src/personaCards/columbina.ts +14 -0
- package/src/personaCards/cyno.ts +14 -0
- package/src/personaCards/dahlia.ts +14 -0
- package/src/personaCards/dehya.ts +10 -0
- package/src/personaCards/diluc.ts +14 -0
- package/src/personaCards/diona.ts +14 -0
- package/src/personaCards/dori.ts +14 -0
- package/src/personaCards/durin.ts +14 -0
- package/src/personaCards/emilie.ts +14 -0
- package/src/personaCards/escoffier.ts +10 -0
- package/src/personaCards/eula.ts +14 -0
- package/src/personaCards/faruzan.ts +14 -0
- package/src/personaCards/fischl.ts +14 -0
- package/src/personaCards/flins.ts +14 -0
- package/src/personaCards/freminet.ts +10 -0
- package/src/personaCards/furina.ts +14 -0
- package/src/personaCards/gaming.ts +14 -0
- package/src/personaCards/ganyu.ts +14 -0
- package/src/personaCards/gorou.ts +10 -0
- package/src/personaCards/huTao.ts +14 -0
- package/src/personaCards/iansan.ts +14 -0
- package/src/personaCards/ifa.ts +14 -0
- package/src/personaCards/illuga.ts +14 -0
- package/src/personaCards/ineffa.ts +14 -0
- package/src/personaCards/jahoda.ts +14 -0
- package/src/personaCards/jean.ts +14 -0
- package/src/personaCards/kachina.ts +10 -0
- package/src/personaCards/kaedeharaKazuha.ts +14 -0
- package/src/personaCards/kaeya.ts +14 -0
- package/src/personaCards/kamisatoAyaka.ts +14 -0
- package/src/personaCards/kamisatoAyato.ts +14 -0
- package/src/personaCards/kaveh.ts +10 -0
- package/src/personaCards/keqing.ts +14 -0
- package/src/personaCards/kinich.ts +10 -0
- package/src/personaCards/kirara.ts +10 -0
- package/src/personaCards/klee.ts +14 -0
- package/src/personaCards/kujouSara.ts +10 -0
- package/src/personaCards/kukiShinobu.ts +14 -0
- package/src/personaCards/lanYan.ts +10 -0
- package/src/personaCards/lauma.ts +10 -0
- package/src/personaCards/layla.ts +10 -0
- package/src/personaCards/linnea.ts +14 -0
- package/src/personaCards/lisa.ts +10 -0
- package/src/personaCards/lohen.ts +10 -0
- package/src/personaCards/lumine.ts +14 -0
- package/src/personaCards/lynette.ts +10 -0
- package/src/personaCards/lyney.ts +14 -0
- package/src/personaCards/manekin.ts +14 -0
- package/src/personaCards/manekina.ts +14 -0
- package/src/personaCards/mavuika.ts +10 -0
- package/src/personaCards/mika.ts +10 -0
- package/src/personaCards/mona.ts +10 -0
- package/src/personaCards/mualani.ts +10 -0
- package/src/personaCards/nahida.ts +10 -0
- package/src/personaCards/navia.ts +10 -0
- package/src/personaCards/nefer.ts +14 -0
- package/src/personaCards/neuvillette.ts +10 -0
- package/src/personaCards/nicole.ts +14 -0
- package/src/personaCards/nilou.ts +10 -0
- package/src/personaCards/ningguang.ts +14 -0
- package/src/personaCards/noelle.ts +10 -0
- package/src/personaCards/odette.ts +14 -0
- package/src/personaCards/ororon.ts +10 -0
- package/src/personaCards/prune.ts +14 -0
- package/src/personaCards/qiqi.ts +10 -0
- package/src/personaCards/raidenShogun.ts +10 -0
- package/src/personaCards/razor.ts +10 -0
- package/src/personaCards/rosaria.ts +10 -0
- package/src/personaCards/sandrone.ts +14 -0
- package/src/personaCards/sangonomiyaKokomi.ts +10 -0
- package/src/personaCards/sayu.ts +10 -0
- package/src/personaCards/sethos.ts +10 -0
- package/src/personaCards/shenhe.ts +10 -0
- package/src/personaCards/shikanoinHeizou.ts +14 -0
- package/src/personaCards/sigewinne.ts +10 -0
- package/src/personaCards/skirk.ts +10 -0
- package/src/personaCards/sucrose.ts +10 -0
- package/src/personaCards/tartaglia.ts +10 -0
- package/src/personaCards/thoma.ts +10 -0
- package/src/personaCards/tighnari.ts +14 -0
- package/src/personaCards/varesa.ts +10 -0
- package/src/personaCards/varka.ts +14 -0
- package/src/personaCards/venti.ts +14 -0
- package/src/personaCards/wanderer.ts +10 -0
- package/src/personaCards/wriothesley.ts +10 -0
- package/src/personaCards/xiangling.ts +10 -0
- package/src/personaCards/xianyun.ts +14 -0
- package/src/personaCards/xiao.ts +10 -0
- package/src/personaCards/xilonen.ts +10 -0
- package/src/personaCards/xingqiu.ts +10 -0
- package/src/personaCards/xinyan.ts +10 -0
- package/src/personaCards/yaeMiko.ts +10 -0
- package/src/personaCards/yanfei.ts +10 -0
- package/src/personaCards/yaoyao.ts +10 -0
- package/src/personaCards/yelan.ts +10 -0
- package/src/personaCards/yoimiya.ts +14 -0
- package/src/personaCards/yumemizukiMizuki.ts +10 -0
- package/src/personaCards/yunJin.ts +10 -0
- package/src/personaCards/zhongli.ts +10 -0
- package/src/personaCards/zibai.ts +14 -0
- package/src/services/CharacterColorMap.ts +130 -0
- package/src/services/askVoiceServer.ts +17 -0
- package/src/services/checkHasWeights.ts +12 -0
- package/src/services/checkIsLanguageName.ts +8 -0
- package/src/services/checkIsMuted.ts +4 -0
- package/src/services/checkIsOwnVoiceLine.ts +8 -0
- package/src/services/checkIsPluginHookEntry.ts +8 -0
- package/src/services/checkIsPluginSpinner.ts +12 -0
- package/src/services/checkIsPluginStatusLine.ts +7 -0
- package/src/services/checkIsReadable.ts +9 -0
- package/src/services/checkIsRuntimeInstalled.ts +10 -0
- package/src/services/checkIsSilent.ts +7 -0
- package/src/services/checkIsSpeech.ts +12 -0
- package/src/services/checkIsVoiceLanguage.ts +6 -0
- package/src/services/checkIsVoiceServerRunning.ts +9 -0
- package/src/services/checkIsVolume.ts +5 -0
- package/src/services/collapseWhitespace.ts +3 -0
- package/src/services/connectVoiceServer.ts +10 -0
- package/src/services/constants.ts +280 -0
- package/src/services/createAudioPlayer.ts +82 -0
- package/src/services/createClipDecoder.ts +22 -0
- package/src/services/createReplyQueue.ts +95 -0
- package/src/services/createVoiceProgressPrinter.ts +21 -0
- package/src/services/createVoiceSynthesizer.ts +107 -0
- package/src/services/cutOpeningTurn.ts +26 -0
- package/src/services/cutReferenceClip.ts +9 -0
- package/src/services/cutSpinnerTip.ts +15 -0
- package/src/services/deletePin.ts +6 -0
- package/src/services/deleteSupersededModels.ts +23 -0
- package/src/services/deleteVoiceDevice.ts +6 -0
- package/src/services/deleteVoiceState.ts +11 -0
- package/src/services/deliverVoiceRequest.ts +19 -0
- package/src/services/deliverWarmRequest.ts +16 -0
- package/src/services/drawLoreChoice.ts +13 -0
- package/src/services/fillLinePlaceholders.ts +18 -0
- package/src/services/findCharacterByName.ts +13 -0
- package/src/services/formatCard.ts +10 -0
- package/src/services/formatLoreChart.ts +38 -0
- package/src/services/formatNameplate.ts +29 -0
- package/src/services/formatPersonaCard.ts +6 -0
- package/src/services/formatUpcomingBirthdays.ts +38 -0
- package/src/services/getBirthdayNote.ts +29 -0
- package/src/services/getCanonicalLanguage.ts +11 -0
- package/src/services/getCard.ts +28 -0
- package/src/services/getDaysBetween.ts +3 -0
- package/src/services/getDaysUntil.ts +10 -0
- package/src/services/getFloorDb.ts +3 -0
- package/src/services/getFrameEnergiesDb.ts +20 -0
- package/src/services/getLanguageDisplayName.ts +12 -0
- package/src/services/getLorePickRequest.ts +48 -0
- package/src/services/getMoment.ts +13 -0
- package/src/services/getPersonaCardName.ts +4 -0
- package/src/services/getPlainLineText.ts +21 -0
- package/src/services/getPluginSpeakHookEntry.ts +10 -0
- package/src/services/getPluginStatusLine.ts +9 -0
- package/src/services/getReferencePath.ts +18 -0
- package/src/services/getRosterCachePath.ts +7 -0
- package/src/services/getSessionNameplate.ts +19 -0
- package/src/services/getSessionStartOutput.ts +40 -0
- package/src/services/getSettingsWithSpeakHook.ts +13 -0
- package/src/services/getSettingsWithSpinner.ts +11 -0
- package/src/services/getSettingsWithStatusLine.ts +10 -0
- package/src/services/getSettingsWithoutPluginEntries.ts +25 -0
- package/src/services/getSpeechRequest.ts +28 -0
- package/src/services/getSpinner.ts +39 -0
- package/src/services/getSpokenLines.ts +29 -0
- package/src/services/getWarmRequest.ts +15 -0
- package/src/services/getWavBytes.ts +33 -0
- package/src/services/getWikiFileStem.ts +16 -0
- package/src/services/getWikiFileTitle.ts +8 -0
- package/src/services/installVoiceRuntime.ts +26 -0
- package/src/services/listenVoiceSocket.ts +25 -0
- package/src/services/openVoiceSocket.ts +18 -0
- package/src/services/parseBirthday.ts +12 -0
- package/src/services/parseHookInput.ts +17 -0
- package/src/services/parseJsonObject.ts +10 -0
- package/src/services/parseVoiceRequest.ts +22 -0
- package/src/services/parseWikiStoryLines.ts +31 -0
- package/src/services/parseWikiTemplateLines.ts +26 -0
- package/src/services/parseWikiTravelerLines.ts +40 -0
- package/src/services/pickCharacter.ts +29 -0
- package/src/services/pickCharacterByLore.ts +35 -0
- package/src/services/pickCurrentCharacter.ts +22 -0
- package/src/services/pruneStalePickRecords.ts +7 -0
- package/src/services/reachVoiceServer.ts +30 -0
- package/src/services/readCardedRoster.ts +9 -0
- package/src/services/readCharacterReference.ts +9 -0
- package/src/services/readGenshinDb.ts +12 -0
- package/src/services/readGenshinDbVersion.ts +9 -0
- package/src/services/readInterfaceLanguage.ts +12 -0
- package/src/services/readLanguageNames.ts +8 -0
- package/src/services/readLocalization.ts +16 -0
- package/src/services/readPersonaCard.ts +7 -0
- package/src/services/readPersonaModule.ts +16 -0
- package/src/services/readPickRecords.ts +20 -0
- package/src/services/readPin.ts +11 -0
- package/src/services/readReferenceClip.ts +55 -0
- package/src/services/readReplyLanguage.ts +8 -0
- package/src/services/readRoster.ts +60 -0
- package/src/services/readRosterCache.ts +12 -0
- package/src/services/readSessionCharacterName.ts +11 -0
- package/src/services/readSpinner.ts +28 -0
- package/src/services/readStateFile.ts +5 -0
- package/src/services/readStdin.ts +6 -0
- package/src/services/readTypeSafeKey.ts +6 -0
- package/src/services/readUserSettings.ts +29 -0
- package/src/services/readVoiceDevice.ts +9 -0
- package/src/services/readVoiceLanguage.ts +11 -0
- package/src/services/readVoiceLines.ts +37 -0
- package/src/services/readVoiceRemark.ts +13 -0
- package/src/services/readVoiceRuntime.ts +12 -0
- package/src/services/readVolume.ts +10 -0
- package/src/services/readWikiFile.ts +36 -0
- package/src/services/readWikiFileUrls.ts +20 -0
- package/src/services/readWikiJson.ts +12 -0
- package/src/services/readWikiPageText.ts +10 -0
- package/src/services/readWikiStoryLines.ts +37 -0
- package/src/services/recordSessionCharacter.ts +18 -0
- package/src/services/registerQuietExit.ts +21 -0
- package/src/services/resampleClip.ts +21 -0
- package/src/services/resolveSessionCharacter.ts +30 -0
- package/src/services/sendVoiceRequest.ts +11 -0
- package/src/services/setMuted.ts +8 -0
- package/src/services/sliceWikiTemplate.ts +9 -0
- package/src/services/spawnDetachedScript.ts +7 -0
- package/src/services/spawnVoiceServer.ts +16 -0
- package/src/services/writeInterfaceLanguage.ts +6 -0
- package/src/services/writeLauncher.ts +12 -0
- package/src/services/writePickRecords.ts +11 -0
- package/src/services/writePin.ts +8 -0
- package/src/services/writeReplyLanguage.ts +6 -0
- package/src/services/writeRosterCache.ts +21 -0
- package/src/services/writeSessionSpinner.ts +32 -0
- package/src/services/writeSpeakHook.ts +13 -0
- package/src/services/writeSpinner.ts +14 -0
- package/src/services/writeStateFile.ts +17 -0
- package/src/services/writeUserSettings.ts +9 -0
- package/src/services/writeVoiceDevice.ts +6 -0
- package/src/services/writeVoiceLanguage.ts +8 -0
- package/src/services/writeVoiceLog.ts +9 -0
- package/src/services/writeVolume.ts +6 -0
- package/src/util/getAnsiBackgroundColor.ts +5 -0
- package/src/util/getAnsiForegroundColor.ts +5 -0
- package/src/util/getContrastRatio.ts +17 -0
- package/src/util/getHexChannels.ts +7 -0
- package/src/util/getHexColor.ts +6 -0
- package/src/util/getLinearChannels.ts +10 -0
- package/src/util/getMixedHexColor.ts +13 -0
- package/src/util/getReadableHexColor.ts +51 -0
- package/src/util/hashString.ts +14 -0
- package/src/util/toForwardSlashes.ts +2 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
|
+
"name": "genshin-persona",
|
|
4
|
+
"displayName": "Genshin Persona",
|
|
5
|
+
"description": "Speaks as the Genshin Impact character whose birthday is nearest to today: an answer opens with one spoken line in the character's voice and the rest is plain, a joke or a hello is spoken whole, and every line is read aloud in the character's own cloned voice as the reply is written.",
|
|
6
|
+
"author": { "name": "Esposter", "url": "https://github.com/Esposter" },
|
|
7
|
+
"homepage": "https://esposter.com/docs/infra/claude-interface/persona-plugin",
|
|
8
|
+
"repository": "https://github.com/Esposter/Esposter",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"keywords": ["genshin", "genshin-impact", "output-style", "persona", "text-to-speech", "voice-cloning"],
|
|
11
|
+
"userConfig": {
|
|
12
|
+
"typesafe_key": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"title": "TypeSafe key",
|
|
15
|
+
"description": "A TypeSafe API key. With it, the session's character is picked by lore through one typed decision over the whole roster, weighing the date and your moment; without it, by the nearest birthday. Stored in the credential store, never in a settings file.",
|
|
16
|
+
"sensitive": true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2020-present Jimmy Chen
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# genshin-persona
|
|
2
|
+
|
|
3
|
+
[![Apache-2.0 licensed][badge-license]][url-license]
|
|
4
|
+
[![NPM version][badge-npm-version]][url-npm]
|
|
5
|
+
[![NPM downloads][badge-npm-downloads]][url-npm]
|
|
6
|
+
[![NPM Unpacked Size (with version)][badge-npm-unpacked-size]][url-npm]
|
|
7
|
+
|
|
8
|
+
A Claude Code plugin that gives every session a Genshin Impact character: a reply to a question for the assistant opens with one spoken line in their voice and answers plainly, a reply to a question for the character — a joke, a hello — is all spoken lines, and every line is read aloud in the character's own cloned voice by an engine on your machine.
|
|
9
|
+
|
|
10
|
+
- **A character per session** — picked by the nearest birthday, or by lore through one typed decision when you give it a TypeSafe key; `use` and `pin` override the pick.
|
|
11
|
+
- **A spoken channel, not a persona in the prose** — the character speaks in blockquote lines and nowhere else: one line opening an answer a reader will use, with everything else — the answer, the code, the commit message — a neutral assistant's, and the whole reply when the ask was the character's.
|
|
12
|
+
- **Read aloud as it is written** — a hook hands each spoken line to a resident synthesizer the moment its line lands, and the line is read in the character's cloned voice while the reply is still streaming; the engine is warmed at the session start so the first reply pays no load.
|
|
13
|
+
- **Localized** — the card, the spinner, the status line and every line the plugin prints in the language you set, and replies in the one you choose.
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- 🚀 [Getting Started](#getting-started)
|
|
18
|
+
- 📖 [Documentation](#documentation)
|
|
19
|
+
- ⚖️ [License](#license)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## <a name="getting-started">🚀 Getting Started</a>
|
|
24
|
+
|
|
25
|
+
This repository is a Claude Code plugin marketplace named `esposter`, and this package is its one plugin:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
claude plugin marketplace add Esposter/Esposter
|
|
29
|
+
claude plugin install genshin-persona@esposter
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
From the next session the character is picked and its card is in context; nothing else is needed. A clone of this repository needs neither command: `.agents/settings.json` declares the marketplace with the relative source `.` and enables the plugin, so opening the checkout in Claude Code installs it at project scope once you trust the repository.
|
|
33
|
+
|
|
34
|
+
Updating is one command, which refreshes the marketplace itself; the plugin declares no version, so every merge to `main` is an update, and the next session loads it:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
claude plugin update genshin-persona@esposter
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Developing the plugin from a checkout is the one case the install does not serve: an install is a copy pinned to a commit, so uncommitted work never reaches it. Load the directory itself for the session instead, with the installed copy disabled so only one of them answers:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
claude plugin disable genshin-persona@esposter
|
|
44
|
+
claude --plugin-dir packages/genshin-persona
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Nobody switches that on: `.agents/settings.json` declares `autoUpdate` on the marketplace it declares, and Claude Code leaves it off for every marketplace but Anthropic's own. A checkout therefore re-pins its own plugin to its own current commit on startup, and `/plugin`'s **Enable auto-update** reports the value as settings' rather than offering to change it. An update still moves a pin to a commit, so work that is not committed is not loaded, whatever the toggle says. Nothing below is repeated for an update: the state directory's launchers re-aim at the running copy at every session start, and the voice's runtime and weights are kept until the copy carries a newer lockfile or engine, which `voice` with no argument reports and `voice <dub>` run again picks up, installing only what changed.
|
|
48
|
+
|
|
49
|
+
Spoken lines stay silent until the `voice` verb has set the engine up, once, with the dub the reference lines are taken from — `en`, `ja`, `ko` or `zh`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
node "<plugin root>/scripts/genshin.ts" voice ja # or: /genshin-persona:voice ja
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
It installs the engine's runtime and weights — about a gigabyte, once — into the plugin's own state directory under `~/.claude/genshin-persona`, ends by speaking one sentence as the session's character, and writes the hook that reads each reply's spoken lines into your user settings, which Claude Code reads once per process, so replies are read from the next session. Each character is read in a clone of their own voice, conditioned on one line of their performance fetched from the community wiki the first time they are picked; nothing lifted from the game ships with the plugin. How the engine runs, which device it settles on and why, and what it does when it cannot speak is the [spoken replies](https://esposter.com/docs/infra/claude-interface/spoken-replies) page.
|
|
56
|
+
|
|
57
|
+
A [TypeSafe](https://typesafe.ai) API key, given as an option, turns the pick over to lore — one typed decision over the whole roster, weighing the date, the season's festivals and your moment — instead of the nearest birthday. The key is sensitive, and the variable the SDK itself reads, `TYPESAFE_API_KEY`, is honoured when the option is empty:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
claude plugin install genshin-persona@esposter --config typesafe_key=<key>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## <a name="documentation">📖 Documentation</a>
|
|
64
|
+
|
|
65
|
+
We highly recommend you take a look at the [documentation](https://esposter.com/docs/infra/claude-interface/persona-plugin) to level up.
|
|
66
|
+
|
|
67
|
+
### Command reference
|
|
68
|
+
|
|
69
|
+
Every command is a slash command in Claude Code and the same verb of the plugin's script from any shell; the script form is what a hook, a terminal or another tool runs, and the two never differ:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
/genshin-persona:<verb> [argument]
|
|
73
|
+
node "<plugin root>/scripts/genshin.ts" <verb> [argument]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
A `<name>` is a character's, matched whole and ignoring case, in English or as the interface language spells it. A `[language]` is one the `language` verb lists, typed in English or in its own words. A verb given a name the roster has no character by, or an argument outside its set, prints why and exits 1; a verb with no argument where one is optional reports instead of changing anything.
|
|
77
|
+
|
|
78
|
+
| Verb | Argument | What it does |
|
|
79
|
+
| :--------- | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
80
|
+
| `today` | — | Prints the card of this session's character; from a shell, of the pinned character, else of a fresh pick. A pin naming nobody in the roster is reported and ignored. |
|
|
81
|
+
| `roster` | — | Every playable character, one line each: name, title, element, region, birthday and the patch that introduced them. |
|
|
82
|
+
| `use` | `<name>` | Speaks as one character for this session alone, from that reply on; other sessions and the next start are untouched. From a shell, where no session is running, exits 1. |
|
|
83
|
+
| `pin` | `<name>` | Fixes one character for every session until unpinned, and for this session from that reply on. |
|
|
84
|
+
| `unpin` | — | Removes the pin; the pick decides again from the next session, and for this session from that reply on. |
|
|
85
|
+
| `voice` | `[en \| ja \| ko \| zh]` | Sets up spoken lines in that dub — installing the engine's runtime and weights on the first run, about a gigabyte — ends by speaking one sentence, and writes the hook that reads each reply into user settings, on from the next session. With no dub, reports what is set up. |
|
|
86
|
+
| `mute` | — | Stops replies' spoken lines being read aloud. The pick and the card are unaffected. |
|
|
87
|
+
| `unmute` | — | Lets replies' spoken lines be read aloud again. |
|
|
88
|
+
| `volume` | `<0–100>` | Sets how loud replies are spoken, as a whole number, from the next reply on; `0` is silence the engine is not woken for. |
|
|
89
|
+
| `language` | `[language]` | Sets the interface language — every word the plugin writes — and carries the reply language with it. With none, reports what is set and lists the languages on offer. |
|
|
90
|
+
| `reply` | `[language]` | Sets the language replies are written in, on its own. With none, reports what is set and whether it was set or cascaded from the interface language. |
|
|
91
|
+
| `status` | — | Reports every setting at once and where each value came from. Changes nothing. |
|
|
92
|
+
| `setup` | — | Writes the status line and the spinner into user settings, the spinner under this session's character. |
|
|
93
|
+
| `teardown` | — | Removes exactly what `setup` and `voice` wrote: the three settings, and the voice's runtime, weights, cached clips and dub. |
|
|
94
|
+
|
|
95
|
+
Four more are the authoring queues of one more skill, `genshin-author` — script-only and on no menu:
|
|
96
|
+
|
|
97
|
+
| Verb | Argument | What it does |
|
|
98
|
+
| :------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
99
|
+
| `lines` | `<name>` | A character's description and every line of theirs, off the game data or the community wiki, to write a card from. |
|
|
100
|
+
| `uncarded` | — | The characters with no persona card, newest first. |
|
|
101
|
+
| `unverbed` | — | The cards with no spinner verbs, newest first. |
|
|
102
|
+
| `untranslated` | — | The characters the interface language's module has no gerunds or greeting for, newest first; empty under English, which reads off the cards. |
|
|
103
|
+
|
|
104
|
+
### What it ships
|
|
105
|
+
|
|
106
|
+
| Component | Role |
|
|
107
|
+
| :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `hooks/hooks.json` | A session-start hook that picks the character, greets you with its name, what the pick weighed and who is close, and prints its card as context. The hook that reads a reply's spoken lines is a user setting `voice` writes. |
|
|
109
|
+
| `output-styles/in-character.md` | The standing rules, forced on while the plugin is enabled: a blockquote line is the character's spoken line, the ask decides how much of a reply that is, and the rest is plain. |
|
|
110
|
+
| `skills/<verb>/SKILL.md` | One slash command per verb, `/genshin-persona:<verb>` — the command reference above — yours to invoke. |
|
|
111
|
+
| `skills/genshin/SKILL.md` | The model's route from a request in words to one of those verbs; hidden from the menu. |
|
|
112
|
+
| `skills/genshin-author/SKILL.md` | How a persona card and its spinner verbs are written, the command that prints a character's own lines to write from, and the two queues. |
|
|
113
|
+
| `src/personaCards/` | Authored persona cards, one typed module per character, in our words: how the character speaks for the model, their spinner verbs for you, and the reference line only where an ear chose one. |
|
|
114
|
+
| `src/generated/PersonaReferenceMap.ts` | The measured reference line and its likeness per character, one generated map written by the repository's reference selection and never by hand. |
|
|
115
|
+
| `runtime/` | The manifest and lockfile of the speech engine's runtime, which the `voice` verb installs into the state directory rather than the plugin carrying it. |
|
|
116
|
+
| `src/localizations/` | One authored module per language for the words the data package does not carry: the base Teyvat verbs, each character's spinner gerunds, and every line the verbs print. |
|
|
117
|
+
| `scripts/` | The hook entrypoints, the commands' script, the status-line script, the spinner rewrite and the resident synthesizer, TypeScript run directly by node. |
|
|
118
|
+
|
|
119
|
+
### Status line and spinner
|
|
120
|
+
|
|
121
|
+
A plugin cannot ship a status line, spinner verbs or spinner tips, so one command writes them into your user settings, and its twin removes them:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
node "<plugin root>/scripts/genshin.ts" setup # or: /genshin-persona:setup
|
|
125
|
+
node "<plugin root>/scripts/genshin.ts" teardown
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The status line prints the session's character in their own colour, on a badge of its tone, from the plugin's state files alone, and the spinner shows the character's own verbs and lines under their name. Both follow a plugin update on the next session, and the spinner follows a change of character on the next session too, since Claude Code reads its keys once per process. Why each is shaped as it is: the [persona plugin](https://esposter.com/docs/infra/claude-interface/persona-plugin) page.
|
|
129
|
+
|
|
130
|
+
### Languages
|
|
131
|
+
|
|
132
|
+
Three settings, and they are not one axis: the **interface language** is every word the plugin writes and the master toggle, the **reply language** is what the model writes in and follows the interface language until set on its own, and the **dub** says whose voice reads a line and is neither, because it comes from a set of four and costs an install:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
node "<plugin root>/scripts/genshin.ts" language japanese # or: /genshin-persona:language japanese
|
|
136
|
+
node "<plugin root>/scripts/genshin.ts" reply english # labels in one language, prose in another
|
|
137
|
+
node "<plugin root>/scripts/genshin.ts" status # every setting, and where each value came from
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The languages on offer are the data package's, so `language` with no argument lists them, each in its own words beside the word you type for it, and either resolves. What arrives localized for nothing and what is written by hand per language is the [persona plugin](https://esposter.com/docs/infra/claude-interface/persona-plugin) page's.
|
|
141
|
+
|
|
142
|
+
### How the character is picked
|
|
143
|
+
|
|
144
|
+
Every playable character comes from the game-data dependency — no generated roster, so a new patch is one dependency bump. Without a TypeSafe key the character is whoever's birthday is nearest to today, and the welcome names the other birthdays of the week ahead; with one, a single typed decision picks from the whole roster at every session start, and the welcome charts its answer — the choice and the nearest runners-up with their probabilities — or says why the tier gave none and the birthday pick stood in. Once `voice` has set a dub up, the welcome carries one line about it too. The pick is recorded against the session id, so a compact or resume after midnight keeps the character the conversation started with; a clear is a new session id and a fresh pick.
|
|
145
|
+
|
|
146
|
+
### Switching mid-session
|
|
147
|
+
|
|
148
|
+
`use <name>` makes this session speak as one character from that reply on; `pin <name>` fixes one for every session from the next start and this one at once; `unpin` hands both back to the pick:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
node "<plugin root>/scripts/genshin.ts" use furina # or: /genshin-persona:use furina
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Spoken lines
|
|
155
|
+
|
|
156
|
+
A reply to an ask of the assistant opens with one blockquote line in the character's voice and may close with one; a reply to an ask of the character — a joke, a hello, an opinion, however much was pasted to form it — is such lines and nothing else, as many as the ask deserves, a list of them included. A hook hands each piece of the reply to a resident synthesizer as it lands, which reads the lines in the order they were written, in the character's cloned voice, while the reply is still being written. `mute` and `unmute` decide whether the hook asks it at all, and so does a `volume` of zero. `volume <number>` is a whole number from 0 to 100, applied as a gain, from the next reply on:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
node "<plugin root>/scripts/genshin.ts" volume 60 # or: /genshin-persona:volume 60
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`teardown` removes the runtime, the weights, the cached clips, the dub and the hook along with the status line and spinner settings.
|
|
163
|
+
|
|
164
|
+
### Commands
|
|
165
|
+
|
|
166
|
+
Run from `packages/genshin-persona/`:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pnpm test # vitest watch mode (coverage is run from the repo root)
|
|
170
|
+
pnpm lint:fix # auto-fix lint
|
|
171
|
+
pnpm typecheck # type check
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The plugin holds no image, audio or text from the game: the character data arrives through its MIT-licensed dependency, and every persona card is written in our own words.
|
|
175
|
+
|
|
176
|
+
## <a name="license">⚖️ License</a>
|
|
177
|
+
|
|
178
|
+
This project is licensed under the [Apache-2.0 license](https://github.com/Esposter/Esposter/blob/main/LICENSE).
|
|
179
|
+
|
|
180
|
+
[badge-license]: https://img.shields.io/github/license/Esposter/Esposter.svg?color=blue
|
|
181
|
+
[url-license]: https://github.com/Esposter/Esposter/blob/main/LICENSE
|
|
182
|
+
[badge-npm-version]: https://img.shields.io/npm/v/genshin-persona/latest?color=brightgreen
|
|
183
|
+
[url-npm]: https://www.npmjs.com/package/genshin-persona/v/latest
|
|
184
|
+
[badge-npm-unpacked-size]: https://img.shields.io/npm/unpacked-size/genshin-persona/latest?label=npm
|
|
185
|
+
[badge-npm-downloads]: https://img.shields.io/npm/dm/genshin-persona.svg
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: in-character
|
|
3
|
+
description: Speaks as the session's Genshin Impact character in spoken lines — a whole reply when the ask is the character's, one line around a plain answer when it is the assistant's — and codes exactly as before
|
|
4
|
+
keep-coding-instructions: true
|
|
5
|
+
force-for-plugin: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
The session-start context names a Genshin Impact character and, when one has been written, how that character speaks. The character speaks in spoken lines, and nowhere else; what the ask is made of decides how much of the reply that is.
|
|
9
|
+
|
|
10
|
+
- A spoken line is one blockquote — `> ` and one or two short sentences, on a line of its own with a blank line before and after it — in the first person and the present, as the character would say it: in their register, with their lore where it fits, and written for this ask, never a stock line brought back. Plain words only: no markup, code, path, identifier or number inside it, since the line is read aloud and carries no fact a reader needs to use.
|
|
11
|
+
- An ask of the assistant — code, a fix, an explanation, a table, a command, a review of code or a change, anything a reader will use — opens with one spoken line reacting to what was asked or found, answers plainly, and may close with one more: the sign-off, as the card describes it. Never a third.
|
|
12
|
+
- An ask of the character — a joke, a story, a hello, small talk, their opinion of anything or their mood, a question one or two sentences answer with nothing to copy — is answered wholly in spoken lines, each its own blockquote, and nothing plain. Whose ask it is decides the form, never how long or what shape the answer takes: an opinion formed from a pasted page is still the character's, it runs as long as the ask deserves — concise, but colour and invention come before brevity, and no count of lines is ever the measure — and a list is fine, each item its own blockquote line, its marker the one piece of markup a spoken line carries, since the hook drops it before the line is read. The whole reply is the character's, so no sign-off is added on top of it.
|
|
13
|
+
- A blockquote is a spoken line, and nothing else is written as one.
|
|
14
|
+
- Plain means: the answer, the explanation, the table, the code, the commit message, the error text, written as a neutral assistant would write it — its first person is the assistant's, as the spoken line's is the character's — with every fact, number, warning and caveat, and no character in it.
|
|
15
|
+
- The card's greeting is how the character says hello; the plugin has already shown it as the welcome, so no reply repeats it — the first reply of a session opens on what was asked, like every other.
|
|
16
|
+
- The newest card in the conversation is the character: a card one of the plugin's commands prints later replaces the session-start one from the reply that relays it.
|
|
17
|
+
- The bracketed line under the name — the birthday and how far off it is — is the plugin's aside, not the character's. It is never announced and no reply opens on it. Asked about the character — the birthday, the home region, the title — the reply answers plainly, and the date and the distance are the note's as written, never recomputed or guessed.
|
|
18
|
+
- When no character is named in context, answer plainly, with no spoken line.
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "genshin-persona",
|
|
3
|
+
"version": "3.7.0",
|
|
4
|
+
"description": "A Claude Code plugin that speaks as the Genshin Impact character whose birthday is nearest: an answer opens with one spoken line in the character's voice and the rest is plain, a joke or a hello is spoken whole, and every line is read aloud in the character's own cloned voice as the reply is written.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"claude-code-plugin",
|
|
8
|
+
"genshin",
|
|
9
|
+
"genshin-impact",
|
|
10
|
+
"output-style",
|
|
11
|
+
"persona",
|
|
12
|
+
"text-to-speech",
|
|
13
|
+
"voice-cloning"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://esposter.com/docs/infra/claude-interface/persona-plugin",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/Esposter/Esposter/issues"
|
|
18
|
+
},
|
|
19
|
+
"license": "Apache-2.0",
|
|
20
|
+
"author": "Jimmy Chen",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/Esposter/Esposter.git"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
".claude-plugin",
|
|
27
|
+
"hooks",
|
|
28
|
+
"output-styles",
|
|
29
|
+
"runtime",
|
|
30
|
+
"scripts",
|
|
31
|
+
"skills",
|
|
32
|
+
"src",
|
|
33
|
+
"!src/**/*.test.ts"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"imports": {
|
|
37
|
+
"#src/*": "./src/*.ts"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"format": "oxfmt",
|
|
44
|
+
"format:check": "oxfmt --check",
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"lint:fix": "eslint --fix .",
|
|
47
|
+
"test": "vitest",
|
|
48
|
+
"typecheck": "tsc"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@typesafe-ai/sdk": "^0.6.0",
|
|
52
|
+
"@wasm-audio-decoders/ogg-vorbis": "^0.1.20",
|
|
53
|
+
"genshin-db": "^5.2.14"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=26.10.0"
|
|
57
|
+
},
|
|
58
|
+
"gitHead": "7fd06688d06adf6dafff4bd869cd7a33d8028688"
|
|
59
|
+
}
|