@bitefoundry/retrieviewer 0.0.3 → 0.0.4

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.
Files changed (254) hide show
  1. package/ASSET-PROVENANCE.md +6 -0
  2. package/ASSETS-LICENSE.md +2 -1
  3. package/ATTRIBUTION.md +6 -1
  4. package/COMFORT-ART.md +65 -0
  5. package/DESKTOP-PLATFORMS.md +6 -1
  6. package/PLUGIN.md +13 -10
  7. package/PREREQUISITES.md +95 -0
  8. package/PUPPY-MEMORY.md +102 -1
  9. package/README.ko.md +110 -0
  10. package/README.md +117 -59
  11. package/RELEASING.md +23 -12
  12. package/THIRD-PARTY-NOTICES.md +5 -3
  13. package/braille.mjs +35 -9
  14. package/examples/live.mjs +2 -2
  15. package/integrations/linux-overlay/overlay.py +2 -2
  16. package/integrations/macos-overlay/overlay.jxa +8 -6
  17. package/integrations/opencode/runtime.mjs +4 -4
  18. package/integrations/opencode/tui.tsx +1 -1
  19. package/integrations/windows-overlay/Overlay.cs +4 -4
  20. package/integrations/windows-overlay/protocol.mjs +11 -7
  21. package/package.json +34 -13
  22. package/puppy-comfort-sprites.mjs +25 -0
  23. package/puppy-companion-comfort-q5.bin.gz +0 -0
  24. package/puppy-companion-comfort.json +77 -0
  25. package/puppy-companion-life.mjs +49 -16
  26. package/puppy-companion-objects.mjs +12 -0
  27. package/puppy-frame-predictive.mjs +15 -9
  28. package/puppy-frame-store.mjs +2 -2
  29. package/puppy-paper-world.mjs +14 -0
  30. package/puppy-paper.mjs +65 -14
  31. package/retrieviewer-plugin.d.mts +1 -1
  32. package/retrieviewer-plugin.mjs +1 -1
  33. package/retrieviewer.d.mts +10 -4
  34. package/retrieviewer.mjs +20 -14
  35. package/locomotion-core.mjs +0 -21
  36. package/locomotion-puppy.animal +0 -0
  37. package/vendor/procedural-animals/package.json +0 -40
  38. package/vendor/procedural-animals/src/animal.js +0 -146
  39. package/vendor/procedural-animals/src/bake.js +0 -51
  40. package/vendor/procedural-animals/src/build.js +0 -81
  41. package/vendor/procedural-animals/src/core/build/coatKit.js +0 -121
  42. package/vendor/procedural-animals/src/core/build/featherCards.js +0 -189
  43. package/vendor/procedural-animals/src/core/build/finEdges.js +0 -85
  44. package/vendor/procedural-animals/src/core/build/furSlope.js +0 -115
  45. package/vendor/procedural-animals/src/core/build/mesh.js +0 -67
  46. package/vendor/procedural-animals/src/core/build/pipeline.js +0 -272
  47. package/vendor/procedural-animals/src/core/build/seams.js +0 -183
  48. package/vendor/procedural-animals/src/core/build/warp.js +0 -112
  49. package/vendor/procedural-animals/src/core/build/weights.js +0 -393
  50. package/vendor/procedural-animals/src/core/math/vec.js +0 -81
  51. package/vendor/procedural-animals/src/core/motion/actions.js +0 -800
  52. package/vendor/procedural-animals/src/core/motion/bird.js +0 -3063
  53. package/vendor/procedural-animals/src/core/motion/birdActions.js +0 -1059
  54. package/vendor/procedural-animals/src/core/motion/common.js +0 -158
  55. package/vendor/procedural-animals/src/core/motion/index.js +0 -22
  56. package/vendor/procedural-animals/src/core/motion/quadruped.js +0 -2875
  57. package/vendor/procedural-animals/src/core/motion/snake.js +0 -1594
  58. package/vendor/procedural-animals/src/core/motion/spider.js +0 -1810
  59. package/vendor/procedural-animals/src/core/motion/swimmer.js +0 -1047
  60. package/vendor/procedural-animals/src/core/motion/swimmerActions.js +0 -613
  61. package/vendor/procedural-animals/src/core/render/animalObject.js +0 -262
  62. package/vendor/procedural-animals/src/core/render/coatMaterial.js +0 -1301
  63. package/vendor/procedural-animals/src/core/render/dqs.js +0 -159
  64. package/vendor/procedural-animals/src/core/render/eyes.js +0 -676
  65. package/vendor/procedural-animals/src/core/render/membranes.js +0 -77
  66. package/vendor/procedural-animals/src/core/render/skeleton.js +0 -41
  67. package/vendor/procedural-animals/src/core/rig/bird.js +0 -327
  68. package/vendor/procedural-animals/src/core/rig/quadruped.js +0 -76
  69. package/vendor/procedural-animals/src/core/rig/rig.js +0 -79
  70. package/vendor/procedural-animals/src/core/rig/snake.js +0 -76
  71. package/vendor/procedural-animals/src/core/rig/spider.js +0 -110
  72. package/vendor/procedural-animals/src/core/rig/swimmer.js +0 -181
  73. package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +0 -53
  74. package/vendor/procedural-animals/src/core/sdf/mesher.js +0 -238
  75. package/vendor/procedural-animals/src/core/sdf/sdf.js +0 -263
  76. package/vendor/procedural-animals/src/index.d.ts +0 -98
  77. package/vendor/procedural-animals/src/index.js +0 -29
  78. package/vendor/procedural-animals/src/registry.js +0 -48
  79. package/vendor/procedural-animals/src/species/bear/behaviour.js +0 -463
  80. package/vendor/procedural-animals/src/species/bear/claws.js +0 -147
  81. package/vendor/procedural-animals/src/species/bear/coat.js +0 -726
  82. package/vendor/procedural-animals/src/species/bear/index.js +0 -139
  83. package/vendor/procedural-animals/src/species/bear/motion.js +0 -112
  84. package/vendor/procedural-animals/src/species/bear/regions.js +0 -78
  85. package/vendor/procedural-animals/src/species/bear/rig.js +0 -112
  86. package/vendor/procedural-animals/src/species/bear/sculpt.js +0 -272
  87. package/vendor/procedural-animals/src/species/boar/behaviour.js +0 -335
  88. package/vendor/procedural-animals/src/species/boar/coat.js +0 -372
  89. package/vendor/procedural-animals/src/species/boar/index.js +0 -110
  90. package/vendor/procedural-animals/src/species/boar/motion.js +0 -85
  91. package/vendor/procedural-animals/src/species/boar/regions.js +0 -88
  92. package/vendor/procedural-animals/src/species/boar/rig.js +0 -111
  93. package/vendor/procedural-animals/src/species/boar/sculpt.js +0 -285
  94. package/vendor/procedural-animals/src/species/cat/behaviour.js +0 -559
  95. package/vendor/procedural-animals/src/species/cat/coat.js +0 -841
  96. package/vendor/procedural-animals/src/species/cat/index.js +0 -211
  97. package/vendor/procedural-animals/src/species/cat/motion.js +0 -101
  98. package/vendor/procedural-animals/src/species/cat/regions.js +0 -82
  99. package/vendor/procedural-animals/src/species/cat/rig.js +0 -100
  100. package/vendor/procedural-animals/src/species/cat/sculpt.js +0 -266
  101. package/vendor/procedural-animals/src/species/cat/whiskers.js +0 -110
  102. package/vendor/procedural-animals/src/species/cheetah/coat.js +0 -427
  103. package/vendor/procedural-animals/src/species/cheetah/index.js +0 -51
  104. package/vendor/procedural-animals/src/species/cheetah/joints.js +0 -3
  105. package/vendor/procedural-animals/src/species/cheetah/motion.js +0 -77
  106. package/vendor/procedural-animals/src/species/cheetah/regions.js +0 -95
  107. package/vendor/procedural-animals/src/species/cheetah/rig.js +0 -66
  108. package/vendor/procedural-animals/src/species/cheetah/sculpt.js +0 -158
  109. package/vendor/procedural-animals/src/species/chicken/coat.js +0 -313
  110. package/vendor/procedural-animals/src/species/chicken/coverts.js +0 -320
  111. package/vendor/procedural-animals/src/species/chicken/index.js +0 -110
  112. package/vendor/procedural-animals/src/species/chicken/motion.js +0 -177
  113. package/vendor/procedural-animals/src/species/chicken/regions.js +0 -66
  114. package/vendor/procedural-animals/src/species/chicken/rig.js +0 -144
  115. package/vendor/procedural-animals/src/species/chicken/sculpt.js +0 -389
  116. package/vendor/procedural-animals/src/species/chicken/wingLook.js +0 -66
  117. package/vendor/procedural-animals/src/species/chicken/wingStack.js +0 -124
  118. package/vendor/procedural-animals/src/species/cow/behaviour.js +0 -521
  119. package/vendor/procedural-animals/src/species/cow/coat.js +0 -465
  120. package/vendor/procedural-animals/src/species/cow/index.js +0 -118
  121. package/vendor/procedural-animals/src/species/cow/motion.js +0 -81
  122. package/vendor/procedural-animals/src/species/cow/regions.js +0 -98
  123. package/vendor/procedural-animals/src/species/cow/rig.js +0 -116
  124. package/vendor/procedural-animals/src/species/cow/sculpt.js +0 -339
  125. package/vendor/procedural-animals/src/species/crow/coat.js +0 -145
  126. package/vendor/procedural-animals/src/species/crow/index.js +0 -70
  127. package/vendor/procedural-animals/src/species/crow/joints.js +0 -3
  128. package/vendor/procedural-animals/src/species/crow/motion.js +0 -101
  129. package/vendor/procedural-animals/src/species/crow/regions.js +0 -50
  130. package/vendor/procedural-animals/src/species/crow/rig.js +0 -83
  131. package/vendor/procedural-animals/src/species/crow/sculpt.js +0 -118
  132. package/vendor/procedural-animals/src/species/deer/behaviour.js +0 -513
  133. package/vendor/procedural-animals/src/species/deer/coat.js +0 -391
  134. package/vendor/procedural-animals/src/species/deer/index.js +0 -106
  135. package/vendor/procedural-animals/src/species/deer/motion.js +0 -97
  136. package/vendor/procedural-animals/src/species/deer/regions.js +0 -60
  137. package/vendor/procedural-animals/src/species/deer/rig.js +0 -124
  138. package/vendor/procedural-animals/src/species/deer/sculpt.js +0 -297
  139. package/vendor/procedural-animals/src/species/dog/behaviour.js +0 -521
  140. package/vendor/procedural-animals/src/species/dog/coat.js +0 -495
  141. package/vendor/procedural-animals/src/species/dog/index.js +0 -144
  142. package/vendor/procedural-animals/src/species/dog/motion.js +0 -118
  143. package/vendor/procedural-animals/src/species/dog/regions.js +0 -61
  144. package/vendor/procedural-animals/src/species/dog/rig.js +0 -129
  145. package/vendor/procedural-animals/src/species/dog/sculpt.js +0 -246
  146. package/vendor/procedural-animals/src/species/eagle/coat.js +0 -250
  147. package/vendor/procedural-animals/src/species/eagle/index.js +0 -76
  148. package/vendor/procedural-animals/src/species/eagle/joints.js +0 -3
  149. package/vendor/procedural-animals/src/species/eagle/motion.js +0 -137
  150. package/vendor/procedural-animals/src/species/eagle/regions.js +0 -57
  151. package/vendor/procedural-animals/src/species/eagle/rig.js +0 -107
  152. package/vendor/procedural-animals/src/species/eagle/sculpt.js +0 -137
  153. package/vendor/procedural-animals/src/species/fish/coat.js +0 -271
  154. package/vendor/procedural-animals/src/species/fish/index.js +0 -88
  155. package/vendor/procedural-animals/src/species/fish/motion.js +0 -92
  156. package/vendor/procedural-animals/src/species/fish/regions.js +0 -27
  157. package/vendor/procedural-animals/src/species/fish/rig.js +0 -143
  158. package/vendor/procedural-animals/src/species/fish/sculpt.js +0 -214
  159. package/vendor/procedural-animals/src/species/fish/variants.js +0 -126
  160. package/vendor/procedural-animals/src/species/fox/behaviour.js +0 -314
  161. package/vendor/procedural-animals/src/species/fox/coat.js +0 -444
  162. package/vendor/procedural-animals/src/species/fox/index.js +0 -120
  163. package/vendor/procedural-animals/src/species/fox/motion.js +0 -81
  164. package/vendor/procedural-animals/src/species/fox/regions.js +0 -59
  165. package/vendor/procedural-animals/src/species/fox/rig.js +0 -91
  166. package/vendor/procedural-animals/src/species/fox/sculpt.js +0 -202
  167. package/vendor/procedural-animals/src/species/frog/behaviour.js +0 -590
  168. package/vendor/procedural-animals/src/species/frog/coat.js +0 -305
  169. package/vendor/procedural-animals/src/species/frog/index.js +0 -97
  170. package/vendor/procedural-animals/src/species/frog/motion.js +0 -69
  171. package/vendor/procedural-animals/src/species/frog/regions.js +0 -46
  172. package/vendor/procedural-animals/src/species/frog/rig.js +0 -156
  173. package/vendor/procedural-animals/src/species/frog/sculpt.js +0 -240
  174. package/vendor/procedural-animals/src/species/goat/behaviour.js +0 -509
  175. package/vendor/procedural-animals/src/species/goat/coat.js +0 -590
  176. package/vendor/procedural-animals/src/species/goat/index.js +0 -149
  177. package/vendor/procedural-animals/src/species/goat/motion.js +0 -95
  178. package/vendor/procedural-animals/src/species/goat/regions.js +0 -98
  179. package/vendor/procedural-animals/src/species/goat/rig.js +0 -181
  180. package/vendor/procedural-animals/src/species/goat/sculpt.js +0 -547
  181. package/vendor/procedural-animals/src/species/horse/coat.js +0 -361
  182. package/vendor/procedural-animals/src/species/horse/coatSeam.js +0 -122
  183. package/vendor/procedural-animals/src/species/horse/index.js +0 -80
  184. package/vendor/procedural-animals/src/species/horse/motion.js +0 -245
  185. package/vendor/procedural-animals/src/species/horse/regions.js +0 -60
  186. package/vendor/procedural-animals/src/species/horse/rig.js +0 -117
  187. package/vendor/procedural-animals/src/species/horse/sculpt.js +0 -316
  188. package/vendor/procedural-animals/src/species/horse/seamWeights.js +0 -272
  189. package/vendor/procedural-animals/src/species/lion/behaviour.js +0 -509
  190. package/vendor/procedural-animals/src/species/lion/coat.js +0 -1016
  191. package/vendor/procedural-animals/src/species/lion/index.js +0 -111
  192. package/vendor/procedural-animals/src/species/lion/motion.js +0 -87
  193. package/vendor/procedural-animals/src/species/lion/regions.js +0 -106
  194. package/vendor/procedural-animals/src/species/lion/rig.js +0 -110
  195. package/vendor/procedural-animals/src/species/lion/sculpt.js +0 -384
  196. package/vendor/procedural-animals/src/species/lion/whiskers.js +0 -132
  197. package/vendor/procedural-animals/src/species/pig/behaviour.js +0 -575
  198. package/vendor/procedural-animals/src/species/pig/coat.js +0 -730
  199. package/vendor/procedural-animals/src/species/pig/ears.js +0 -242
  200. package/vendor/procedural-animals/src/species/pig/index.js +0 -161
  201. package/vendor/procedural-animals/src/species/pig/motion.js +0 -105
  202. package/vendor/procedural-animals/src/species/pig/regions.js +0 -100
  203. package/vendor/procedural-animals/src/species/pig/rig.js +0 -152
  204. package/vendor/procedural-animals/src/species/pig/sculpt.js +0 -382
  205. package/vendor/procedural-animals/src/species/rabbit/behaviour.js +0 -605
  206. package/vendor/procedural-animals/src/species/rabbit/coat.js +0 -285
  207. package/vendor/procedural-animals/src/species/rabbit/index.js +0 -85
  208. package/vendor/procedural-animals/src/species/rabbit/motion.js +0 -85
  209. package/vendor/procedural-animals/src/species/rabbit/regions.js +0 -48
  210. package/vendor/procedural-animals/src/species/rabbit/rig.js +0 -99
  211. package/vendor/procedural-animals/src/species/rabbit/sculpt.js +0 -148
  212. package/vendor/procedural-animals/src/species/rat/behaviour.js +0 -539
  213. package/vendor/procedural-animals/src/species/rat/coat.js +0 -341
  214. package/vendor/procedural-animals/src/species/rat/index.js +0 -111
  215. package/vendor/procedural-animals/src/species/rat/motion.js +0 -90
  216. package/vendor/procedural-animals/src/species/rat/regions.js +0 -92
  217. package/vendor/procedural-animals/src/species/rat/rig.js +0 -112
  218. package/vendor/procedural-animals/src/species/rat/sculpt.js +0 -163
  219. package/vendor/procedural-animals/src/species/rat/whiskers.js +0 -119
  220. package/vendor/procedural-animals/src/species/shark/coat.js +0 -383
  221. package/vendor/procedural-animals/src/species/shark/index.js +0 -104
  222. package/vendor/procedural-animals/src/species/shark/motion.js +0 -69
  223. package/vendor/procedural-animals/src/species/shark/regions.js +0 -34
  224. package/vendor/procedural-animals/src/species/shark/rig.js +0 -194
  225. package/vendor/procedural-animals/src/species/shark/sculpt.js +0 -343
  226. package/vendor/procedural-animals/src/species/shark/variants.js +0 -105
  227. package/vendor/procedural-animals/src/species/sheep/behaviour.js +0 -522
  228. package/vendor/procedural-animals/src/species/sheep/coat.js +0 -529
  229. package/vendor/procedural-animals/src/species/sheep/index.js +0 -152
  230. package/vendor/procedural-animals/src/species/sheep/motion.js +0 -86
  231. package/vendor/procedural-animals/src/species/sheep/neck.js +0 -41
  232. package/vendor/procedural-animals/src/species/sheep/regions.js +0 -62
  233. package/vendor/procedural-animals/src/species/sheep/rig.js +0 -163
  234. package/vendor/procedural-animals/src/species/sheep/sculpt.js +0 -542
  235. package/vendor/procedural-animals/src/species/snake/coat.js +0 -315
  236. package/vendor/procedural-animals/src/species/snake/index.js +0 -73
  237. package/vendor/procedural-animals/src/species/snake/motion.js +0 -51
  238. package/vendor/procedural-animals/src/species/snake/regions.js +0 -51
  239. package/vendor/procedural-animals/src/species/snake/rig.js +0 -108
  240. package/vendor/procedural-animals/src/species/snake/sculpt.js +0 -122
  241. package/vendor/procedural-animals/src/species/spider/coat.js +0 -279
  242. package/vendor/procedural-animals/src/species/spider/index.js +0 -78
  243. package/vendor/procedural-animals/src/species/spider/motion.js +0 -72
  244. package/vendor/procedural-animals/src/species/spider/regions.js +0 -87
  245. package/vendor/procedural-animals/src/species/spider/rig.js +0 -118
  246. package/vendor/procedural-animals/src/species/spider/sculpt.js +0 -182
  247. package/vendor/procedural-animals/src/species/wolf/behaviour.js +0 -160
  248. package/vendor/procedural-animals/src/species/wolf/coat.js +0 -749
  249. package/vendor/procedural-animals/src/species/wolf/index.js +0 -107
  250. package/vendor/procedural-animals/src/species/wolf/motion.js +0 -80
  251. package/vendor/procedural-animals/src/species/wolf/regions.js +0 -57
  252. package/vendor/procedural-animals/src/species/wolf/rig.js +0 -87
  253. package/vendor/procedural-animals/src/species/wolf/sculpt.js +0 -339
  254. package/vendor/procedural-animals/src/worker.js +0 -29
package/README.md CHANGED
@@ -1,90 +1,148 @@
1
- # Retrieviewer
1
+ <p align="center">
2
+ <a href="https://bitefoundry.github.io/retrieviewer/"><img src="https://raw.githubusercontent.com/BiteFoundry/retrieviewer/main/docs/assets/preview.png" alt="Retrieviewer — a fluffy retriever drawn with tiny monochrome Braille dots" width="960"></a>
3
+ </p>
2
4
 
3
- An autonomous, fluffy Braille retriever that lives above your app window or in a TUI pane.
4
- Give it a ball or a treat; otherwise it wanders and plays on its own. By BiteFoundry.
5
+ <h1 align="center">Retrieviewer</h1>
6
+ <p align="center">A little company for your screen.</p>
7
+ <p align="center">
8
+ <a href="https://bitefoundry.github.io/retrieviewer/">Meet your retriever</a> ·
9
+ <a href="./README.ko.md">한국어</a> ·
10
+ <a href="https://www.npmjs.com/package/@bitefoundry/retrieviewer">npm</a> ·
11
+ <a href="https://github.com/BiteFoundry/retrieviewer/issues">Feedback</a>
12
+ </p>
5
13
 
6
- **Version 0.0.3.** Source code is MIT; puppy artwork is CC BY-SA 4.0, including
7
- commercial use and adaptations under its attribution/ShareAlike conditions.
8
- See [licensing](./LICENSE), [artwork terms](./ASSETS-LICENSE.md),
9
- [credits](./ATTRIBUTION.md) and [brand notice](./TRADEMARKS.md).
10
- The complete package is not MIT-only.
14
+ A fluffy, autonomous Braille-art retriever that hangs out above an app window.
15
+ It wanders, runs, flops belly-up and naps. Toss a ball, offer a treat or play tug.
16
+ Get back to your thing.
11
17
 
12
- ## Install
18
+ Made by [BiteFoundry](https://github.com/BiteFoundry). No model API, account or
19
+ telemetry is needed by the runtime.
13
20
 
14
- Node.js >=20 is required. Windows10/11 x64 uses the Windows .NET Framework4
15
- compiler (automatic helper build on first launch). Linux needs X11, a compositor,
16
- system Python3.6+ and X11/Xrender/Xext; AlmaLinux8/GLIBC2.28 has been tested.
17
- macOS uses built-in osascript/AppKit and is **experimental, not runtime verified**.
18
- Native Wayland is not supported. See [platform requirements](./DESKTOP-PLATFORMS.md).
21
+ ## Bring one home
19
22
 
20
- 1. Install:
23
+ Install **on the computer displaying the app**, in a terminal. Node.js is required;
24
+ [install Node/npm first](./PREREQUISITES.md) if you do not have them.
25
+
26
+ 1. Install (or update):
21
27
 
22
28
  ```sh
23
- npm install -g @bitefoundry/retrieviewer
29
+ npm install -g @bitefoundry/retrieviewer@latest
24
30
  ```
25
31
 
26
- 2. Run and choose the app window you want your puppy to live on:
32
+ 2. Run, then choose an app in the window picker:
27
33
 
28
34
  ```sh
29
35
  retrieviewer desktop
30
36
  ```
31
37
 
32
- That's it. Use your app normally. Ball/treat controls sit above the selected
33
- window; the pet lets ordinary clicks through. No Codex patch, wrapper, MCP setup,
34
- administrator access, or automatic startup registration. It follows a whole window,
35
- not individual tabs, and hides when you switch away. It is a separate transparent
36
- native window, **not a widget injected into another app**. macOS is experimental;
37
- exclusive fullscreen apps and privileged/security surfaces are not certified.
38
+ Next time, just run `retrieviewer desktop`. This is a separate transparent,
39
+ click-through native overlay—not a patched app, shell wrapper or injected MCP
40
+ widget. It follows a whole app window, not a tab, and hides when that window is
41
+ inactive or minimized. No automatic startup entry is installed.
42
+
43
+ > **Cursor / VS Code Remote SSH:** run those commands in your **local** computer's
44
+ > terminal, not the remote server's terminal. The puppy belongs where the window
45
+ > is displayed. A server's `DISPLAY=:1` refers to that server's X11 display, which
46
+ > you may be viewing through VNC; it is not automatically your local Cursor window.
38
47
 
39
- Exit from the tray icon or `retrieviewer desktop-stop`. To remove the companion's
40
- own cache, run `retrieviewer desktop-remove --yes`; then
41
- `npm uninstall -g @bitefoundry/retrieviewer` removes the package. See
42
- [platform support](./DESKTOP-PLATFORMS.md) and [Windows controls and removal](./WINDOWS-COMPANION.md).
48
+ <details>
49
+ <summary>Try once with npx / command not found / Node is missing</summary>
43
50
 
44
- ## Optional: native OpenCode pane
51
+ With Node/npm installed, try without a global installation:
45
52
 
46
53
  ```sh
47
- retrieviewer enable --agent opencode --yes
48
- opencode
54
+ npx --yes --package @bitefoundry/retrieviewer@latest retrieviewer desktop
49
55
  ```
50
56
 
51
- Without `--agent` / `--yes`, interactive `retrieviewer enable` offers agent
52
- selection and a preview before changing configuration. The native adapter is
53
- currently verified only with OpenCode 2.1.2 on Windows. Codex, Claude Code, Cursor
54
- Agent, Grok and Antigravity native panes are not implemented. MCP connectivity
55
- alone does not create a pet inside their screens.
57
+ `npx` does **not** permanently add `retrieviewer` to PATH. Use the global install
58
+ above for future short commands. If that still says command not found, see
59
+ [PATH fixes for bash, csh/tcsh and Windows](./PREREQUISITES.md#command-not-found).
60
+ Do not use `sudo npm install -g` as a blanket workaround.
56
61
 
57
- Inside OpenCode use `/retrieviewer ball`, `/retrieviewer treat`, or
58
- `/retrieviewer disable`. See [installation and removal](./INSTALLING.md).
62
+ </details>
59
63
 
60
- ## Embed in your own TUI
64
+ ## Where it can live
61
65
 
62
- Install `@bitefoundry/retrieviewer` in your app, without `-g`, then use the host callbacks:
66
+ | Desktop | Status / requirements |
67
+ | --- | --- |
68
+ | Windows 10/11 x64 | Live tested. Node + Windows .NET Framework 4 compiler; helper builds on first launch. |
69
+ | Linux X11 | AlmaLinux 8 / GLIBC 2.28 / Python 3.6.8 / Node 22.23.4 tested in an isolated composited X11 desktop. Requires system Python 3.6+, X11/Xrender/Xext and a compositor. |
70
+ | macOS | **Experimental; no Mac runtime verification yet.** Uses built-in osascript/AppKit. |
71
+ | Native Wayland / headless SSH | Not supported by the desktop overlay. No session/privacy workaround is installed. |
63
72
 
64
- ```js
65
- import {createPetPlugin} from '@bitefoundry/retrieviewer/plugin';
73
+ Linux currently favors lower load: 16px cells / 15fps versus the Windows default
74
+ 8px cells / 30fps, so its dots look coarser. The Q5 artwork is identical.
75
+ This is not a zero-resource widget: the npm tarball is about 19 MB. An earlier
76
+ 0.0.3 AlmaLinux test used roughly 180 MiB of Node RSS, plus the Python helper;
77
+ that is not a memory budget or a new Linux GUI check for 0.0.4.
78
+ See [platform details and verification boundaries](./DESKTOP-PLATFORMS.md).
79
+
80
+ ## Easy to leave, too
81
+
82
+ Quit through the controls, or run `retrieviewer desktop-stop`.
83
+ To remove the companion's own cache and the package:
84
+
85
+ ```sh
86
+ retrieviewer desktop-remove --yes
87
+ npm uninstall -g @bitefoundry/retrieviewer
88
+ ```
89
+
90
+ The desktop companion does not edit agent credentials, app binaries or shell
91
+ profiles. [Optional OpenCode registration](./INSTALLING.md) is separate; disconnect
92
+ that registration before uninstalling if you explicitly enabled it.
93
+
94
+ ## Put it inside your own TUI
66
95
 
67
- const puppy = await createPetPlugin({host: {
68
- getSize: () => ({columns: pane.width, rows: pane.height}),
69
- render: ({text}) => pane.setContent(text),
70
- onError: error => logToYourApp(error),
71
- }});
96
+ The core is host-driven. Your app owns the pane, input and clock; the puppy does
97
+ not take over stdin/stdout.
98
+
99
+ ```js
100
+ import { createPetPlugin } from '@bitefoundry/retrieviewer/plugin';
101
+
102
+ const puppy = await createPetPlugin({
103
+ host: {
104
+ getSize: () => ({ columns: pane.width, rows: pane.height }),
105
+ render: ({ text }) => pane.setContent(text),
106
+ onError: error => logToYourApp(error),
107
+ },
108
+ });
72
109
  puppy.start();
73
- // Optional interaction: puppy.interact('ball') / puppy.interact('treat')
110
+ // puppy.interact('ball') / puppy.interact('treat') / puppy.interact('tug')
74
111
  // On unmount: puppy.dispose()
75
112
  ```
76
113
 
77
- `pane` and `logToYourApp` are supplied by your app. The pet does not take over
78
- stdin, stdout or the screen. Q5 (32-level) artwork is bundled; no model API,
79
- account or telemetry is needed by the runtime. npm dependencies require an
80
- initial download or a populated cache. This is not a tiny icon: the complete
81
- tarball is about 21 MB and a previous Windows sample used about 172 MB RSS.
114
+ `pane` and `logToYourApp` come from your app.
115
+ [Plugin lifecycle](./PLUGIN.md) · [Core / JSONL bridge](./EMBEDDING.md) ·
116
+ [Optional OpenCode adapter](./INSTALLING.md).
117
+ The native OpenCode pane has Windows/OpenCode 2.1.2 host evidence; Codex, Claude,
118
+ Cursor, Grok and Antigravity **in-terminal** renderers are not implemented.
119
+ An MCP connection alone cannot insert a persistent picture into those clients.
120
+
121
+ ## Build, contribute, be kind
122
+
123
+ ```sh
124
+ npm ci
125
+ npm test
126
+ npm run build:site
127
+ npm start
128
+ ```
129
+
130
+ The public tree contains the shipped runtime, Q5 art, focused runtime/adapter
131
+ tests and reproducible site build. Historical art experiments, original reference
132
+ photos and private worker/QA logs are intentionally absent.
133
+ See [contributing](./CONTRIBUTING.md) and [source scope](./SOURCE-SCOPE.md).
134
+ Compatibility reports are welcome—especially real Mac testing and X11 desktops.
135
+
136
+ ## Code and coat have different licenses
137
+
138
+ **Code: MIT. Artwork: CC BY-SA 4.0.** Commercial reuse is permitted under the
139
+ respective terms. Keep artwork credits and ShareAlike conditions when applicable;
140
+ the complete package is **not MIT-only**.
82
141
 
83
- - [Plugin lifecycle](./PLUGIN.md) — host callbacks, clocks and embedding.
84
- - [Core and JSONL bridge](./EMBEDDING.md) — JS and non-JS TUI integration.
85
- - [Release process](./RELEASING.md) — checks and support boundaries.
86
- - [Third-party notices](./THIRD-PARTY-NOTICES.md).
142
+ [Code license](./LICENSE-CODE) · [Artwork terms](./ASSETS-LICENSE.md) ·
143
+ [Required credits](./ATTRIBUTION.md) · [Third-party notices](./THIRD-PARTY-NOTICES.md) ·
144
+ [Brand notice](./TRADEMARKS.md).
87
145
 
88
- The runtime has no install scripts and never edits agent settings automatically.
89
- Only an explicit `retrieviewer enable` changes settings, after a preview/approval
90
- or an explicit `--yes`. Unsupported hosts are refused.
146
+ The puppy artwork was developed with AI-generated imagery and programmatic pose,
147
+ grounding and frame processing. It is authored animation, not motion capture or
148
+ a claim of sentience.
package/RELEASING.md CHANGED
@@ -1,6 +1,6 @@
1
- # Retrieviewer 0.0.3 release process
1
+ # Retrieviewer 0.0.4 release process
2
2
 
3
- Target: `@bitefoundry/retrieviewer@0.0.3`, public npm registry, `latest` tag.
3
+ Target: `@bitefoundry/retrieviewer@0.0.4`, public npm registry, `latest` tag.
4
4
  The npm organization `bitefoundry` uses the free public-packages plan; account
5
5
  `shinick` owns the organization.
6
6
 
@@ -12,11 +12,15 @@ artwork draft is superseded. ATTRIBUTION.md retains the photographic references
12
12
  and original license links. ASSET-PROVENANCE.md records the bounded review and
13
13
  remaining limits; this is not comprehensive legal clearance.
14
14
 
15
- The owner explicitly authorized publishing0.0.3 with the cross-platform companion
16
- and the two-step npm install/desktop launch guide. Windows and the AlmaLinux8
17
- GLIBC2.28 X11 baseline have live test evidence; macOS ships as experimental and
18
- not runtime verified. Native Wayland is unsupported. No new art license or Codex
19
- modification is part of this release. Preserve all earlier registry artifacts.
15
+ The owner explicitly authorized GitHub push and npm publication of the reviewed
16
+ comfort extension and runtime optimizations on2026-10-23. Version0.0.4 removes
17
+ unused Three.js runtime work, retains only reachable interaction samples, and
18
+ adds belly-up/sleep behavior plus a tiny tug sprite family. Code/art licenses stay
19
+ MIT/CC BY-SA4.0, including the new covered archive. No Codex modification is made.
20
+ Windows live, installed-consumer and browser checks cover this release. Linux
21
+ retains the earlier AlmaLinux8/GLIBC2.28 X11 adapter baseline; new controls have
22
+ grammar/protocol checks, not a new Linux GUI test. macOS remains experimental.
23
+ Native Wayland is unsupported. Preserve all earlier registry artifacts.
20
24
 
21
25
  `release-policy.json` has four independent approval gates and the CC artwork
22
26
  license identifier. The guard still refuses false/missing approvals, private
@@ -38,10 +42,16 @@ interactions, lifecycle, examples, JSONL and isolated installer settings.
38
42
  Its report is in a fresh `dist/package-check-*/package-check.json`; it does not publish or edit live
39
43
  agent configuration. Keep the final tarball hash and file inventory.
40
44
 
41
- The product workspace is not a Git repository. No public source repository,
42
- Actions pipeline or npm trusted publisher is implied by this npm release.
43
- Do not upload this experimental workspace wholesale: original photos, source
44
- image sheets, workers, QA receipts, credentials and local settings stay local.
45
+ The original art playground was not a Git repository. The owner separately
46
+ authorized a curated public source tree at BiteFoundry/retrieviewer and its
47
+ GitHub Pages workflow. This is not an upload of the experimental workspace:
48
+ original photos, source image sheets, workers, QA receipts, credentials and local
49
+ settings remain local. See SOURCE-SCOPE.md. There is no npm trusted publisher or
50
+ automatic npm release workflow; the site workflow deploys the site only.
51
+
52
+ Immutable npm0.0.3 was already published and verified. Do not republish different
53
+ bytes as0.0.3. This release uses0.0.4 with fresh authorization, version/lock/test/
54
+ policy updates, exact-tarball checks and registry-install verification.
45
55
 
46
56
  ## Publish the tested tarball
47
57
 
@@ -58,7 +68,8 @@ https://docs.npmjs.com/trusted-publishers/
58
68
 
59
69
  ## Support boundaries
60
70
 
61
- The default Q5 art and runtime are unchanged by this release. The OpenCode
71
+ The approved existing Q5 frames are unchanged; the new tiny tug family uses the
72
+ same32-level pipeline. Belly/sleep reuse existing source frames. The OpenCode
62
73
  2.1.2 Windows directory-based adapter has local host proof; npm `./tui`
63
74
  discovery alone is not live-host certification. Other agent-native renderers
64
75
  remain unimplemented. MCP alone cannot inject a pet into arbitrary agent UIs.
@@ -1,11 +1,13 @@
1
1
  # Third-party notices
2
2
 
3
3
  - **procedural-animals 0.1.0** — MIT, Copyright (c) 2026 Majid Manzarpour and
4
- procedural-animals contributors. Source is vendored under
5
- `vendor/procedural-animals/src`; the full notice is retained at
4
+ procedural-animals contributors. The original development source is retained
5
+ under `vendor/procedural-animals/src` for motion parity tests; it is no longer
6
+ executed or shipped in the dot-art runtime. The full notice is retained at
6
7
  `vendor/procedural-animals/LICENSE`.
7
8
  Upstream: https://github.com/majidmanzarpour/threejs-procedural-animals
8
- - **three 0.186.1** — MIT; installed as a pinned npm dependency. Its distribution
9
+ - **three 0.186.1** — MIT; development-only dependency for original 3D parity
10
+ tests. Not installed by the production package. Its development distribution
9
11
  includes its own `LICENSE`. https://github.com/mrdoob/three.js
10
12
  - **jsonc-parser 3.3.1** — MIT; installed as a pinned npm dependency. Its
11
13
  distribution includes `LICENSE.md`. https://github.com/microsoft/node-jsonc-parser
package/braille.mjs CHANGED
@@ -2,23 +2,49 @@
2
2
  export const BRAILLE_BITS=[[1,8],[2,16],[4,32],[64,128]];
3
3
  const BAYER=[[0,8,2,10],[12,4,14,6],[3,11,1,9],[15,7,13,5]];
4
4
  const clamp=v=>Math.max(0,Math.min(1,v));
5
+ const GLYPHS=Array.from({length:256},(_,i)=>String.fromCharCode(0x2800+i));
6
+ let grayTable=null,grayBrightness=0,grayContrast=0;
7
+ function stableBraille(rgba,width,height,brightness,contrast){
8
+ if(grayBrightness!==brightness||grayContrast!==contrast){
9
+ grayTable=Float32Array.from({length:256},(_,v)=>{
10
+ const luma=(.2126*v+.7152*v+.0722*v)/255;
11
+ return luma===0?0:clamp((Math.pow(luma,.9)*brightness-.5)*contrast+.5);
12
+ });
13
+ grayBrightness=brightness;grayContrast=contrast;
14
+ }
15
+ const table=grayTable,bytePixels=rgba instanceof Uint8Array||rgba instanceof Uint8ClampedArray,columns=Math.ceil(width/2),rows=Math.ceil(height/4),masks=new Uint8Array(columns*rows);
16
+ let dots=0;
17
+ // Stable dithering has no error diffusion: background pixels cannot affect a
18
+ // neighbor. Skip them before luma/hash work, and write straight to cell masks.
19
+ // Float32 rounding matches the original intermediate values array exactly.
20
+ for(let y=0;y<height;y++)for(let x=0,p=y*width*4;x<width;x++,p+=4){
21
+ const r=rgba[p],g=rgba[p+1],b=rgba[p+2],a=rgba[p+3];
22
+ if(a===0||(r===0&&g===0&&b===0))continue;
23
+ let value;
24
+ if(bytePixels&&a===255&&r===g&&g===b)value=table[r];
25
+ else{
26
+ const luma=(.2126*r+.7152*g+.0722*b)/255*(a/255);
27
+ value=Math.fround(luma===0?0:clamp((Math.pow(luma,.9)*brightness-.5)*contrast+.5));
28
+ }
29
+ if(value<=0)continue;
30
+ let n=Math.imul(x+1,0x1f123bb5)^Math.imul(y+1,0x5f356495);
31
+ n=Math.imul(n^(n>>>16),0x45d9f3b);n=Math.imul(n^(n>>>16),0x45d9f3b);n=(n^(n>>>16))>>>0;
32
+ if(value>(n+.5)/4294967296){masks[(y>>2)*columns+(x>>1)]|=BRAILLE_BITS[y&3][x&1];dots++;}
33
+ }
34
+ const lines=[];
35
+ for(let y=0;y<rows;y++){let line='';for(let x=0;x<columns;x++)line+=GLYPHS[masks[y*columns+x]];lines.push(line);}
36
+ return{text:lines.join('\n'),columns,rows,dots};
37
+ }
5
38
  export function rgbaToBraille(rgba,width,height,{brightness=1,contrast=1,method='floyd'}={}){
6
39
  if(!Number.isInteger(width)||!Number.isInteger(height)||width<1||height<1||width*height>1_000_000||rgba.length!==width*height*4)throw Error('Invalid RGBA image');
7
40
  if(!Number.isFinite(brightness)||brightness<=0||brightness>4||!Number.isFinite(contrast)||contrast<=0||contrast>4||!['floyd','bayer','stable'].includes(method))throw Error('Invalid dithering options');
41
+ if(method==='stable')return stableBraille(rgba,width,height,brightness,contrast);
8
42
  const values=new Float32Array(width*height),bits=new Uint8Array(width*height);
9
43
  for(let i=0;i<values.length;i++){
10
44
  const p=i*4,luma=(.2126*rgba[p]+.7152*rgba[p+1]+.0722*rgba[p+2])/255*(rgba[p+3]/255);
11
45
  values[i]=luma===0?0:clamp((Math.pow(luma,.9)*brightness-.5)*contrast+.5);
12
46
  }
13
- if(method==='stable'){
14
- // Fixed per-pixel threshold, not fresh random noise on every animation tick.
15
- // Unlike the 4x4 Bayer matrix this avoids a repeating cross-hatch on fur.
16
- for(let y=0;y<height;y++)for(let x=0;x<width;x++){
17
- let n=Math.imul(x+1,0x1f123bb5)^Math.imul(y+1,0x5f356495);
18
- n=Math.imul(n^(n>>>16),0x45d9f3b);n=Math.imul(n^(n>>>16),0x45d9f3b);n=(n^(n>>>16))>>>0;
19
- bits[y*width+x]=values[y*width+x]>(n+.5)/4294967296?1:0;
20
- }
21
- }else if(method==='bayer'){
47
+ if(method==='bayer'){
22
48
  for(let y=0;y<height;y++)for(let x=0;x<width;x++)bits[y*width+x]=values[y*width+x]>(BAYER[y%4][x%4]+.5)/16?1:0;
23
49
  }else{
24
50
  const add=(x,y,error,weight)=>{if(x>=0&&x<width&&y<height)values[y*width+x]+=error*weight/16;};
package/examples/live.mjs CHANGED
@@ -13,7 +13,7 @@ if(!out.isTTY||!input.isTTY){
13
13
  const data=bytes=>{for(const c of bytes.toString()){
14
14
  if(c==='q'||c==='\x03')stop();
15
15
  if(c===' ')paused=!paused;
16
- if(c==='b'||c==='t'){if(pet.interact(c==='b'?'ball':'treat'))paused=false;}
16
+ if(c==='b'||c==='t'||c==='g'){if(pet.interact(c==='b'?'ball':c==='t'?'treat':'tug'))paused=false;}
17
17
  }};
18
18
  process.on('SIGINT',stop);process.on('SIGTERM',stop);
19
19
  input.setRawMode(true);input.resume();input.on('data',data);
@@ -28,7 +28,7 @@ if(!out.isTTY||!input.isTTY){
28
28
  const frame=pet.frame({columns,rows}),lines=frame.text.split('\n');let batch='';
29
29
  for(let y=0;y<rows;y++)if(lines[y]!==previous[y])batch+=`\x1b[${y+1};1H${lines[y]}`;
30
30
  previous=lines;
31
- const status=`${paused?'Paused':frame.report.intent} | B ball T treat Space pause Q quit`.slice(0,columns);
31
+ const status=`${paused?'Paused':frame.report.intent} | B ball T treat G tug Space pause Q quit`.slice(0,columns);
32
32
  batch+=`\x1b[${rows+1};1H\x1b[2K${status}`;
33
33
  if(!out.write(batch))await once(out,'drain');
34
34
  await new Promise(resolve=>setTimeout(resolve,Math.max(1,1000/30-(performance.now()-start))));
@@ -213,7 +213,7 @@ class Companion(object):
213
213
  def press(self, name):
214
214
  if self.quitting:
215
215
  return
216
- if name in ('ball', 'treat'):
216
+ if name in ('ball', 'treat', 'tug'):
217
217
  if self.loaded and not self.paused:
218
218
  self.emit({'type': 'interact', 'kind': name})
219
219
  elif name == 'pause':
@@ -460,7 +460,7 @@ def ascii_label(text, limit):
460
460
 
461
461
  class XDisplay(object):
462
462
  """Owned X11 resources: one ARGB pet window, one control strip, one picker."""
463
- BAR_BUTTONS = (('ball', 'Ball'), ('treat', 'Treat'), ('window', 'Window'), ('pause', 'Pause'), ('quit', 'Quit'))
463
+ BAR_BUTTONS = (('ball', 'Ball'), ('treat', 'Treat'), ('tug', 'Tug'), ('window', 'Window'), ('pause', 'Pause'), ('quit', 'Quit'))
464
464
 
465
465
  def __init__(self, display_name=None, require_compositor=True, x=None):
466
466
  self.x = x or load_libraries()
@@ -265,7 +265,7 @@ var STYLE_BORDERLESS = 0, STYLE_TITLED = 1, STYLE_CLOSABLE = 2, STYLE_NONACTIVAT
265
265
  var BACKING_BUFFERED = 2, FLOATING_LEVEL = 3, ACTIVATION_ACCESSORY = 1, ANIMATION_NONE = 2;
266
266
  // canJoinAllSpaces | stationary | ignoresCycle | fullScreenAuxiliary
267
267
  var OVERLAY_SPACES = 1 | 16 | 64 | 256;
268
- var BAR_WIDTH = 354, BAR_HEIGHT = 40;
268
+ var BAR_WIDTH = 404, BAR_HEIGHT = 40;
269
269
 
270
270
  var shell = null;
271
271
 
@@ -379,7 +379,7 @@ function registerClasses() {
379
379
  name: 'RetrieviewerController', superclass: 'NSObject',
380
380
  methods: {
381
381
  'onInput:': guarded('onInput'), 'onTick:': guarded('onTick'),
382
- 'onBall:': guarded('onBall'), 'onTreat:': guarded('onTreat'), 'onPick:': guarded('onPick'),
382
+ 'onBall:': guarded('onBall'), 'onTreat:': guarded('onTreat'), 'onTug:': guarded('onTug'), 'onPick:': guarded('onPick'),
383
383
  'onPause:': guarded('onPause'), 'onQuit:': guarded('onQuit'),
384
384
  'onRefresh:': guarded('onRefresh'), 'onAttach:': guarded('onAttach'), 'onCancel:': guarded('onCancel'),
385
385
  'windowWillClose:': guarded('onWindowWillClose')
@@ -412,10 +412,11 @@ function startCompanion(testMode) {
412
412
  ballButton = makeButton('\uACF5', { x: 8, y: 6, width: 40, height: 28 }, 'onBall:');
413
413
  content.addSubview(ballButton);
414
414
  content.addSubview(makeButton('\uAC04\uC2DD', { x: 52, y: 6, width: 46, height: 28 }, 'onTreat:'));
415
- content.addSubview(makeButton('\uCC3D', { x: 102, y: 6, width: 40, height: 28 }, 'onPick:'));
416
- content.addSubview(makeButton('\uC27C', { x: 146, y: 6, width: 40, height: 28 }, 'onPause:'));
417
- content.addSubview(makeButton('\uC885\uB8CC', { x: 190, y: 6, width: 46, height: 28 }, 'onQuit:'));
418
- statusLabel = makeLabel(TEXT.preparing, { x: 242, y: 10, width: 108, height: 20 }, $.NSColor.whiteColor);
415
+ content.addSubview(makeButton('\uD130\uADF8', { x: 102, y: 6, width: 46, height: 28 }, 'onTug:'));
416
+ content.addSubview(makeButton('\uCC3D', { x: 152, y: 6, width: 40, height: 28 }, 'onPick:'));
417
+ content.addSubview(makeButton('\uC27C', { x: 196, y: 6, width: 40, height: 28 }, 'onPause:'));
418
+ content.addSubview(makeButton('\uC885\uB8CC', { x: 240, y: 6, width: 46, height: 28 }, 'onQuit:'));
419
+ statusLabel = makeLabel(TEXT.preparing, { x: 292, y: 10, width: 108, height: 20 }, $.NSColor.whiteColor);
419
420
  content.addSubview(statusLabel);
420
421
 
421
422
  // Menu bar item: the macOS counterpart of the Windows tray icon.
@@ -535,6 +536,7 @@ function startCompanion(testMode) {
535
536
  };
536
537
  shell.onBall = function () { core.interact('ball'); };
537
538
  shell.onTreat = function () { core.interact('treat'); };
539
+ shell.onTug = function () { core.interact('tug'); };
538
540
  shell.onPick = function () { choose(); };
539
541
  shell.onPause = function () { core.togglePause(); };
540
542
  shell.onQuit = function () { core.quit(); };
@@ -11,7 +11,7 @@ export const HEARTBEAT_MS=5000;
11
11
  // Bounded so the host prompt stays usable: at most 64x12 cells, hidden when the
12
12
  // terminal is too small for a legible pet.
13
13
  export const LIMITS=Object.freeze({maxColumns:64,maxRows:12,minColumns:20,minRows:5,sideMargin:4,reservedRows:14});
14
- export const COMMANDS=Object.freeze(['enable','disable','ball','treat','status']);
14
+ export const COMMANDS=Object.freeze(['enable','disable','ball','treat','tug','status']);
15
15
 
16
16
  const fn=(value,name)=>{if(typeof value!=='function')throw TypeError(`${name} must be a function`);};
17
17
  const defaultScheduler=()=>({now:()=>performance.now(),schedule:(callback,delayMs)=>setTimeout(callback,delayMs),cancel:handle=>clearTimeout(handle)});
@@ -133,7 +133,7 @@ export function createOpenCodePetController({hostVersion='unknown',scheduler,fps
133
133
  enabled=value;reconcile();
134
134
  }
135
135
  function interact(kind){
136
- if(kind!=='ball'&&kind!=='treat')throw TypeError("kind must be 'ball' or 'treat'");
136
+ if(!['ball','treat','tug'].includes(kind))throw TypeError("kind must be 'ball', 'treat' or 'tug'");
137
137
  return plugin?plugin.interact(kind):false;
138
138
  }
139
139
  function status(){
@@ -168,11 +168,11 @@ export function createOpenCodePetController({hostVersion='unknown',scheduler,fps
168
168
  setEnabled,
169
169
  interact,
170
170
  status,
171
- // Slash handler: '/retrieviewer <enable|disable|ball|treat|status>'.
171
+ // Slash handler: '/retrieviewer <enable|disable|ball|treat|tug|status>'.
172
172
  async command(argument){
173
173
  const word=String(argument??'').trim().toLowerCase()||'status';
174
174
  if(word==='enable'||word==='disable'){await setEnabled(word==='enable');return word==='enable'?'Retrieviewer enabled':'Retrieviewer disabled';}
175
- if(word==='ball'||word==='treat'){
175
+ if(word==='ball'||word==='treat'||word==='tug'){
176
176
  if(!plugin)return enabled?'Retrieviewer is still loading':'Retrieviewer is disabled; run /retrieviewer enable';
177
177
  return interact(word)?`Retrieviewer: ${word} accepted`:`Retrieviewer is busy; ${word} not accepted`;
178
178
  }
@@ -43,7 +43,7 @@ export default Plugin.define({
43
43
  commands:[{
44
44
  id:'retrieviewer.pet',
45
45
  title:'Retrieviewer pet',
46
- description:'enable | disable | ball | treat | status',
46
+ description:'enable | disable | ball | treat | tug | status',
47
47
  group:'Retrieviewer',
48
48
  palette:true,
49
49
  slash:{name:'retrieviewer',arguments:true},
@@ -111,10 +111,10 @@ sealed class Companion : ApplicationContext {
111
111
  TargetItem target;Form pickerWindow;QuietWindow testTarget;readonly bool testMode;Rectangle canvas;int revision=0,cell=8;bool visible=false,paused=false,loaded=false,quitting=false,picking=false,announced=false;
112
112
  Label status=new Label();Mutex mutex;
113
113
  internal Companion(Mutex single,bool diagnostic){
114
- mutex=single;testMode=diagnostic;bar.Text="Retrieviewer controls";bar.Size=new Size(354,40);bar.BackColor=Color.FromArgb(28,30,34);bar.ForeColor=Color.White;
114
+ mutex=single;testMode=diagnostic;bar.Text="Retrieviewer controls";bar.Size=new Size(404,40);bar.BackColor=Color.FromArgb(28,30,34);bar.ForeColor=Color.White;
115
115
  bar.Font=new Font("Segoe UI",9);bar.Controls.Add(MakeButton("공",8,()=>Interact("ball")));bar.Controls.Add(MakeButton("간식",52,()=>Interact("treat")));
116
- bar.Controls.Add(MakeButton("창",102,ChooseTarget));bar.Controls.Add(MakeButton("쉼",146,TogglePause));bar.Controls.Add(MakeButton("종료",190,Quit));
117
- status.AutoSize=false;status.Location=new Point(240,12);status.Size=new Size(110,22);status.Text="준비 중";bar.Controls.Add(status);
116
+ bar.Controls.Add(MakeButton("터그",102,()=>Interact("tug")));bar.Controls.Add(MakeButton("창",152,ChooseTarget));bar.Controls.Add(MakeButton("쉼",196,TogglePause));bar.Controls.Add(MakeButton("종료",240,Quit));
117
+ status.AutoSize=false;status.Location=new Point(290,12);status.Size=new Size(110,22);status.Text="준비 중";bar.Controls.Add(status);
118
118
  ContextMenuStrip menu=new ContextMenuStrip();menu.Items.Add("다른 창 선택",null,(s,e)=>ChooseTarget());menu.Items.Add("숨기기 / 다시 표시",null,(s,e)=>TogglePause());menu.Items.Add("종료",null,(s,e)=>Quit());
119
119
  tray.Icon=SystemIcons.Application;tray.Text="Retrieviewer · 창 선택";tray.ContextMenuStrip=menu;tray.Visible=true;tray.DoubleClick+=(s,e)=>ChooseTarget();
120
120
  // Handles are created on the UI thread before the reader can signal EOF.
@@ -127,7 +127,7 @@ sealed class Companion : ApplicationContext {
127
127
  }
128
128
  }
129
129
  Button MakeButton(string title,int x,Action action){
130
- Button b=new Button();b.Text=title;b.TabStop=false;b.Size=new Size(title=="간식"?46:40,28);b.Location=new Point(x,6);b.FlatStyle=FlatStyle.Flat;b.FlatAppearance.BorderSize=0;b.BackColor=Color.FromArgb(48,51,58);b.ForeColor=Color.White;b.Click+=(s,e)=>action();return b;
130
+ Button b=new Button();b.Text=title;b.TabStop=false;b.Size=new Size(title=="간식"||title=="터그"?46:40,28);b.Location=new Point(x,6);b.FlatStyle=FlatStyle.Flat;b.FlatAppearance.BorderSize=0;b.BackColor=Color.FromArgb(48,51,58);b.ForeColor=Color.White;b.Click+=(s,e)=>action();return b;
131
131
  }
132
132
  void ReadInput(){
133
133
  try{
@@ -20,20 +20,24 @@ export function cropFrame(frame,revision){
20
20
 
21
21
  // Request/ack rendering: never queue obsolete frames behind a slow native painter.
22
22
  export function createFramePump({pet,send,now=()=>performance.now()}){
23
- let viewport=null,inFlight=false,last=null,revision=0,paused=false,disposed=false;
23
+ let viewport=null,inFlight=false,last=null,lastFrame=null,revision=0,paused=false,disposed=false;
24
24
  const alive=()=>{if(disposed)throw Error('Overlay pump is disposed');};
25
25
  return {
26
- viewport(message){alive();const next=viewportOf(message);revision=message.revision;viewport=next;last=null;},
27
- pause(value){alive();paused=!!value;last=null;},
26
+ viewport(message){alive();const next=viewportOf(message);revision=message.revision;viewport=next;last=null;lastFrame=null;},
27
+ pause(value){alive();paused=!!value;last=null;lastFrame=null;},
28
28
  ack(){alive();inFlight=false;},
29
29
  tick(){
30
30
  alive();if(inFlight||!viewport||paused)return false;
31
31
  const t=now(),dt=last===null?0:Math.max(0,(t-last)/1000);last=t;
32
- pet.step(dt);const frame=pet.frame(viewport);inFlight=true;
33
- try{send(cropFrame(frame,revision));}catch(error){inFlight=false;throw error;}return true;
32
+ pet.step(dt);const frame=cropFrame(pet.frame(viewport),revision);
33
+ // A held seat/down pose can be byte-identical for seconds. Advance the life
34
+ // clock normally but avoid JSON, IPC, bitmap allocation and native repaint.
35
+ if(lastFrame&&frame.x===lastFrame.x&&frame.y===lastFrame.y&&frame.columns===lastFrame.columns&&frame.rows===lastFrame.rows&&frame.text===lastFrame.text)return false;
36
+ inFlight=true;
37
+ try{send(frame);lastFrame=frame;}catch(error){inFlight=false;throw error;}return true;
34
38
  },
35
- interact(kind){alive();if(!['ball','treat'].includes(kind))throw Error('Invalid overlay interaction');return pet.interact(kind);},
39
+ interact(kind){alive();if(!['ball','treat','tug'].includes(kind))throw Error('Invalid overlay interaction');const accepted=pet.interact(kind);if(accepted)lastFrame=null;return accepted;},
36
40
  get hidden(){return !viewport||paused;},
37
- dispose(){if(!disposed){disposed=true;viewport=null;pet.dispose();}},
41
+ dispose(){if(!disposed){disposed=true;viewport=lastFrame=null;pet.dispose();}},
38
42
  };
39
43
  }
package/package.json CHANGED
@@ -1,10 +1,28 @@
1
1
  {
2
2
  "name": "@bitefoundry/retrieviewer",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "A fluffy Braille desktop pet for Windows and Linux X11, with experimental macOS support and an embeddable TUI engine.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
- "homepage": "https://github.com/BiteFoundry",
7
- "keywords": ["tui", "braille", "pet", "retriever", "opencode", "desktop-pet", "windows", "linux", "macos", "overlay"],
6
+ "homepage": "https://bitefoundry.github.io/retrieviewer/",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/BiteFoundry/retrieviewer.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/BiteFoundry/retrieviewer/issues"
13
+ },
14
+ "keywords": [
15
+ "tui",
16
+ "braille",
17
+ "pet",
18
+ "retriever",
19
+ "opencode",
20
+ "desktop-pet",
21
+ "windows",
22
+ "linux",
23
+ "macos",
24
+ "overlay"
25
+ ],
8
26
  "publishConfig": {
9
27
  "access": "public",
10
28
  "registry": "https://registry.npmjs.org/",
@@ -64,16 +82,17 @@
64
82
  "DESKTOP-PLATFORMS.md",
65
83
  "WINDOWS-COMPANION.md",
66
84
  "INSTALLING.md",
85
+ "PREREQUISITES.md",
86
+ "README.ko.md",
67
87
  "PLUGIN.md",
68
88
  "EMBEDDING.md",
69
89
  "PUPPY-MEMORY.md",
70
90
  "PUPPY-Q5-COMPARISON.md",
91
+ "COMFORT-ART.md",
71
92
  "examples/embed.mjs",
72
93
  "examples/live.mjs",
73
94
  "examples/plugin.mjs",
74
95
  "examples/bridge.py",
75
- "locomotion-core.mjs",
76
- "locomotion-puppy.animal",
77
96
  "braille.mjs",
78
97
  "puppy-frame-store.mjs",
79
98
  "puppy-frame-predictive.mjs",
@@ -91,6 +110,7 @@
91
110
  "puppy-companion-life.mjs",
92
111
  "puppy-companion-objects.mjs",
93
112
  "puppy-companion-sprites.mjs",
113
+ "puppy-comfort-sprites.mjs",
94
114
  "puppy-mouth-anchor.mjs",
95
115
  "puppy-mouth-anchor.json",
96
116
  "puppy-clean.mjs",
@@ -116,24 +136,25 @@
116
136
  "puppy-paper-actions-v9.json",
117
137
  "puppy-companion-interactions-v3-q5.bin.gz",
118
138
  "puppy-companion-interactions-v3.json",
119
- "vendor/procedural-animals/src",
120
- "vendor/procedural-animals/LICENSE",
121
- "vendor/procedural-animals/package.json"
139
+ "puppy-companion-comfort-q5.bin.gz",
140
+ "puppy-companion-comfort.json",
141
+ "vendor/procedural-animals/LICENSE"
122
142
  ],
123
143
  "scripts": {
124
- "start": "node server.mjs",
125
- "terminal": "node terminal.mjs",
126
- "pet": "node puppy-terminal.mjs",
144
+ "start": "node tools/preview-site.mjs",
145
+ "build:site": "node tools/build-site.mjs",
127
146
  "pet:companion": "node examples/live.mjs",
128
147
  "pet:desktop": "node retrieviewer-cli.mjs desktop",
129
148
  "test": "node --test \"*.test.mjs\"",
130
- "test:locomotion": "node check-locomotion.mjs",
131
149
  "test:package": "node check-pet-package.mjs",
132
150
  "release:check": "node tools/check-release.mjs",
133
151
  "prepublishOnly": "npm run release:check"
134
152
  },
135
153
  "dependencies": {
136
- "jsonc-parser": "3.3.1",
154
+ "jsonc-parser": "3.3.1"
155
+ },
156
+ "devDependencies": {
157
+ "playwright": "1.64.1",
137
158
  "three": "0.186.1"
138
159
  }
139
160
  }