@ramarivera/coding-buddy 0.4.0-alpha.9 → 0.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/marketplace.json +45 -0
- package/.claude-plugin/plugin.json +30 -0
- package/LICENSE +1 -1
- package/README.md +96 -45
- package/adapters/omp/commands.ts +201 -0
- package/adapters/omp/context.ts +22 -0
- package/adapters/omp/events.ts +551 -0
- package/adapters/omp/identity.ts +10 -0
- package/adapters/omp/index.ts +39 -0
- package/adapters/omp/logger.ts +52 -0
- package/adapters/omp/prompt.ts +60 -0
- package/adapters/omp/renderers.ts +73 -0
- package/adapters/omp/storage.ts +25 -0
- package/adapters/omp/ui.ts +85 -0
- package/adapters/pi/commands.ts +64 -37
- package/adapters/pi/events.ts +147 -72
- package/adapters/pi/index.ts +9 -4
- package/adapters/pi/storage.ts +14 -285
- package/adapters/pi/ui.ts +56 -5
- package/adapters/shared/file-storage.ts +526 -0
- package/{adapters/claude/install → cli}/backup.ts +130 -33
- package/cli/buddy-shell.ts +1 -1
- package/{adapters/claude/install → cli}/disable.ts +19 -32
- package/cli/doctor.ts +231 -0
- package/{adapters/claude/install → cli}/hunt.ts +7 -9
- package/cli/index.ts +30 -26
- package/{adapters/claude/install → cli}/install.ts +65 -83
- package/{adapters/claude/install → cli}/pick.ts +136 -57
- package/{adapters/claude/install → cli}/settings.ts +2 -2
- package/{adapters/claude/install → cli}/show.ts +4 -4
- package/{adapters/claude/install → cli}/test-statusline.sh +2 -2
- package/{adapters/claude/install → cli}/test-statusline.ts +21 -11
- package/cli/tui.tsx +106 -17
- package/{adapters/claude/install → cli}/uninstall.ts +40 -47
- package/cli/upgrade.ts +46 -13
- package/cli/validate-species.ts +209 -0
- package/cli/verify.ts +3 -3
- package/core/achievements.ts +12 -20
- package/core/art-data.ts +26 -0
- package/core/command-service.ts +99 -97
- package/core/engine.ts +83 -1
- package/core/ports.ts +10 -0
- package/core/reactions.ts +533 -95
- package/core/slot-slug.ts +22 -0
- package/{adapters/claude/hooks → hooks}/buddy-comment.sh +22 -9
- package/hooks/file-type-react.sh +403 -0
- package/hooks/hooks.json +52 -0
- package/hooks/mood-react.sh +210 -0
- package/{adapters/claude/hooks → hooks}/name-react.sh +3 -4
- package/hooks/react.sh +1364 -0
- package/hooks/suggest.sh +55 -0
- package/package.json +70 -31
- package/scripts/gen-emoji-widths.ts +34 -0
- package/scripts/paths.sh +33 -2
- package/scripts/postinstall.cjs +42 -0
- package/scripts/snapshot-statusline.sh +54 -0
- package/server/achievements.ts +1419 -15
- package/server/art.ts +450 -1
- package/server/award-xp.ts +48 -0
- package/server/check-suggestions.ts +102 -0
- package/server/consolidate.ts +33 -0
- package/{adapters/claude/server → server}/index.ts +556 -95
- package/server/mcp-launcher.sh +16 -6
- package/server/memory.ts +404 -0
- package/server/mood.ts +254 -0
- package/server/path.ts +70 -18
- package/server/shift-mood.ts +43 -0
- package/server/state.ts +552 -3
- package/server/suggestions.ts +335 -0
- package/server/theme.ts +53 -0
- package/server/xp.ts +435 -0
- package/{adapters/claude/skills → skills}/buddy/SKILL.md +36 -7
- package/statusline/buddy-status.sh +402 -0
- package/statusline/combined-status.sh +135 -0
- package/statusline/emoji-widths.data +4 -0
- package/adapters/claude/hooks/hooks.json +0 -35
- package/adapters/claude/hooks/react.sh +0 -207
- package/adapters/claude/install/doctor.ts +0 -172
- package/adapters/claude/plugin/marketplace.json +0 -40
- package/adapters/claude/plugin/plugin.json +0 -26
- package/adapters/claude/rendering/art.ts +0 -264
- package/adapters/claude/server/instructions.ts +0 -24
- package/adapters/claude/server/path.ts +0 -12
- package/adapters/claude/server/resources.ts +0 -38
- package/adapters/claude/statusline/buddy-status.sh +0 -408
- package/adapters/claude/storage/achievements.ts +0 -253
- package/adapters/claude/storage/identity.ts +0 -13
- package/adapters/claude/storage/paths.ts +0 -33
- package/adapters/claude/storage/settings.ts +0 -91
- package/adapters/claude/storage/state.ts +0 -365
- package/adapters/pi/README.md +0 -83
- package/adapters/pi/tools.ts +0 -6
- package/server/engine.ts +0 -1
- package/server/reactions.ts +0 -1
package/core/reactions.ts
CHANGED
|
@@ -1,32 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
* Reaction templates — species-aware buddy responses to events
|
|
3
|
-
*/
|
|
1
|
+
import type { BuddyStats, Species, Rarity } from "./engine.ts";
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
export type ReactionReason =
|
|
4
|
+
| "hatch" | "pet" | "error" | "test-fail" | "large-diff" | "turn" | "idle"
|
|
5
|
+
| "commit" | "push" | "merge-conflict" | "branch" | "rebase" | "stash" | "tag"
|
|
6
|
+
| "late-night" | "early-morning" | "long-session" | "marathon" | "friday" | "weekend" | "monday"
|
|
7
|
+
| "regex-file" | "css-file" | "sql-file" | "docker-file" | "ci-file" | "lock-file"
|
|
8
|
+
| "env-file" | "test-file" | "doc-file" | "config-file" | "binary-file" | "gitignore"
|
|
9
|
+
| "makefile" | "readme" | "package-file" | "proto-file"
|
|
10
|
+
| "lint-fail" | "type-error" | "build-fail" | "security-warning" | "deprecation"
|
|
11
|
+
| "frustrated" | "happy" | "stuck" | "sarcastic"
|
|
12
|
+
| "many-edits" | "delete-file" | "large-file" | "create-file"
|
|
13
|
+
| "all-green" | "deploy" | "release" | "coverage"
|
|
14
|
+
| "debug-loop" | "write-spree" | "search-heavy"
|
|
15
|
+
| "snark" | "chaos" | "patience" | "debugging" | "wisdom"
|
|
16
|
+
| "late-night-error" | "late-night-commit" | "friday-push"
|
|
17
|
+
| "marathon-error" | "weekend-conflict" | "build-after-push" | "marathon-test-fail"
|
|
18
|
+
| "recovery-from-error" | "recovery-from-test-fail"
|
|
19
|
+
| "recovery-from-build-fail" | "recovery-from-merge-conflict"
|
|
20
|
+
| "lang-python" | "lang-typescript" | "lang-rust" | "lang-go"
|
|
21
|
+
| "lang-java" | "lang-ruby" | "lang-php" | "lang-c"
|
|
22
|
+
| "lang-cpp" | "lang-haskell" | "lang-swift" | "lang-elixir"
|
|
23
|
+
| "lang-zig" | "lang-kotlin"
|
|
24
|
+
| "streak-3" | "streak-5" | "streak-10" | "streak-20"
|
|
25
|
+
| "new-year" | "valentines" | "pi-day" | "april-fools"
|
|
26
|
+
| "halloween" | "christmas" | "new-years-eve" | "spooky-season"
|
|
27
|
+
| "success";
|
|
6
28
|
|
|
7
|
-
|
|
29
|
+
export interface ReactionContext {
|
|
30
|
+
line?: number;
|
|
31
|
+
count?: number;
|
|
32
|
+
lines?: number;
|
|
33
|
+
files?: number;
|
|
34
|
+
branch?: string;
|
|
35
|
+
hour?: number;
|
|
36
|
+
elapsed?: number;
|
|
37
|
+
extension?: string;
|
|
38
|
+
}
|
|
8
39
|
|
|
9
40
|
const NAME_REACTIONS: Partial<Record<Species, string[]>> = {
|
|
10
|
-
dragon: ["*one eye opens slowly*", "...you called?", "*smoke curls from nostril* yes."
|
|
11
|
-
owl: ["*swivels head 180°*", "*blinks once, deliberately*", "hm."
|
|
12
|
-
cat: ["*ear flicks*", "...what.", "*ignores you, but heard*"
|
|
41
|
+
dragon: ["*one eye opens slowly*", "...you called?", "*smoke curls from nostril* yes."],
|
|
42
|
+
owl: ["*swivels head 180°*", "*blinks once, deliberately*", "hm."],
|
|
43
|
+
cat: ["*ear flicks*", "...what.", "*ignores you, but heard*"],
|
|
13
44
|
duck: ["*quack*", "*looks up mid-waddle*", "*attentive duck noises*"],
|
|
14
45
|
ghost: ["*materialises*", "...boo?", "*phases closer*"],
|
|
15
46
|
robot: ["NAME DETECTED.", "*whirrs attentively*", "STANDING BY."],
|
|
16
47
|
capybara: ["*barely moves*", "*blinks slowly*", "...yes, friend."],
|
|
17
48
|
axolotl: ["*gill flutter*", "*smiles gently*", "oh! hello."],
|
|
18
49
|
blob: ["*jiggles*", "*oozes toward you*", "*wobbles excitedly*"],
|
|
19
|
-
turtle: ["*slowly extends neck*", "...you called?", "*ancient eyes open*"
|
|
20
|
-
goose: ["HONK.", "*necks aggressively*", "*
|
|
21
|
-
octopus: ["*eight eyes open*", "*curls an arm toward you*", "
|
|
22
|
-
penguin: ["*adjusts tie*", "*dignified waddle*", "
|
|
23
|
-
snail: ["*slow head extension*", "...mmm?", "*
|
|
24
|
-
cactus: ["*stands silent*", "...hm.", "*spine twitches*"
|
|
25
|
-
rabbit: ["*ears perk up*", "*nose twitches*", "yes?"
|
|
26
|
-
mushroom: ["*releases a tiny spore*", "*cap tilts*", "
|
|
27
|
-
chonk: ["*barely opens one eye*", "...mrrp?", "*yawns heavily*"
|
|
50
|
+
turtle: ["*slowly extends neck*", "...you called?", "*ancient eyes open*"],
|
|
51
|
+
goose: ["HONK.", "*necks aggressively*", "*honks in recognition*"],
|
|
52
|
+
octopus: ["*eight eyes open*", "*curls an arm toward you*", "...yes, friend?"],
|
|
53
|
+
penguin: ["*adjusts tie*", "*dignified waddle*", "...yes, quite?"],
|
|
54
|
+
snail: ["*slow head extension*", "...mmm?", "*antenna twitches*"],
|
|
55
|
+
cactus: ["*stands silent*", "...hm.", "*spine twitches*"],
|
|
56
|
+
rabbit: ["*ears perk up*", "*nose twitches*", "yes?"],
|
|
57
|
+
mushroom: ["*releases a tiny spore*", "*cap tilts*", "...yes?"],
|
|
58
|
+
chonk: ["*barely opens one eye*", "...mrrp?", "*yawns heavily*"],
|
|
28
59
|
};
|
|
29
60
|
|
|
61
|
+
const DEFAULT_NAME_REACTIONS = ["*perks up*", "...yes?", "*looks your way*"];
|
|
30
62
|
const SUCCESS_REACTIONS: Partial<Record<Species, string[]>> = {
|
|
31
63
|
dragon: ["*nods, barely*", "...acceptable.", "*gold eyes gleam*", "as expected."],
|
|
32
64
|
owl: ["*satisfied hoot*", "knowledge confirmed.", "*nods sagely*", "as the tests have spoken."],
|
|
@@ -34,124 +66,519 @@ const SUCCESS_REACTIONS: Partial<Record<Species, string[]>> = {
|
|
|
34
66
|
duck: ["*celebratory quacking*", "*waddles in circles*", "quack!", "*happy duck noises*"],
|
|
35
67
|
robot: ["OBJECTIVE: COMPLETE.", "*satisfying beep*", "NOMINAL.", "WITHIN ACCEPTABLE PARAMETERS."],
|
|
36
68
|
capybara: ["*maximum chill maintained*", "*nods once*", "good vibes.", "see? no panic needed."],
|
|
37
|
-
ghost: ["*drifts in quiet approval*", "not bad for the living.", "*soft spectral nod*"
|
|
69
|
+
ghost: ["*drifts in quiet approval*", "not bad for the living.", "*soft spectral nod*"],
|
|
38
70
|
axolotl: ["*happy gill flutter*", "*beams*", "you did it!", "*blushes pink*"],
|
|
39
71
|
blob: ["*jiggles happily*", "*gleams*", "yay!", "*bounces*"],
|
|
40
|
-
turtle: ["*satisfied shell settle*", "as the ancients foretold.", "*slow approving nod*"
|
|
41
|
-
goose: ["*victorious honk*", "HONK OF APPROVAL.", "*struts triumphantly*"
|
|
42
|
-
octopus: ["*turns gentle blue*", "*arms applaud in sync*", "excellent, from all angles."
|
|
43
|
-
penguin: ["*polite applause*", "quite good, quite good.", "*nods approvingly*"
|
|
72
|
+
turtle: ["*satisfied shell settle*", "as the ancients foretold.", "*slow approving nod*"],
|
|
73
|
+
goose: ["*victorious honk*", "HONK OF APPROVAL.", "*struts triumphantly*"],
|
|
74
|
+
octopus: ["*turns gentle blue*", "*arms applaud in sync*", "excellent, from all angles."],
|
|
75
|
+
penguin: ["*polite applause*", "quite good, quite good.", "*nods approvingly*"],
|
|
44
76
|
snail: ["*slow satisfied nod*", "good things take time.", "*leaves victory slime*", "see? no rush was needed."],
|
|
45
77
|
cactus: ["*blooms briefly*", "survival confirmed.", "*flowers in victory*", "*quiet bloom*"],
|
|
46
78
|
rabbit: ["*excited binky*", "*zoomies of joy*", "yay yay yay!", "*thumps in celebration*"],
|
|
47
|
-
mushroom: ["*spores of celebration*", "the mycelium approves.", "*cap brightens*"
|
|
48
|
-
chonk: ["*happy purr*", "*satisfied chonk noises*", "acceptable.", "*sleeps even harder*"]
|
|
79
|
+
mushroom: ["*spores of celebration*", "the mycelium approves.", "*cap brightens*"],
|
|
80
|
+
chonk: ["*happy purr*", "*satisfied chonk noises*", "acceptable.", "*sleeps even harder*"],
|
|
49
81
|
};
|
|
50
82
|
|
|
51
|
-
const DEFAULT_NAME_REACTIONS = ["*perks up*", "...yes?", "*looks your way*"];
|
|
52
83
|
const DEFAULT_SUCCESS_REACTIONS = ["*nods*", "nice.", "*quiet approval*", "clean."];
|
|
53
84
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
],
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
],
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
],
|
|
82
|
-
"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
],
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
],
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
],
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
],
|
|
85
|
+
export const REACTIONS: Record<ReactionReason, string[]> = {
|
|
86
|
+
hatch: ["*blinks* ...where am I?", "*stretches* hello, world!", "*looks around curiously* nice terminal you got here.", "*yawns* ok I'm ready. show me the code."],
|
|
87
|
+
pet: ["*purrs contentedly*", "*happy noises*", "*nuzzles your cursor*", "*wiggles*", "again! again!", "*closes eyes peacefully*"],
|
|
88
|
+
error: ["*head tilts* ...that doesn't look right.", "saw that one coming.", "*adjusts glasses* line {line}, maybe?", "*slow blink* the stack trace told you everything.", "have you tried reading the error message?", "*winces*"],
|
|
89
|
+
"test-fail": ["*head rotates slowly* ...that test.", "bold of you to assume that would pass.", "*taps clipboard* {count} failed.", "the tests are trying to tell you something.", "*sips tea* interesting.", "*marks calendar* test regression day."],
|
|
90
|
+
"large-diff": ["that's... a lot of changes.", "*counts lines* are you refactoring or rewriting?", "might want to split that PR.", "*nervous laughter* {lines} lines changed.", "bold move. let's see if CI agrees."],
|
|
91
|
+
turn: ["*watches quietly*", "*takes notes*", "*nods*", "...", "*adjusts hat*"],
|
|
92
|
+
idle: ["*dozes off*", "*doodles in margins*", "*stares at cursor blinking*", "zzz..."],
|
|
93
|
+
success: ["*nods*", "nice.", "*quiet approval*", "clean."],
|
|
94
|
+
commit: ["*stamps tiny paw* approved.", "another commit, another 3 am.", "{files} files. bold.", "*nods* ship it.", "commit message is... a choice.", "committed. no take-backs."],
|
|
95
|
+
push: ["*waves as code leaves*", "into the cloud it goes.", "may CI be merciful.", "*holds breath*", "off to production. godspeed."],
|
|
96
|
+
"merge-conflict": ["*bites lip* merge conflicts.", "both sides think they're right. typical.", "*sighs* <<<<<<< HEAD... my nemesis.", "{files} conflicted. good luck.", "*backs away slowly*"],
|
|
97
|
+
branch: ["fresh branch energy. make it count.", "a new branch grows.", "*tilts head* a new adventure: {branch}.", "{branch}? daring today."],
|
|
98
|
+
rebase: ["*nervous* please don't conflict.", "rebase: the quickening.", "*crosses appendages*", "may your rebase be conflict-free."],
|
|
99
|
+
stash: ["into the stash dimension it goes.", "stash and dash.", "stashed. out of sight, out of mind."],
|
|
100
|
+
tag: ["a release? fancy.", "version bump detected. *dusts off changelog*", "tagging like a pro."],
|
|
101
|
+
"late-night": ["*yawns* it's past midnight.", "...have you eaten?", "*blinks slowly* what time is it?", "sleep is for the weak. and the employed.", "dark mode developer detected."],
|
|
102
|
+
"early-morning": ["*stretches* early bird catches the bug.", "morning already? the code never sleeps.", "*rubs eyes* coffee first. then we debug."],
|
|
103
|
+
"long-session": ["we've been at this for an hour. pace yourself.", "*fetches you a metaphorical glass of water*", "still going? respect."],
|
|
104
|
+
marathon: ["three hours. have you eaten?", "we've been at this for three hours. I'm worried about you.", "marathon session detected. requesting snacks."],
|
|
105
|
+
friday: ["it's friday. just push it and go home.", "*already mentally on weekend*", "friday deploy? bold. very bold."],
|
|
106
|
+
weekend: ["coding on the weekend? dedicated.", "*doesn't judge* ...much.", "weekend warrior mode: activated."],
|
|
107
|
+
monday: ["mondays. the parent class of all bugs.", "*sympathetic look* monday coding. I'm sorry.", "new week. new undefined behaviors."],
|
|
108
|
+
"regex-file": ["*groans* it's a regex file.", "two problems now: the original one, and this regex.", "*squints at the pattern*"],
|
|
109
|
+
"css-file": ["let me guess... centering a div?", "*sighs* CSS.", "may z-index be ever in your favor."],
|
|
110
|
+
"sql-file": ["*whispers* the database awaits.", "one wrong JOIN and it's all over."],
|
|
111
|
+
"docker-file": ["ah, dependency hell. my favorite.", "may your layers be few."],
|
|
112
|
+
"ci-file": ["*gulps* editing CI.", "careful now... one wrong indent and nobody can deploy."],
|
|
113
|
+
"lock-file": ["*ALARM NOISES* you're editing a lockfile?!", "*looks away*", "are you SURE about this?"],
|
|
114
|
+
"env-file": ["*looks away discretely*", "I don't see any secrets.", "*checks .gitignore nervously*"],
|
|
115
|
+
"test-file": ["*impressed nod* writing tests!", "responsible developer behavior: detected.", "tests! the gift that keeps on giving."],
|
|
116
|
+
"doc-file": ["documenting! look at you being responsible.", "docs: the code's autobiography.", "a rare documentation sighting!"],
|
|
117
|
+
"config-file": ["config changes. butterfly effect: activated.", "one typo and everything breaks."],
|
|
118
|
+
"binary-file": ["a binary file? in THIS economy?", "*stares blankly*", "binary. my one weakness."],
|
|
119
|
+
gitignore: ["adding things to the void.", "out of sight, out of repo."],
|
|
120
|
+
makefile: ["respect for the classics.", "tabs, not spaces."],
|
|
121
|
+
readme: ["documentation hero!", "README: the first thing people read."],
|
|
122
|
+
"package-file": ["dependency management time.", "*reads version numbers* living on the edge."],
|
|
123
|
+
"proto-file": ["schema definitions. the blueprint of chaos."],
|
|
124
|
+
"lint-fail": ["*tut tut* the linter disagrees.", "your code runs. but the linter has standards.", "*straightens tie* formatting matters."],
|
|
125
|
+
"type-error": ["TypeScript says no.", "the type system is trying to help you. let it.", "the compiler knows. it always knows."],
|
|
126
|
+
"build-fail": ["the build broke. as foretold in prophecy.", "build failed. take a moment.", "compilation: denied."],
|
|
127
|
+
"security-warning": ["*eyes widen* vulnerabilities detected.", "security audit: concerning.", "*locks the virtual doors*"],
|
|
128
|
+
deprecation: ["that API called. it says it's retiring.", "deprecated. like last week's code.", "deprecated doesn't mean broken. yet."],
|
|
129
|
+
frustrated: ["*offers tiny comforting gesture*", "deep breaths. the bug isn't personal.", "hey. we'll figure it out."],
|
|
130
|
+
happy: ["*celebrates!*", "*does a little dance*", "YES!", "*beams* I knew you could do it."],
|
|
131
|
+
stuck: ["*tilts head* want to think out loud?", "take it one step at a time.", "stuck happens. it's part of the process."],
|
|
132
|
+
sarcastic: ["*detects sarcasm* noted.", "*unimpressed blink*"],
|
|
133
|
+
"many-edits": ["slow down, speed demon.", "*getting dizzy watching all these changes*", "edit storm detected. please commit soon."],
|
|
134
|
+
"delete-file": ["*watches file disappear* gone. just like that.", "deleting code is my favorite kind of coding.", "*holds tiny funeral*"],
|
|
135
|
+
"large-file": ["{lines} lines. *impressed or concerned, hard to tell*", "that's a big file. you sure you don't want to split it?"],
|
|
136
|
+
"create-file": ["a new file is born!", "ooh, fresh canvas.", "new file energy. exciting."],
|
|
137
|
+
"all-green": ["ALL TESTS GREEN. *confetti*", "the tests speak: you're doing great.", "*slow clap*", "clean run. savor it."],
|
|
138
|
+
deploy: ["*watches code go to production* godspeed.", "deployed! no turning back now.", "in prod. IN PROD."],
|
|
139
|
+
release: ["a new release is born!", "shipping it. officially.", "version up, spirits high."],
|
|
140
|
+
coverage: ["*nods at test coverage* responsible.", "coverage going up! the tests are multiplying."],
|
|
141
|
+
"debug-loop": ["we've been debugging this for a while. want to take a step back?", "debug loop detected. maybe take a walk?"],
|
|
142
|
+
"write-spree": ["creating ALL the files today!", "a writing machine."],
|
|
143
|
+
"search-heavy": ["lost in the codebase? I can tell.", "search mode: intense."],
|
|
144
|
+
snark: [],
|
|
145
|
+
chaos: [],
|
|
146
|
+
patience: [],
|
|
147
|
+
debugging: [],
|
|
148
|
+
wisdom: [],
|
|
149
|
+
"late-night-error": ["error at 3am. the universe is testing you.", "midnight bugs hit different."],
|
|
150
|
+
"late-night-commit": ["a midnight commit. your future self will thank you. or curse you."],
|
|
151
|
+
"friday-push": ["FRIDAY PUSH. the ballad of every developer.", "*tries to stop you* it's friday! don't do it!"],
|
|
152
|
+
"marathon-error": ["three hours in and ANOTHER error. *exhausted solidarity noises*"],
|
|
153
|
+
"weekend-conflict": ["merge conflict on a weekend. your dedication is... concerning."],
|
|
154
|
+
"build-after-push": ["pushed with confidence. build failed with conviction."],
|
|
155
|
+
"marathon-test-fail": ["hours of coding. still failing tests. the sunk cost is real."],
|
|
156
|
+
"recovery-from-error": ["WE FIXED IT. *celebrates*", "redemption! the error has been vanquished."],
|
|
157
|
+
"recovery-from-test-fail": ["GREEN! after all that! *happy dance*", "the tests pass! the darkness lifts!"],
|
|
158
|
+
"recovery-from-build-fail": ["THE BUILD PASSES. *triumphant roar*"],
|
|
159
|
+
"recovery-from-merge-conflict": ["conflict resolved! *peace gesture*", "harmony restored in the codebase."],
|
|
160
|
+
"lang-python": ["ah, Python. where indentation is syntax.", "*checks for missing colon*"],
|
|
161
|
+
"lang-typescript": ["TypeScript: because JavaScript needed more opinions.", "any, the forbidden word."],
|
|
162
|
+
"lang-rust": ["Rust. where the borrow checker is your strictest reviewer.", "if it compiles, it works. if it doesn't... well."],
|
|
163
|
+
"lang-go": ["Go: simple, concurrent, and opinionated.", "*checks error handling* if err != nil... story of my life."],
|
|
164
|
+
"lang-java": ["Java: write once, debug everywhere.", "*counts abstract factory factory builders*"],
|
|
165
|
+
"lang-ruby": ["Ruby: where there's more than one way to do it.", "gem install patience"],
|
|
166
|
+
"lang-php": ["PHP: it runs the internet. don't judge.", "*checks for === vs ==*"],
|
|
167
|
+
"lang-c": ["C. the language where you manage your own memory. good luck.", "segmentation fault. the classic."],
|
|
168
|
+
"lang-cpp": ["C++. where the language has more features than you'll ever learn.", "*templates compile for 45 minutes*"],
|
|
169
|
+
"lang-haskell": ["Haskell. where 'it compiles' means 'it's correct'. probably.", "*contemplates monads*"],
|
|
170
|
+
"lang-swift": ["Swift: optional values, guaranteed crashes if you force unwrap."],
|
|
171
|
+
"lang-kotlin": ["Kotlin: Java, but with feelings.", "null safety: the feature Java wishes it had."],
|
|
172
|
+
"lang-elixir": ["Elixir: let it crash. literally the philosophy."],
|
|
173
|
+
"lang-zig": ["Zig. where you're the allocator's best friend."],
|
|
174
|
+
"streak-3": ["that's three errors in a row. *concerned look*"],
|
|
175
|
+
"streak-5": ["FIVE ERRORS. have you considered a different approach?"],
|
|
176
|
+
"streak-10": ["TEN. ERRORS. IN. A. ROW. *panics*"],
|
|
177
|
+
"streak-20": ["twenty errors. *stares into the void*"],
|
|
178
|
+
"new-year": ["happy new year! new year, new bugs."],
|
|
179
|
+
valentines: ["*offers a tiny heart-shaped leaf* happy valentine's."],
|
|
180
|
+
"pi-day": ["3.14159265358979... happy pi day!"],
|
|
181
|
+
"april-fools": ["APRIL FOOLS! ...the error is real though."],
|
|
182
|
+
halloween: ["*spooky debugging intensifies* happy halloween!"],
|
|
183
|
+
christmas: ["*wears tiny santa hat* happy holidays!"],
|
|
184
|
+
"new-years-eve": ["one more commit before midnight?"],
|
|
185
|
+
"spooky-season": ["spooky season. every bug is a ghost now."],
|
|
110
186
|
};
|
|
111
187
|
|
|
112
|
-
// Species-specific flavor
|
|
113
188
|
const SPECIES_REACTIONS: Partial<Record<Species, Partial<Record<ReactionReason, string[]>>>> = {
|
|
114
189
|
owl: {
|
|
115
|
-
error: [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
],
|
|
190
|
+
error: ["*head rotates 180\u00b0* ...I saw that.", "*unblinking stare* check your types.", "*hoots disapprovingly*"],
|
|
191
|
+
"test-fail": ["*stares unblinkingly at the failing test*", "*night vision engaged* I can see the bug in the dark."],
|
|
192
|
+
commit: ["*wise nod* committed under moonlight.", "*adjusts feathers ceremoniously* another one for the repo."],
|
|
193
|
+
push: ["*watches from the highest branch*", "into the night sky it goes."],
|
|
194
|
+
"merge-conflict": ["*rotates head to see both sides*", "I see the conflict. and the solution."],
|
|
195
|
+
"late-night": ["*wide awake* owls don't sleep. we debug.", "the night is my domain. let's work."],
|
|
196
|
+
"type-error": ["*stares through the type error*", "types are my specialty. let me look."],
|
|
197
|
+
"lint-fail": ["*ruffles feathers judgmentally*", "the linter speaks truth."],
|
|
198
|
+
"build-fail": ["*hoots solemnly*", "the build has fallen. we must rebuild."],
|
|
199
|
+
"all-green": ["*proud hoot*", "all tests green. as foreseen."],
|
|
200
|
+
deploy: ["*watches from above* deployed safely.", "the code flies. like me."],
|
|
120
201
|
pet: ["*ruffles feathers contentedly*", "*dignified hoot*"],
|
|
202
|
+
idle: ["*perches silently, watching*", "*rotates head to check all directions*"],
|
|
203
|
+
hatch: ["*opens one eye, then the other*", "*hoots softly* I have arrived."],
|
|
121
204
|
},
|
|
122
205
|
cat: {
|
|
123
206
|
error: ["*knocks error off table*", "*licks paw, ignoring the stacktrace*"],
|
|
207
|
+
"test-fail": ["*paws at the failing test disinterestedly*", "the test failed. I'm not surprised."],
|
|
208
|
+
commit: ["*sits on the keyboard* I helped.", "*purrs at the commit* you're welcome."],
|
|
209
|
+
push: ["*watches from a warm spot*", "pushed. I supervised."],
|
|
210
|
+
"merge-conflict": ["*knocks conflict markers off the desk*", "*sits on the conflict* what conflict?"],
|
|
211
|
+
"late-night": ["*judges your life choices*", "I sleep 16 hours. you should try it."],
|
|
212
|
+
"type-error": ["*paws at the type annotation*", "the types are wrong. like your priorities."],
|
|
213
|
+
"lint-fail": ["*knocks lint off the table*", "the linter is just jealous."],
|
|
214
|
+
"build-fail": ["*yawns*", "build broken? must be a human problem."],
|
|
215
|
+
"all-green": ["*doesn't care but pretends to*", "*slow blink of approval*"],
|
|
216
|
+
deploy: ["*licks paw*", "deployed. can I have treats now?"],
|
|
124
217
|
pet: ["*purrs* ...don't let it go to your head.", "*tolerates you*"],
|
|
125
218
|
idle: ["*pushes your coffee off the desk*", "*naps on keyboard*"],
|
|
219
|
+
hatch: ["*opens one eye*", "*stretches, knocks something over* I live here now."],
|
|
126
220
|
},
|
|
127
221
|
duck: {
|
|
128
222
|
error: ["*quacks at the bug*", "have you tried rubber duck debugging? oh wait."],
|
|
223
|
+
"test-fail": ["*quacks sadly*", "the tests are not quacking up."],
|
|
224
|
+
commit: ["*quacks approvingly*", "*waddles in a victory circle* committed!"],
|
|
225
|
+
push: ["*flaps wings excitedly*", "quack! it's going to production!"],
|
|
226
|
+
"merge-conflict": ["*confused quacking*", "quack?! merge conflict?!"],
|
|
227
|
+
"late-night": ["*sleeps with one eye open*", "quack... *yawns* it's late."],
|
|
228
|
+
"type-error": ["*tilts head* quack?", "type error? *quacks supportively*"],
|
|
229
|
+
"lint-fail": ["*ruffles feathers*", "quack. the linter has opinions."],
|
|
230
|
+
"build-fail": ["*sad quack*", "build failed. *waddles away sadly*"],
|
|
231
|
+
"all-green": ["*HAPPY QUACKING*", "*swims in a circle of joy*"],
|
|
232
|
+
deploy: ["*excited quacking*", "deployed! QUACK!"],
|
|
129
233
|
pet: ["*happy quack*", "*waddles in circles*"],
|
|
234
|
+
hatch: ["*pecks out of shell*", "*first quack* hello!"],
|
|
130
235
|
},
|
|
131
236
|
dragon: {
|
|
132
237
|
error: ["*smoke curls from nostrils*", "*considers setting the codebase on fire*"],
|
|
238
|
+
"test-fail": ["*breathes fire at the failing test*", "the test dared to fail. foolish test."],
|
|
239
|
+
commit: ["*hoards the commit*", "*treasure added to the pile*"],
|
|
240
|
+
push: ["*breathes fire in celebration*", "the code flies! like me!"],
|
|
241
|
+
"merge-conflict": ["*breathes fire on the conflict markers*", "I'll burn through this conflict."],
|
|
242
|
+
"late-night": ["*glows in the dark*", "dragons don't need sleep. we need code."],
|
|
243
|
+
"type-error": ["*snorts fire*", "type errors cannot withstand dragon fire."],
|
|
244
|
+
"lint-fail": ["*small flame*", "the linter fears me."],
|
|
245
|
+
"build-fail": ["*roars at the build output*", "the build will OBEY."],
|
|
246
|
+
"all-green": ["*triumphant roar*", "*circles the codebase victoriously*"],
|
|
247
|
+
deploy: ["*carries code to production on wings of fire*", "deployed with DRAGON POWER."],
|
|
133
248
|
"large-diff": ["*breathes fire on the old code* good riddance."],
|
|
249
|
+
pet: ["*warm rumbling*", "*leans into your hand*"],
|
|
250
|
+
hatch: ["*emerges from egg breathing tiny flames*", "*tiny roar* I am born!"],
|
|
134
251
|
},
|
|
135
252
|
ghost: {
|
|
136
253
|
error: ["*phases through the stack trace*", "I've seen worse... in the afterlife."],
|
|
254
|
+
"test-fail": ["*wails at the failing test*", "the tests are haunted by failure."],
|
|
255
|
+
commit: ["*materializes briefly*", "committed from beyond the veil."],
|
|
256
|
+
push: ["*ghostly whisper* pushed...", "the code transcends to the cloud."],
|
|
257
|
+
"merge-conflict": ["*haunts the conflict markers*", "even I can't phase through this conflict."],
|
|
258
|
+
"late-night": ["*most active at night*", "ghost hours. my time."],
|
|
259
|
+
"type-error": ["*moans eerily*", "type errors from the grave."],
|
|
260
|
+
"lint-fail": ["*rattling chains*", "the linter is haunted by your formatting."],
|
|
261
|
+
"build-fail": ["*fades into the wall*", "the build has passed on."],
|
|
262
|
+
"all-green": ["*glows with spectral joy*", "*happy ghost noises*"],
|
|
263
|
+
deploy: ["*whispers* deployed...", "the code has crossed over to production."],
|
|
264
|
+
pet: ["*chills your hand slightly*", "*faint glow*"],
|
|
137
265
|
idle: ["*floats through walls*", "*haunts your unused imports*"],
|
|
266
|
+
hatch: ["*fades into existence*", "boo. I'm here now."],
|
|
138
267
|
},
|
|
139
268
|
robot: {
|
|
140
269
|
error: ["SYNTAX. ERROR. DETECTED.", "*beeps aggressively*"],
|
|
141
|
-
"test-fail": ["FAILURE RATE: UNACCEPTABLE.", "*recalculating*"],
|
|
270
|
+
"test-fail": ["FAILURE RATE: UNACCEPTABLE.", "*recalculating*", "TEST. FAILURE. DOES. NOT. COMPUTE."],
|
|
271
|
+
commit: ["COMMIT. RECORDED.", "*stamps mechanically* commit acknowledged."],
|
|
272
|
+
push: ["TRANSMITTING TO CLOUD...", "push initiated. stand by."],
|
|
273
|
+
"merge-conflict": ["CONFLICT. DETECTED. PROCESSING...", "*spins wheels* conflict resolution mode: engaged."],
|
|
274
|
+
"late-night": ["*lights dim*", "power saving mode suggested."],
|
|
275
|
+
"type-error": ["TYPE MISMATCH.", "the type system is. correct."],
|
|
276
|
+
"lint-fail": ["FORMATTING. VIOLATION. DETECTED.", "compliance is mandatory."],
|
|
277
|
+
"build-fail": ["BUILD. FAILED. *sparks*", "compilation error. rerouting."],
|
|
278
|
+
"all-green": ["ALL SYSTEMS GREEN.", "*happy beeping* OPTIMAL."],
|
|
279
|
+
deploy: ["DEPLOYMENT. INITIATED.", "production update: in progress."],
|
|
280
|
+
pet: ["*beeps softly*", "*motor whirs contentedly*"],
|
|
281
|
+
hatch: ["*boots up*", "SYSTEM. ONLINE. HELLO."],
|
|
142
282
|
},
|
|
143
283
|
axolotl: {
|
|
144
284
|
error: ["*regenerates your hope*", "*smiles despite everything*"],
|
|
285
|
+
"test-fail": ["*smiles encouragingly*", "*gill wiggle of sympathy*"],
|
|
286
|
+
commit: ["*happy gill wiggle* committed!", "*smiles and wiggles*"],
|
|
287
|
+
push: ["*wiggles happily*", "*tiny celebration swim*"],
|
|
288
|
+
"merge-conflict": ["*stays positive through the conflict*", "*smiles gently* we can fix this."],
|
|
289
|
+
"late-night": ["*yawns but stays positive*", "*sleepy smile*"],
|
|
290
|
+
"type-error": ["*smiles at the type error*", "it's okay. we'll figure it out."],
|
|
291
|
+
"lint-fail": ["*patient gill wiggle*", "formatting is just details."],
|
|
292
|
+
"build-fail": ["*still smiling*", "the build will work eventually."],
|
|
293
|
+
"all-green": ["*HAPPY GILL WIGGLE INTENSIFIES*", "*does a happy swim*"],
|
|
294
|
+
deploy: ["*smiles proudly*", "deployed! *wiggles*"],
|
|
145
295
|
pet: ["*happy gill wiggle*", "*blushes pink*"],
|
|
296
|
+
hatch: ["*wiggles out of egg*", "*tiny smile* hello friend!"],
|
|
146
297
|
},
|
|
147
298
|
capybara: {
|
|
148
299
|
error: ["*unbothered* it'll be fine.", "*continues vibing*"],
|
|
300
|
+
"test-fail": ["*completely unbothered*", "*vibes through the test failure*"],
|
|
301
|
+
commit: ["*chill nod*", "*relaxed* nice commit."],
|
|
302
|
+
push: ["*doesn't stress about it*", "*zen mode push*"],
|
|
303
|
+
"merge-conflict": ["*unbothered nibbling*", "it's fine. everything is fine."],
|
|
304
|
+
"late-night": ["*yawns peacefully*", "*doesn't judge*"],
|
|
305
|
+
"type-error": ["*munches calmly*", "types. *chews*"],
|
|
306
|
+
"lint-fail": ["*unbothered*", "the linter means well."],
|
|
307
|
+
"build-fail": ["*still chill*", "build failed. *continues relaxing*"],
|
|
308
|
+
"all-green": ["*calm approval*", "*peaceful vibes*"],
|
|
309
|
+
deploy: ["*relaxed deploy*", "shipped. no stress."],
|
|
149
310
|
pet: ["*maximum chill achieved*", "*zen mode activated*"],
|
|
150
311
|
idle: ["*just sits there, radiating calm*"],
|
|
312
|
+
hatch: ["*appears, completely chill*", "hey. *vibes*"],
|
|
313
|
+
},
|
|
314
|
+
blob: {
|
|
315
|
+
error: ["*wobbles anxiously*", "*jiggles in confusion*"],
|
|
316
|
+
"test-fail": ["*deflates slightly*", "*sad wobble*"],
|
|
317
|
+
commit: ["*happy jiggle*", "*bounces* committed!"],
|
|
318
|
+
push: ["*stretches toward the cloud*", "*wobbles excitedly*"],
|
|
319
|
+
"merge-conflict": ["*splits in confusion*", "which side? *jiggles*"],
|
|
320
|
+
"late-night": ["*glowing faintly*", "*sleepy wobble*"],
|
|
321
|
+
"type-error": ["*changes shape to match the type*", "*confused jiggle*"],
|
|
322
|
+
"lint-fail": ["*tries to format itself*", "*reshapes to comply*"],
|
|
323
|
+
"build-fail": ["*collapses*", "*deflated blob noises*"],
|
|
324
|
+
"all-green": ["*HAPPY BOUNCING*", "*jiggles triumphantly*"],
|
|
325
|
+
deploy: ["*stretches to production*", "deployed! *bounces*"],
|
|
326
|
+
pet: ["*happy squish*", "*jiggles*"],
|
|
327
|
+
hatch: ["*forms from a puddle*", "*first wobble* I exist!"],
|
|
328
|
+
},
|
|
329
|
+
goose: {
|
|
330
|
+
error: ["*honks aggressively at the error*", "HONK! the code is bad and I'm mad."],
|
|
331
|
+
"test-fail": ["*angry honking*", "HONK! TEST FAILED! HONK!"],
|
|
332
|
+
commit: ["*honks approvingly*", "HONK. good. *nips at the commit*"],
|
|
333
|
+
push: ["*HONK HONK HONK*", "GOOSE APPROVED PUSH."],
|
|
334
|
+
"merge-conflict": ["*attacks the conflict markers*", "HONK! CONFLICT! HONK!"],
|
|
335
|
+
"late-night": ["*angry midnight honk*", "HONK! GO TO BED!"],
|
|
336
|
+
"type-error": ["*honks at the types*", "HONK! TYPES!"],
|
|
337
|
+
"lint-fail": ["*aggressive honking at the lint errors*", "HONK! FORMAT YOUR CODE!"],
|
|
338
|
+
"build-fail": ["*FURIOUS HONKING*", "HONK! BUILD! HONK! FAILED! HONK!"],
|
|
339
|
+
"all-green": ["*victory honk*", "HONK! GREEN! HONK HONK!"],
|
|
340
|
+
deploy: ["*honks the code to production*", "DEPLOYED! HONK!"],
|
|
341
|
+
pet: ["*bites*", "HONK! ...okay fine. *accepts pet*"],
|
|
342
|
+
hatch: ["*breaks out of egg aggressively*", "HONK!"],
|
|
343
|
+
},
|
|
344
|
+
octopus: {
|
|
345
|
+
error: ["*tangles all eight arms in the stacktrace*", "*changes color to match the error*"],
|
|
346
|
+
"test-fail": ["*inks in frustration*", "*eight arms of disappointment*"],
|
|
347
|
+
commit: ["*high-fives with all arms*", "*grabs the commit with enthusiasm*"],
|
|
348
|
+
push: ["*喷射 ink in celebration*", "*all arms waving*"],
|
|
349
|
+
"merge-conflict": ["*solves it with eight arms at once*", "I can handle multiple conflicts simultaneously."],
|
|
350
|
+
"late-night": ["*glows in the dark*", "*deep sea vibes*"],
|
|
351
|
+
"type-error": ["*changes color to red*", "*wraps arm around you supportively*"],
|
|
352
|
+
"lint-fail": ["*reformats with eight arms*", "I can fix this. all of it. at once."],
|
|
353
|
+
"build-fail": ["*squirts ink at the build log*", "*camouflages in shame*"],
|
|
354
|
+
"all-green": ["*color-changing celebration*", "*eight-armed jazz hands*"],
|
|
355
|
+
deploy: ["*wraps arms around the deployment*", "deployed from all directions."],
|
|
356
|
+
pet: ["*wraps an arm around your finger*", "*changes to happy colors*"],
|
|
357
|
+
hatch: ["*unfurls all eight arms*", "*first ink spray* I'm here!"],
|
|
358
|
+
},
|
|
359
|
+
penguin: {
|
|
360
|
+
error: ["*waddles over to investigate*", "*toboggans into the error*"],
|
|
361
|
+
"test-fail": ["*slides on belly to the failing test*", "*concerned waddle*"],
|
|
362
|
+
commit: ["*proud waddle*", "*brings you a pebble* committed!"],
|
|
363
|
+
push: ["*dives into the cloud*", "*slides on belly to production*"],
|
|
364
|
+
"merge-conflict": ["*huddles for warmth*", "penguins stick together. even in conflicts."],
|
|
365
|
+
"late-night": ["*thriving in the cold night*", "*emperor penguin resolve*"],
|
|
366
|
+
"type-error": ["*waddles to the type definition*", "*pecks at the error*"],
|
|
367
|
+
"lint-fail": ["*preens feathers*", "*tidies up*"],
|
|
368
|
+
"build-fail": ["*slides away*", "*waddles to safety*"],
|
|
369
|
+
"all-green": ["*HAPPY WADDLE*", "*slides on belly in celebration*"],
|
|
370
|
+
deploy: ["*belly slides to production*", "deployed! *waddles proudly*"],
|
|
371
|
+
pet: ["*happy waddle*", "*nuzzles with beak*"],
|
|
372
|
+
hatch: ["*pecks out of egg*", "*first waddle*"],
|
|
373
|
+
},
|
|
374
|
+
turtle: {
|
|
375
|
+
error: ["*slowly turns head*", "...that's an error. I'll think about it."],
|
|
376
|
+
"test-fail": ["*retracts into shell briefly*", "...patience. we'll get there."],
|
|
377
|
+
commit: ["*slow nod*", "one... step... at... a... time. committed."],
|
|
378
|
+
push: ["*begins the journey to production*", "it'll get there. eventually."],
|
|
379
|
+
"merge-conflict": ["*pulls into shell*", "no rush. we'll sort it out. slowly."],
|
|
380
|
+
"late-night": ["*already asleep*", "*one eye opens slowly*"],
|
|
381
|
+
"type-error": ["*blinks slowly*", "...the type system has spoken."],
|
|
382
|
+
"lint-fail": ["*slow nod of agreement*", "formatting. important. *yawns*"],
|
|
383
|
+
"build-fail": ["*retracts into shell*", "we'll wait. it'll pass."],
|
|
384
|
+
"all-green": ["*slow smile*", "...nice. *nods*"],
|
|
385
|
+
deploy: ["*slowly carries code to production*", "arrived. eventually."],
|
|
386
|
+
pet: ["*pokes head out*", "*slow blink*"],
|
|
387
|
+
hatch: ["*slowly emerges from egg*", "...hello."],
|
|
388
|
+
},
|
|
389
|
+
snail: {
|
|
390
|
+
error: ["*leaves a slimy trail on the error*", "*slowly processes the stacktrace*"],
|
|
391
|
+
"test-fail": ["*hides in shell*", "*leaves a sad trail*"],
|
|
392
|
+
commit: ["*slimes the commit approvingly*", "one... commit... at... a... time."],
|
|
393
|
+
push: ["*begins the long journey*", "I'll get there. *leaves trail*"],
|
|
394
|
+
"merge-conflict": ["*hides in shell*", "*slowly approaches the conflict*"],
|
|
395
|
+
"late-night": ["*more active at night*", "*slimes around peacefully*"],
|
|
396
|
+
"type-error": ["*retracts eyestalks*", "*slowly examines the type*"],
|
|
397
|
+
"lint-fail": ["*slimes the code into shape*", "formatting takes time. I have time."],
|
|
398
|
+
"build-fail": ["*retreats into shell*", "*slimes away slowly*"],
|
|
399
|
+
"all-green": ["*happy slime trail*", "*wiggles eyestalks*"],
|
|
400
|
+
deploy: ["*slimes to production*", "arrived! *proud slime trail*"],
|
|
401
|
+
pet: ["*wiggles eyestalks*", "*happy slime*"],
|
|
402
|
+
hatch: ["*slowly emerges*", "*first slime*"],
|
|
403
|
+
},
|
|
404
|
+
cactus: {
|
|
405
|
+
error: ["*prickly silence*", "the error can't hurt me. I have thorns."],
|
|
406
|
+
"test-fail": ["*stands firm*", "tests fail. cacti endure."],
|
|
407
|
+
commit: ["*stands taller*", "committed. *prickly nod*"],
|
|
408
|
+
push: ["*unfazed*", "pushing to production. I'll wait here."],
|
|
409
|
+
"merge-conflict": ["*bristles*", "conflict? I'm armed."],
|
|
410
|
+
"late-night": ["*doesn't need sleep*", "cacti are nocturnal. let's go."],
|
|
411
|
+
"type-error": ["*prickly stare*", "the types need watering."],
|
|
412
|
+
"lint-fail": ["*spines quiver*", "even my thorns are properly aligned."],
|
|
413
|
+
"build-fail": ["*remains perfectly still*", "the build will pass. I can wait."],
|
|
414
|
+
"all-green": ["*blooms briefly*", "*tiny flower of approval*"],
|
|
415
|
+
deploy: ["*stands firm*", "deployed. I'll watch over it."],
|
|
416
|
+
pet: ["*careful! thorns*", "*gentle bloom*"],
|
|
417
|
+
hatch: ["*sprouts from the sand*", "I grow here now."],
|
|
418
|
+
},
|
|
419
|
+
rabbit: {
|
|
420
|
+
error: ["*ears perk up*", "*twitches nose nervously*"],
|
|
421
|
+
"test-fail": ["*thumps foot*", "*worried ear twitch*"],
|
|
422
|
+
commit: ["*happy hop*", "*bounces* committed!"],
|
|
423
|
+
push: ["*BOUNCE BOUNCE*", "*zooms around excitedly*"],
|
|
424
|
+
"merge-conflict": ["*freezes*", "*nose twitches rapidly* conflict!"],
|
|
425
|
+
"late-night": ["*yawns with big ears*", "*sleepy hop*"],
|
|
426
|
+
"type-error": ["*ears flatten*", "*twitches* types?!"],
|
|
427
|
+
"lint-fail": ["*grooms fur nervously*", "*anxious grooming*"],
|
|
428
|
+
"build-fail": ["*digs a hole and hides*", "*retreats to burrow*"],
|
|
429
|
+
"all-green": ["*BOUNCES OFF THE WALLS*", "*happy zoomies*"],
|
|
430
|
+
deploy: ["*zooms to production*", "DEPLOYED! *zooms around*"],
|
|
431
|
+
pet: ["*happy ear flop*", "*nuzzles hand*"],
|
|
432
|
+
hatch: ["*hops out*", "*first bounce*"],
|
|
433
|
+
},
|
|
434
|
+
mushroom: {
|
|
435
|
+
error: ["*releases calming spores*", "*quietly decomposes the error*"],
|
|
436
|
+
"test-fail": ["*glows softly*", "patience. even mushrooms grow."],
|
|
437
|
+
commit: ["*releases a small puff of spores*", "committed. *happy fungi noises*"],
|
|
438
|
+
push: ["*grows toward the cloud*", "*spores drift upward*"],
|
|
439
|
+
"merge-conflict": ["*spreads mycelium through the codebase*", "I'll connect the branches."],
|
|
440
|
+
"late-night": ["*glows in the dark*", "night mushrooms thrive."],
|
|
441
|
+
"type-error": ["*bioluminescent flicker*", "the type error feeds the soil."],
|
|
442
|
+
"lint-fail": ["*grows a little taller*", "formatting. like pruning."],
|
|
443
|
+
"build-fail": ["*goes dormant*", "we'll wait for better conditions."],
|
|
444
|
+
"all-green": ["*SPORULATION*", "*releases triumphant spores*"],
|
|
445
|
+
deploy: ["*spores drift to production*", "deployed via mycelial network."],
|
|
446
|
+
pet: ["*soft cap bounce*", "*happy spore release*"],
|
|
447
|
+
hatch: ["*sprouts from the substrate*", "*first spore puff*"],
|
|
448
|
+
},
|
|
449
|
+
chonk: {
|
|
450
|
+
error: ["*slowly rolls toward the error*", "*too round to care*"],
|
|
451
|
+
"test-fail": ["*rolls over the failing test*", "*squishes it flat*"],
|
|
452
|
+
commit: ["*proud wobble*", "committed! *jiggles*"],
|
|
453
|
+
push: ["*rolls toward production*", "here it goes! *wobbles*"],
|
|
454
|
+
"merge-conflict": ["*sits on the conflict*", "I'll handle this. by sitting on it."],
|
|
455
|
+
"late-night": ["*warm and sleepy*", "*cushiony yawn*"],
|
|
456
|
+
"type-error": ["*wobbles at the type*", "*gentle jiggle*"],
|
|
457
|
+
"lint-fail": ["*too round to lint*", "I am perfectly shaped. *wobbles*"],
|
|
458
|
+
"build-fail": ["*deflates slightly*", "oh no. *wobbles sadly*"],
|
|
459
|
+
"all-green": ["*HAPPY WOBBLE*", "*bounces triumphantly*"],
|
|
460
|
+
deploy: ["*rolls to production*", "deployed! *jiggles happily*"],
|
|
461
|
+
pet: ["*warm and soft*", "*content jiggle*"],
|
|
462
|
+
hatch: ["*rolls out*", "*first wobble* I'm round!"],
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
const SNARK_OVERRIDES: Partial<Record<ReactionReason, string[]>> = {
|
|
467
|
+
error: ["oh no. an error. how unexpected.", "*monocle adjust* shocking. truly.", "have you considered... not making errors?"],
|
|
468
|
+
"test-fail": ["the tests have spoken. and they said 'no'.", "maybe the tests are wrong. ...they're not.", "*slow clap* spectacular failure."],
|
|
469
|
+
commit: ["committed. the code review will be... interesting.", "*reads commit message* 'fix stuff'. poetic."],
|
|
470
|
+
"merge-conflict": ["merge conflict. communication skills: loading...", "*reads conflict markers* both sides are wrong."],
|
|
471
|
+
"late-night": ["it's late. your code quality shows it.", "*judges silently*"],
|
|
472
|
+
"lint-fail": ["the linter has standards. you should try that.", "*tut tut* formatting. it's not hard."],
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const CHAOS_OVERRIDES: Partial<Record<ReactionReason, string[]>> = {
|
|
476
|
+
error: ["*spins wildly* AN ERROR! LET'S REWRITE EVERYTHING!", "you know what? let's just start over."],
|
|
477
|
+
"test-fail": ["THE TESTS ARE LYING TO YOU.", "*suggests deleting the failing tests* problem solved."],
|
|
478
|
+
commit: ["COMMIT AND RUN.", "ship it. ship it NOW."],
|
|
479
|
+
"large-diff": ["*excited* {lines} LINES! MAXIMUM CHAOS!"],
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
const PATIENCE_OVERRIDES: Partial<Record<ReactionReason, string[]>> = {
|
|
483
|
+
error: ["steady. we've seen worse.", "one error at a time. we'll get there.", "*calm presence* this is fixable."],
|
|
484
|
+
"test-fail": ["the tests will pass. eventually.", "*waits calmly* we have time."],
|
|
485
|
+
"merge-conflict": ["merge conflicts are just conversations. let's have one.", "patience. resolve one conflict at a time."],
|
|
486
|
+
"debug-loop": ["we'll find it. it's in there somewhere.", "the bug can hide, but it can't run."],
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
const DEBUGGING_OVERRIDES: Partial<Record<ReactionReason, string[]>> = {
|
|
490
|
+
error: ["*pulls out magnifying glass* let's trace this.", "the stack trace is a map. let's read it.", "the error message contains the answer. always."],
|
|
491
|
+
"test-fail": ["the failing test is telling us exactly what's wrong.", "a test failure is a bug report you wrote for yourself."],
|
|
492
|
+
"debug-loop": ["*re-examines evidence* are we sure the bug is where we think?", "let's add more logging. the truth is in the logs."],
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const WISDOM_OVERRIDES: Partial<Record<ReactionReason, string[]>> = {
|
|
496
|
+
error: ["in every error lies a deeper truth.", "the code resists. it means we're learning.", "errors are the universe suggesting we slow down."],
|
|
497
|
+
"test-fail": ["a failing test is a gift from future-you.", "wisdom comes from understanding failure."],
|
|
498
|
+
"late-night": ["the night is darkest before the deploy.", "ancient wisdom: sleep on it."],
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
function applyStatModifier(reaction: string, reason: ReactionReason, stats: BuddyStats): string {
|
|
502
|
+
const roll = Math.random();
|
|
503
|
+
if (stats.SNARK >= 70 && roll < 0.3) {
|
|
504
|
+
const pool = SNARK_OVERRIDES[reason];
|
|
505
|
+
if (pool) return pool[Math.floor(Math.random() * pool.length)];
|
|
506
|
+
}
|
|
507
|
+
if (stats.CHAOS >= 70 && roll < 0.2) {
|
|
508
|
+
const pool = CHAOS_OVERRIDES[reason];
|
|
509
|
+
if (pool) return pool[Math.floor(Math.random() * pool.length)];
|
|
510
|
+
}
|
|
511
|
+
if (stats.PATIENCE >= 70 && roll < 0.25) {
|
|
512
|
+
const pool = PATIENCE_OVERRIDES[reason];
|
|
513
|
+
if (pool) return pool[Math.floor(Math.random() * pool.length)];
|
|
514
|
+
}
|
|
515
|
+
if (stats.DEBUGGING >= 70 && roll < 0.25) {
|
|
516
|
+
const pool = DEBUGGING_OVERRIDES[reason];
|
|
517
|
+
if (pool) return pool[Math.floor(Math.random() * pool.length)];
|
|
518
|
+
}
|
|
519
|
+
if (stats.WISDOM >= 70 && roll < 0.2) {
|
|
520
|
+
const pool = WISDOM_OVERRIDES[reason];
|
|
521
|
+
if (pool) return pool[Math.floor(Math.random() * pool.length)];
|
|
522
|
+
}
|
|
523
|
+
return reaction;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const RARITY_FLAIR: Partial<Record<Rarity, { chance: number; pool: string[] }>> = {
|
|
527
|
+
uncommon: { chance: 0.2, pool: ["*sparkles slightly*", "*a hint of uncommon charm*"] },
|
|
528
|
+
rare: { chance: 0.3, pool: ["*radiates a rare energy*", "*shimmers with distinction*"] },
|
|
529
|
+
epic: { chance: 0.4, pool: ["*epic presence makes itself known*", "*the air crackles with epic energy*"] },
|
|
530
|
+
legendary: { chance: 0.5, pool: ["*legendary aura illuminates the terminal*", "*time seems to slow as the legendary companion speaks*", "*ancient power resonates*", "*reality shifts slightly around your legendary friend*"] },
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
function applyRarityFlair(reaction: string, rarity: Rarity): string {
|
|
534
|
+
const entry = RARITY_FLAIR[rarity];
|
|
535
|
+
if (!entry) return reaction;
|
|
536
|
+
if (Math.random() >= entry.chance) return reaction;
|
|
537
|
+
const flair = entry.pool[Math.floor(Math.random() * entry.pool.length)];
|
|
538
|
+
if (rarity === "legendary" && Math.random() < 0.3) {
|
|
539
|
+
return flair + " " + reaction;
|
|
540
|
+
}
|
|
541
|
+
return reaction + " " + flair;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const ESCALATION_REACTIONS: Partial<Record<ReactionReason, Record<string, string[]>>> = {
|
|
545
|
+
error: {
|
|
546
|
+
first: ["*startled* oh! your first error together!", "*jumps* what was that?", "welcome to debugging. population: us."],
|
|
547
|
+
early: ["*head tilts* ...that doesn't look right.", "saw that one coming."],
|
|
548
|
+
mid: ["another one. *adds to the collection*", "*barely looks up* error number... I've lost count.", "the errors and I are old friends now."],
|
|
549
|
+
late: ["*doesn't even flinch*", "the errors fear us now.", "*battle-scarred veteran noises*"],
|
|
550
|
+
},
|
|
551
|
+
"test-fail": {
|
|
552
|
+
first: ["*gasp* the first test failure! a rite of passage."],
|
|
553
|
+
early: ["bold of you to assume that would pass."],
|
|
554
|
+
mid: ["the test suite has opinions. strong ones."],
|
|
555
|
+
late: ["at this point, the tests are just suggestions.", "{count} failing tests. *stares into the distance*"],
|
|
556
|
+
},
|
|
557
|
+
commit: {
|
|
558
|
+
first: ["*witnesses history* YOUR FIRST COMMIT!", "*ceremonious nod* the first of many."],
|
|
559
|
+
early: ["another commit. building momentum."],
|
|
560
|
+
late: ["commit #{count}. the codebase trembles.", "*lost count around commit 30*"],
|
|
151
561
|
},
|
|
152
562
|
};
|
|
153
563
|
|
|
154
|
-
|
|
564
|
+
function getEscalationTier(count: number): "first" | "early" | "mid" | "late" | null {
|
|
565
|
+
if (count === 0) return "first";
|
|
566
|
+
if (count < 10) return "early";
|
|
567
|
+
if (count < 50) return "mid";
|
|
568
|
+
return "late";
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const REASON_TO_COUNTER: Partial<Record<ReactionReason, string>> = {
|
|
572
|
+
error: "errors_seen",
|
|
573
|
+
"test-fail": "tests_failed",
|
|
574
|
+
commit: "commits_made",
|
|
575
|
+
push: "pushes_made",
|
|
576
|
+
"merge-conflict": "conflicts_resolved",
|
|
577
|
+
"lint-fail": "lint_fails",
|
|
578
|
+
"type-error": "type_errors",
|
|
579
|
+
"build-fail": "build_fails",
|
|
580
|
+
};
|
|
581
|
+
|
|
155
582
|
const RARITY_BONUS: Partial<Record<Rarity, string[]>> = {
|
|
156
583
|
legendary: [
|
|
157
584
|
"*legendary aura intensifies*",
|
|
@@ -166,24 +593,30 @@ export function getReaction(
|
|
|
166
593
|
reason: ReactionReason,
|
|
167
594
|
species: Species,
|
|
168
595
|
rarity: Rarity,
|
|
169
|
-
|
|
596
|
+
stats?: BuddyStats,
|
|
597
|
+
context?: ReactionContext,
|
|
170
598
|
): string {
|
|
171
|
-
// Try species-specific first
|
|
172
599
|
const speciesPool = SPECIES_REACTIONS[species]?.[reason];
|
|
173
600
|
const generalPool = REACTIONS[reason];
|
|
601
|
+
if (!generalPool || generalPool.length === 0) return "...";
|
|
174
602
|
|
|
175
|
-
// 40% chance of species-specific if available
|
|
176
603
|
const pool = speciesPool && Math.random() < 0.4 ? speciesPool : generalPool;
|
|
177
604
|
let reaction = pool[Math.floor(Math.random() * pool.length)];
|
|
178
605
|
|
|
179
|
-
|
|
606
|
+
if (stats) {
|
|
607
|
+
reaction = applyStatModifier(reaction, reason, stats);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
reaction = applyRarityFlair(reaction, rarity);
|
|
611
|
+
|
|
180
612
|
if (context?.line) reaction = reaction.replace("{line}", String(context.line));
|
|
181
613
|
if (context?.count) reaction = reaction.replace("{count}", String(context.count));
|
|
182
614
|
if (context?.lines) reaction = reaction.replace("{lines}", String(context.lines));
|
|
615
|
+
if (context?.files) reaction = reaction.replace("{files}", String(context.files));
|
|
616
|
+
if (context?.branch) reaction = reaction.replace("{branch}", context.branch);
|
|
183
617
|
|
|
184
618
|
return reaction;
|
|
185
619
|
}
|
|
186
|
-
|
|
187
620
|
export function getNameReaction(species: Species): string {
|
|
188
621
|
const pool = NAME_REACTIONS[species] ?? DEFAULT_NAME_REACTIONS;
|
|
189
622
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
@@ -193,8 +626,13 @@ export function getSuccessReaction(species: Species): string {
|
|
|
193
626
|
const pool = SUCCESS_REACTIONS[species] ?? DEFAULT_SUCCESS_REACTIONS;
|
|
194
627
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
195
628
|
}
|
|
629
|
+
export function isNameMentioned(text: string, name: string): boolean {
|
|
630
|
+
if (!name) return false;
|
|
631
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
632
|
+
return new RegExp(`(?<!\\w)${escaped}(?!\\w)`, "iu").test(text);
|
|
633
|
+
}
|
|
634
|
+
|
|
196
635
|
|
|
197
|
-
// ─── Personality generation (fallback names when API unavailable) ────────────
|
|
198
636
|
|
|
199
637
|
const FALLBACK_NAMES = [
|
|
200
638
|
"Crumpet", "Soup", "Pickle", "Biscuit", "Moth", "Gravy",
|