opencode-overclock 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-overclock",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Power-ups for opencode: background tasks, scheduling, sandboxed bash, tool hooks, usage telemetry, checkpoints. Modular, toggleable.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -54,6 +54,17 @@ function rollStat(rng: () => number): number {
54
54
  return 1 + Math.floor(rng() * 10)
55
55
  }
56
56
 
57
+ /**
58
+ * Companions persist in TUI kv and outlive the sprite sheet, so an install that
59
+ * hatched a species we have since retired would look it up and find no art. Move
60
+ * it onto a species we still draw, keeping the identity that isn't the drawing:
61
+ * same name, rarity, stats and hatch date. Returns undefined when nothing to do.
62
+ */
63
+ export function migrateSpecies(c: Companion, rng: () => number = Math.random): Companion | undefined {
64
+ if ((SPECIES as readonly string[]).includes(c.species)) return undefined
65
+ return { ...c, species: pick(rng, SPECIES) }
66
+ }
67
+
57
68
  /** One-line card for the /oc-buddy toast. */
58
69
  export function describeCompanion(c: Companion): string {
59
70
  const s = c.stats
@@ -30,40 +30,94 @@ const EYES = {
30
30
  } as const
31
31
 
32
32
  interface SpeciesArt {
33
- /** Two body frames, alternated while idle: tail flick, ear twitch, wing flap... */
33
+ /** Rest pose + fidget pose: tail flick, ear twitch, wing beat... */
34
34
  idle: [string[], string[]]
35
+ /**
36
+ * Which of the two poses a tick shows. Per-species on purpose: alternating
37
+ * every tick reads as a strobe, and it makes every species move alike. A cat
38
+ * flicks its tail rarely, a dog wags nonstop, a dragon's wingbeat is slow and
39
+ * held at the top, a ghost never quite lands.
40
+ */
41
+ beat: (t: number) => 0 | 1
42
+ }
43
+
44
+ /** Fidget pose for `hold` ticks out of every `period`; rest pose otherwise. */
45
+ function pulse(period: number, hold = 1): (t: number) => 0 | 1 {
46
+ return (t) => (t % period < hold ? 1 : 0)
35
47
  }
36
48
 
37
49
  const ART: Record<Species, SpeciesArt> = {
50
+ // tail flick: rare, one tick, then dead still again
38
51
  cat: {
39
52
  idle: [
40
- [" /\\_/\\", "( {E} )", " > ^ <"],
41
- [" /\\_/\\", "( {E} )", " > ^ <~"],
53
+ [" /\\_/\\", " ( {E} )", " > ^ <"],
54
+ [" /\\_/\\", " ( {E} )", " > ^ <~"],
42
55
  ],
56
+ beat: pulse(9),
43
57
  },
58
+ // ear perk: a quick double twitch, then a long settle
44
59
  dog: {
45
60
  idle: [
46
- [" /^-^\\", "( {E} )", "/ ~ \\"],
47
- [" /^-^/", "( {E} )", "/ ~ \\"],
61
+ [" ,---,", " /({E})\\", " (__U__)"],
62
+ [" ,---,", " /({E})/", " (__U__)"],
63
+ ],
64
+ beat: (t) => (t % 7 === 0 || t % 7 === 2 ? 1 : 0),
65
+ },
66
+ // ear wiggle: twitchier than the dog, never for long
67
+ bunny: {
68
+ idle: [
69
+ [" (\\_/)", " ({E})", ' (")_(")'],
70
+ [" (/_\\)", " ({E})", ' (")_(")'],
71
+ ],
72
+ beat: (t) => (t % 11 === 0 || t % 11 === 2 ? 1 : 0),
73
+ },
74
+ // feather ruffle: an owl mostly just sits there
75
+ owl: {
76
+ idle: [
77
+ [" ,_,", " ({E})", " {`\"'}"],
78
+ [" ,_,", " ({E})", " {'\"`}"],
79
+ ],
80
+ beat: pulse(13),
81
+ },
82
+ // wing beat: fast, never stops fluttering
83
+ bat: {
84
+ idle: [
85
+ [" /^\\_/^\\", " <({E})>", " \\v/"],
86
+ [" /^\\_/^\\", " ^({E})^", " \\v/"],
87
+ ],
88
+ beat: pulse(2),
89
+ },
90
+ // waddle: a slow rock, feet turning in and out
91
+ penguin: {
92
+ idle: [
93
+ [" ({E})", " <|_v_|>", " _/ \\_"],
94
+ [" ({E})", " <|_v_|>", " _\\ /_"],
48
95
  ],
96
+ beat: pulse(6, 3),
49
97
  },
50
- dragon: {
98
+ // ripples: spreading out, then settling
99
+ duck: {
51
100
  idle: [
52
- [" /\\~/\\", " ( {E} )", "<( v )>"],
53
- [" /\\~/\\", " ( {E} )", "^( v )^"],
101
+ [" ,-,", " ({E})>", " ~\\__/~"],
102
+ [" ,-,", " ({E})>", " ~ \\__/ ~"],
54
103
  ],
104
+ beat: pulse(6, 2),
55
105
  },
106
+ // float: never lands, drifting the whole time
56
107
  ghost: {
57
108
  idle: [
58
109
  [" .-.", " ({E})", " '\"'\"'"],
59
110
  [" .-.", " ({E})", ' ~"~"~'],
60
111
  ],
112
+ beat: pulse(4, 2),
61
113
  },
114
+ // squash: a brief squish, then a long settle
62
115
  slime: {
63
116
  idle: [
64
117
  [" ___", " ({E})", " (_____)"],
65
118
  [" ___", " (({E}))", "(_______)"],
66
119
  ],
120
+ beat: pulse(10, 2),
67
121
  },
68
122
  }
69
123
 
@@ -1,4 +1,14 @@
1
- export const SPECIES = ["cat", "dog", "dragon", "ghost", "slime"] as const
1
+ export const SPECIES = [
2
+ "cat",
3
+ "dog",
4
+ "bunny",
5
+ "owl",
6
+ "bat",
7
+ "penguin",
8
+ "duck",
9
+ "ghost",
10
+ "slime",
11
+ ] as const
2
12
  export type Species = (typeof SPECIES)[number]
3
13
 
4
14
  export type Rarity = "common" | "uncommon" | "rare" | "legendary"