vibejourney 0.2.0 → 0.3.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/README.md +63 -0
- package/README.zh-CN.md +63 -0
- package/dist/index.js +297 -19
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -70,6 +70,69 @@ When you open VibeJourney, you'll see what your buddy did while you were coding:
|
|
|
70
70
|
- **Narrative journal** — travel stories based on terrain, weather, and buddy personality
|
|
71
71
|
- **Offline support** — GeoJSON map cached locally after first download
|
|
72
72
|
|
|
73
|
+
## Cities, Landmarks & Souvenirs
|
|
74
|
+
|
|
75
|
+
29 cities, 116 landmarks, 58 souvenirs. Your buddy picks the order. You just write code.
|
|
76
|
+
|
|
77
|
+
### 🌏 Asia (8)
|
|
78
|
+
|
|
79
|
+
| City | Landmarks | Souvenirs |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| Beijing | the Great Wall · the Forbidden City · Tiananmen Square · the Temple of Heaven | 🧧 jade bracelet · 🪭 silk fan |
|
|
82
|
+
| Tokyo | Shibuya Crossing · Tokyo Tower · Senso-ji Temple · Mount Fuji in the distance | 🍣 sushi set · 🌸 sakura bookmark |
|
|
83
|
+
| Seoul | Gyeongbokgung Palace · Bukchon Hanok Village · Namsan Tower · street food in Myeongdong | 🍵 ceramic teacup · 🎵 K-pop album |
|
|
84
|
+
| Hong Kong | Victoria Peak · the Star Ferry · Temple Street Night Market · neon signs reflecting in puddles | 🥮 egg tart box · 💎 jade pendant |
|
|
85
|
+
| Bangkok | the Grand Palace · Wat Arun at sunset · floating markets · tuk-tuks weaving through traffic | 🙏 golden Buddha charm · 🌶️ spicy sauce set |
|
|
86
|
+
| Singapore | Marina Bay Sands · Gardens by the Bay · the Merlion · hawker stalls on every corner | 🌺 orchid pin · 🦁 Merlion figurine |
|
|
87
|
+
| Mumbai | the Gateway of India · Marine Drive at night · Dharavi's colorful streets · Bollywood billboards everywhere | ☕ chai spice blend · 🧣 silk scarf |
|
|
88
|
+
| Dubai | the Burj Khalifa · the Palm Jumeirah · the Dubai Mall · desert dunes at sunset | 🌴 golden dates box · 🧴 oud perfume |
|
|
89
|
+
|
|
90
|
+
### 🌍 Europe (9)
|
|
91
|
+
|
|
92
|
+
| City | Landmarks | Souvenirs |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| Istanbul | the Hagia Sophia · the Grand Bazaar · the Bosphorus at dawn · a cup of Turkish tea | 🍬 Turkish delight box · 🧿 evil eye charm |
|
|
95
|
+
| Moscow | Red Square · St. Basil's Cathedral · the Kremlin walls · the Moscow Metro | 🪆 matryoshka doll · 💍 amber ring |
|
|
96
|
+
| Prague | Charles Bridge · Prague Castle · the Astronomical Clock · a quiet beer garden | 🥂 crystal glass · 🎭 marionette puppet |
|
|
97
|
+
| Berlin | the Brandenburg Gate · remnants of the Berlin Wall · Museum Island · currywurst from a street stand | 🧱 Wall fragment · 🥨 pretzel magnet |
|
|
98
|
+
| Amsterdam | canals lined with bicycles · the Rijksmuseum · Anne Frank House · tulips at a flower market | 🌷 tulip bulb set · 🏠 Delft tile |
|
|
99
|
+
| London | Big Ben · Tower Bridge · the British Museum · a red phone booth | 🫖 Earl Grey tea tin · 🚌 red bus model |
|
|
100
|
+
| Paris | the Eiffel Tower · the Louvre · Montmartre at sunset · a fresh croissant | 🗼 tiny Eiffel Tower · 🧁 macaron box |
|
|
101
|
+
| Barcelona | the Sagrada Familia · Park Guell · La Rambla · tapas at a tiny bar | 🎨 Gaudi mosaic tile · 🍷 sangria mix |
|
|
102
|
+
| Rome | the Colosseum · the Trevi Fountain · the Vatican · gelato on the Spanish Steps | 🏛️ Colosseum snow globe · 🫒 truffle oil bottle |
|
|
103
|
+
|
|
104
|
+
### 🌍 Africa (4)
|
|
105
|
+
|
|
106
|
+
| City | Landmarks | Souvenirs |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| Cairo | the Pyramids of Giza · the Sphinx · the Nile at dusk · Khan el-Khalili bazaar | 🏺 miniature pyramid · 📜 papyrus scroll |
|
|
109
|
+
| Nairobi | Nairobi National Park · giraffes walking past the skyline · the Karen Blixen Museum · Kenyan coffee at a local cafe | ☕ Kenyan coffee beans · 📿 Maasai beads |
|
|
110
|
+
| Marrakech | Jemaa el-Fnaa square · the Majorelle Garden · the Medina's winding alleys · mint tea on a rooftop | 🫒 argan oil bottle · 🧶 Berber rug swatch |
|
|
111
|
+
| Cape Town | Table Mountain · the Cape of Good Hope · penguins at Boulders Beach · vineyards stretching to the hills | 🫖 rooibos tea tin · 🐧 penguin figure |
|
|
112
|
+
|
|
113
|
+
### 🌎 North America (4)
|
|
114
|
+
|
|
115
|
+
| City | Landmarks | Souvenirs |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| New York | the Statue of Liberty · Times Square · Central Park · a New York slice | ☕ I♥NY mug · 🪙 subway token |
|
|
118
|
+
| Los Angeles | the Hollywood sign · Santa Monica Pier · Venice Beach · palm trees lining the boulevard | ⭐ Hollywood star badge · 🕶️ sunglasses |
|
|
119
|
+
| San Francisco | the Golden Gate Bridge · Alcatraz Island · cable cars on steep hills · fog rolling over the bay | 🔔 cable car bell · 🍞 sourdough starter |
|
|
120
|
+
| Mexico City | the Zocalo · Frida Kahlo's Blue House · Chapultepec Castle · tacos al pastor from a street cart | 🪨 obsidian mirror · 🍫 hot chocolate mix |
|
|
121
|
+
|
|
122
|
+
### 🌎 South America (2)
|
|
123
|
+
|
|
124
|
+
| City | Landmarks | Souvenirs |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| Buenos Aires | La Boca's colorful houses · Plaza de Mayo · a tango show on the street · steak sizzling at a parrilla | 🧉 mate gourd · 💃 tango music box |
|
|
127
|
+
| Rio | Christ the Redeemer · Sugarloaf Mountain · Copacabana Beach · samba music in the streets | 🪇 samba shaker · 🫐 açaí bowl recipe |
|
|
128
|
+
|
|
129
|
+
### 🌏 Oceania (2)
|
|
130
|
+
|
|
131
|
+
| City | Landmarks | Souvenirs |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| Sydney | the Opera House · Harbour Bridge · Bondi Beach · the Blue Mountains | 🪃 boomerang keychain · 💠 opal stone |
|
|
134
|
+
| Auckland | the Sky Tower · Rangitoto Island · sailing boats in the harbour · a hangi feast | 🟢 pounamu pendant · 🥝 kiwi plush |
|
|
135
|
+
|
|
73
136
|
## Commands
|
|
74
137
|
|
|
75
138
|
```bash
|
package/README.zh-CN.md
CHANGED
|
@@ -70,6 +70,69 @@ buddy 自己选目的地(你不控制它去哪)。它优先去没去过的
|
|
|
70
70
|
- **叙事日志** — 基于地形、天气和 buddy 性格的旅行故事
|
|
71
71
|
- **离线支持** — 首次下载后地图本地缓存
|
|
72
72
|
|
|
73
|
+
## 城市、地标与特产
|
|
74
|
+
|
|
75
|
+
29 座城市,116 个地标,58 件特产。buddy 自己挑顺序,你只管写代码。
|
|
76
|
+
|
|
77
|
+
### 🌏 亚洲 (8)
|
|
78
|
+
|
|
79
|
+
| 城市 | 地标 | 特产 |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| Beijing | the Great Wall · the Forbidden City · Tiananmen Square · the Temple of Heaven | 🧧 jade bracelet · 🪭 silk fan |
|
|
82
|
+
| Tokyo | Shibuya Crossing · Tokyo Tower · Senso-ji Temple · Mount Fuji in the distance | 🍣 sushi set · 🌸 sakura bookmark |
|
|
83
|
+
| Seoul | Gyeongbokgung Palace · Bukchon Hanok Village · Namsan Tower · street food in Myeongdong | 🍵 ceramic teacup · 🎵 K-pop album |
|
|
84
|
+
| Hong Kong | Victoria Peak · the Star Ferry · Temple Street Night Market · neon signs reflecting in puddles | 🥮 egg tart box · 💎 jade pendant |
|
|
85
|
+
| Bangkok | the Grand Palace · Wat Arun at sunset · floating markets · tuk-tuks weaving through traffic | 🙏 golden Buddha charm · 🌶️ spicy sauce set |
|
|
86
|
+
| Singapore | Marina Bay Sands · Gardens by the Bay · the Merlion · hawker stalls on every corner | 🌺 orchid pin · 🦁 Merlion figurine |
|
|
87
|
+
| Mumbai | the Gateway of India · Marine Drive at night · Dharavi's colorful streets · Bollywood billboards everywhere | ☕ chai spice blend · 🧣 silk scarf |
|
|
88
|
+
| Dubai | the Burj Khalifa · the Palm Jumeirah · the Dubai Mall · desert dunes at sunset | 🌴 golden dates box · 🧴 oud perfume |
|
|
89
|
+
|
|
90
|
+
### 🌍 欧洲 (9)
|
|
91
|
+
|
|
92
|
+
| 城市 | 地标 | 特产 |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| Istanbul | the Hagia Sophia · the Grand Bazaar · the Bosphorus at dawn · a cup of Turkish tea | 🍬 Turkish delight box · 🧿 evil eye charm |
|
|
95
|
+
| Moscow | Red Square · St. Basil's Cathedral · the Kremlin walls · the Moscow Metro | 🪆 matryoshka doll · 💍 amber ring |
|
|
96
|
+
| Prague | Charles Bridge · Prague Castle · the Astronomical Clock · a quiet beer garden | 🥂 crystal glass · 🎭 marionette puppet |
|
|
97
|
+
| Berlin | the Brandenburg Gate · remnants of the Berlin Wall · Museum Island · currywurst from a street stand | 🧱 Wall fragment · 🥨 pretzel magnet |
|
|
98
|
+
| Amsterdam | canals lined with bicycles · the Rijksmuseum · Anne Frank House · tulips at a flower market | 🌷 tulip bulb set · 🏠 Delft tile |
|
|
99
|
+
| London | Big Ben · Tower Bridge · the British Museum · a red phone booth | 🫖 Earl Grey tea tin · 🚌 red bus model |
|
|
100
|
+
| Paris | the Eiffel Tower · the Louvre · Montmartre at sunset · a fresh croissant | 🗼 tiny Eiffel Tower · 🧁 macaron box |
|
|
101
|
+
| Barcelona | the Sagrada Familia · Park Guell · La Rambla · tapas at a tiny bar | 🎨 Gaudi mosaic tile · 🍷 sangria mix |
|
|
102
|
+
| Rome | the Colosseum · the Trevi Fountain · the Vatican · gelato on the Spanish Steps | 🏛️ Colosseum snow globe · 🫒 truffle oil bottle |
|
|
103
|
+
|
|
104
|
+
### 🌍 非洲 (4)
|
|
105
|
+
|
|
106
|
+
| 城市 | 地标 | 特产 |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| Cairo | the Pyramids of Giza · the Sphinx · the Nile at dusk · Khan el-Khalili bazaar | 🏺 miniature pyramid · 📜 papyrus scroll |
|
|
109
|
+
| Nairobi | Nairobi National Park · giraffes walking past the skyline · the Karen Blixen Museum · Kenyan coffee at a local cafe | ☕ Kenyan coffee beans · 📿 Maasai beads |
|
|
110
|
+
| Marrakech | Jemaa el-Fnaa square · the Majorelle Garden · the Medina's winding alleys · mint tea on a rooftop | 🫒 argan oil bottle · 🧶 Berber rug swatch |
|
|
111
|
+
| Cape Town | Table Mountain · the Cape of Good Hope · penguins at Boulders Beach · vineyards stretching to the hills | 🫖 rooibos tea tin · 🐧 penguin figure |
|
|
112
|
+
|
|
113
|
+
### 🌎 北美洲 (4)
|
|
114
|
+
|
|
115
|
+
| 城市 | 地标 | 特产 |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| New York | the Statue of Liberty · Times Square · Central Park · a New York slice | ☕ I♥NY mug · 🪙 subway token |
|
|
118
|
+
| Los Angeles | the Hollywood sign · Santa Monica Pier · Venice Beach · palm trees lining the boulevard | ⭐ Hollywood star badge · 🕶️ sunglasses |
|
|
119
|
+
| San Francisco | the Golden Gate Bridge · Alcatraz Island · cable cars on steep hills · fog rolling over the bay | 🔔 cable car bell · 🍞 sourdough starter |
|
|
120
|
+
| Mexico City | the Zocalo · Frida Kahlo's Blue House · Chapultepec Castle · tacos al pastor from a street cart | 🪨 obsidian mirror · 🍫 hot chocolate mix |
|
|
121
|
+
|
|
122
|
+
### 🌎 南美洲 (2)
|
|
123
|
+
|
|
124
|
+
| 城市 | 地标 | 特产 |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| Buenos Aires | La Boca's colorful houses · Plaza de Mayo · a tango show on the street · steak sizzling at a parrilla | 🧉 mate gourd · 💃 tango music box |
|
|
127
|
+
| Rio | Christ the Redeemer · Sugarloaf Mountain · Copacabana Beach · samba music in the streets | 🪇 samba shaker · 🫐 açaí bowl recipe |
|
|
128
|
+
|
|
129
|
+
### 🌏 大洋洲 (2)
|
|
130
|
+
|
|
131
|
+
| 城市 | 地标 | 特产 |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| Sydney | the Opera House · Harbour Bridge · Bondi Beach · the Blue Mountains | 🪃 boomerang keychain · 💠 opal stone |
|
|
134
|
+
| Auckland | the Sky Tower · Rangitoto Island · sailing boats in the harbour · a hangi feast | 🟢 pounamu pendant · 🥝 kiwi plush |
|
|
135
|
+
|
|
73
136
|
## 命令
|
|
74
137
|
|
|
75
138
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,82 @@ var __export = (target, all) => {
|
|
|
30
30
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
31
31
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
32
32
|
|
|
33
|
+
// src/wyhash.ts
|
|
34
|
+
function mum(a, b) {
|
|
35
|
+
const x = a * b;
|
|
36
|
+
return { low: x & MASK64, high: x >> 64n & MASK64 };
|
|
37
|
+
}
|
|
38
|
+
function mix(a, b) {
|
|
39
|
+
const { low, high } = mum(a, b);
|
|
40
|
+
return (low ^ high) & MASK64;
|
|
41
|
+
}
|
|
42
|
+
function wyr8(p, i) {
|
|
43
|
+
return BigInt(p[i]) | BigInt(p[i + 1]) << 8n | BigInt(p[i + 2]) << 16n | BigInt(p[i + 3]) << 24n | BigInt(p[i + 4]) << 32n | BigInt(p[i + 5]) << 40n | BigInt(p[i + 6]) << 48n | BigInt(p[i + 7]) << 56n;
|
|
44
|
+
}
|
|
45
|
+
function wyr4(p, i) {
|
|
46
|
+
return BigInt(p[i]) | BigInt(p[i + 1]) << 8n | BigInt(p[i + 2]) << 16n | BigInt(p[i + 3]) << 24n;
|
|
47
|
+
}
|
|
48
|
+
function wyhash64(input, seedInit = 0n) {
|
|
49
|
+
const p = utf8.encode(input);
|
|
50
|
+
const len = p.length;
|
|
51
|
+
const s0 = (seedInit ^ mix((seedInit ^ SECRET[0]) & MASK64, SECRET[1])) & MASK64;
|
|
52
|
+
const state = [s0, s0, s0];
|
|
53
|
+
let a;
|
|
54
|
+
let b;
|
|
55
|
+
if (len <= 16) {
|
|
56
|
+
if (len >= 4) {
|
|
57
|
+
const end = len - 4;
|
|
58
|
+
const quarter = len >> 3 << 2;
|
|
59
|
+
a = (wyr4(p, 0) << 32n | wyr4(p, quarter)) & MASK64;
|
|
60
|
+
b = (wyr4(p, end) << 32n | wyr4(p, end - quarter)) & MASK64;
|
|
61
|
+
} else if (len > 0) {
|
|
62
|
+
a = BigInt(p[0]) << 16n | BigInt(p[len >> 1]) << 8n | BigInt(p[len - 1]);
|
|
63
|
+
b = 0n;
|
|
64
|
+
} else {
|
|
65
|
+
a = 0n;
|
|
66
|
+
b = 0n;
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
let i = 0;
|
|
70
|
+
if (len >= 48) {
|
|
71
|
+
while (i + 48 < len) {
|
|
72
|
+
for (let k = 0;k < 3; k++) {
|
|
73
|
+
const ra = wyr8(p, i + 16 * k);
|
|
74
|
+
const rb = wyr8(p, i + 16 * k + 8);
|
|
75
|
+
state[k] = mix((ra ^ SECRET[k + 1]) & MASK64, (rb ^ state[k]) & MASK64);
|
|
76
|
+
}
|
|
77
|
+
i += 48;
|
|
78
|
+
}
|
|
79
|
+
state[0] = (state[0] ^ state[1] ^ state[2]) & MASK64;
|
|
80
|
+
}
|
|
81
|
+
const remaining = len - i;
|
|
82
|
+
let j = 0;
|
|
83
|
+
while (j + 16 < remaining) {
|
|
84
|
+
const off = i + j;
|
|
85
|
+
state[0] = mix((wyr8(p, off) ^ SECRET[1]) & MASK64, (wyr8(p, off + 8) ^ state[0]) & MASK64);
|
|
86
|
+
j += 16;
|
|
87
|
+
}
|
|
88
|
+
a = wyr8(p, len - 16);
|
|
89
|
+
b = wyr8(p, len - 8);
|
|
90
|
+
}
|
|
91
|
+
a = (a ^ SECRET[1]) & MASK64;
|
|
92
|
+
b = (b ^ state[0]) & MASK64;
|
|
93
|
+
const { low, high } = mum(a, b);
|
|
94
|
+
a = low;
|
|
95
|
+
b = high;
|
|
96
|
+
return mix((a ^ SECRET[0] ^ BigInt(len)) & MASK64, (b ^ SECRET[1]) & MASK64);
|
|
97
|
+
}
|
|
98
|
+
var SECRET, MASK64 = 0xffffffffffffffffn, utf8;
|
|
99
|
+
var init_wyhash = __esm(() => {
|
|
100
|
+
SECRET = [
|
|
101
|
+
0xa0761d6478bd642fn,
|
|
102
|
+
0xe7037ed1a0b428dbn,
|
|
103
|
+
0x8ebc6af09c88c6e3n,
|
|
104
|
+
0x589965cc75374cc3n
|
|
105
|
+
];
|
|
106
|
+
utf8 = new TextEncoder;
|
|
107
|
+
});
|
|
108
|
+
|
|
33
109
|
// src/buddy.ts
|
|
34
110
|
import { readFileSync } from "fs";
|
|
35
111
|
import { homedir } from "os";
|
|
@@ -45,15 +121,8 @@ function mulberry32(seed) {
|
|
|
45
121
|
};
|
|
46
122
|
}
|
|
47
123
|
function hashString(s) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
let h = 2166136261;
|
|
52
|
-
for (let i = 0;i < s.length; i++) {
|
|
53
|
-
h ^= s.charCodeAt(i);
|
|
54
|
-
h = Math.imul(h, 16777619);
|
|
55
|
-
}
|
|
56
|
-
return h >>> 0;
|
|
124
|
+
const h = typeof Bun !== "undefined" ? BigInt(Bun.hash(s)) : wyhash64(s);
|
|
125
|
+
return Number(h & 0xffffffffn);
|
|
57
126
|
}
|
|
58
127
|
function pick(rng, arr) {
|
|
59
128
|
return arr[Math.floor(rng() * arr.length)];
|
|
@@ -133,6 +202,7 @@ function getLocalCompanion() {
|
|
|
133
202
|
}
|
|
134
203
|
var RARITIES, SPECIES, EYES, HATS, STAT_NAMES, RARITY_WEIGHTS, BODIES, HAT_LINES, RARITY_FLOOR, SALT = "friend-2026-401";
|
|
135
204
|
var init_buddy = __esm(() => {
|
|
205
|
+
init_wyhash();
|
|
136
206
|
RARITIES = ["common", "uncommon", "rare", "epic", "legendary"];
|
|
137
207
|
SPECIES = [
|
|
138
208
|
"duck",
|
|
@@ -2629,6 +2699,211 @@ function renderSummary(events, buddyName, foodName, foodEmoji) {
|
|
|
2629
2699
|
return out;
|
|
2630
2700
|
}
|
|
2631
2701
|
|
|
2702
|
+
// src/onboarding.ts
|
|
2703
|
+
init_colors();
|
|
2704
|
+
init_buddy();
|
|
2705
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2706
|
+
import { readdir as readdir2 } from "fs/promises";
|
|
2707
|
+
import { homedir as homedir6 } from "os";
|
|
2708
|
+
import { join as join6 } from "path";
|
|
2709
|
+
var STATE_FILE2 = join6(homedir6(), ".vibejourney", "state.json");
|
|
2710
|
+
var CLAUDE_PROJECTS = join6(homedir6(), ".claude", "projects");
|
|
2711
|
+
var CLEAR = "\x1B[2J\x1B[H";
|
|
2712
|
+
var RULE = C.dim + "─".repeat(52) + C.reset;
|
|
2713
|
+
function needsOnboarding() {
|
|
2714
|
+
return !existsSync2(STATE_FILE2);
|
|
2715
|
+
}
|
|
2716
|
+
async function checkTokenLogs() {
|
|
2717
|
+
if (!existsSync2(CLAUDE_PROJECTS))
|
|
2718
|
+
return false;
|
|
2719
|
+
try {
|
|
2720
|
+
const entries = await readdir2(CLAUDE_PROJECTS, { recursive: true });
|
|
2721
|
+
for (const e of entries) {
|
|
2722
|
+
if (typeof e === "string" && e.endsWith(".jsonl"))
|
|
2723
|
+
return true;
|
|
2724
|
+
}
|
|
2725
|
+
return false;
|
|
2726
|
+
} catch {
|
|
2727
|
+
return false;
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
function waitForEnter() {
|
|
2731
|
+
return new Promise((resolve) => {
|
|
2732
|
+
process.stdin.resume();
|
|
2733
|
+
const handler = () => {
|
|
2734
|
+
process.stdin.removeListener("data", handler);
|
|
2735
|
+
process.stdin.pause();
|
|
2736
|
+
resolve();
|
|
2737
|
+
};
|
|
2738
|
+
process.stdin.on("data", handler);
|
|
2739
|
+
});
|
|
2740
|
+
}
|
|
2741
|
+
function screenWelcome() {
|
|
2742
|
+
process.stdout.write(CLEAR);
|
|
2743
|
+
const pad = " ";
|
|
2744
|
+
const out = [];
|
|
2745
|
+
out.push("");
|
|
2746
|
+
out.push(`${pad}${C.bold}\uD83C\uDF0D VibeJourney${C.reset}`);
|
|
2747
|
+
out.push(`${pad}${C.dim}Your vibe coding is also a journey.${C.reset}`);
|
|
2748
|
+
out.push("");
|
|
2749
|
+
out.push(`${pad}${RULE}`);
|
|
2750
|
+
out.push("");
|
|
2751
|
+
out.push(`${pad}Every line of code you write sends your buddy a little further`);
|
|
2752
|
+
out.push(`${pad}into the world. While you're deep in a 2am debugging session,`);
|
|
2753
|
+
out.push(`${pad}your companion is watching the sunset in Barcelona. When you`);
|
|
2754
|
+
out.push(`${pad}finally ship that feature, they've already reached Tokyo and`);
|
|
2755
|
+
out.push(`${pad}picked up a souvenir for you.`);
|
|
2756
|
+
out.push("");
|
|
2757
|
+
out.push(`${pad}${C.bold}How it works${C.reset}`);
|
|
2758
|
+
out.push("");
|
|
2759
|
+
out.push(`${pad}${C.yellow}You code${C.reset} → daily Claude Code tokens become food`);
|
|
2760
|
+
out.push(`${pad}${C.yellow}Buddy explores${C.reset} → visits landmarks in the current city`);
|
|
2761
|
+
out.push(`${pad}${C.yellow}Buddy travels${C.reset} → walks toward the next city`);
|
|
2762
|
+
out.push(`${pad}${C.yellow}You rest${C.reset} → buddy rests with you`);
|
|
2763
|
+
out.push("");
|
|
2764
|
+
out.push(`${pad}${C.dim}29 cities · 18 companion species · one quiet journey${C.reset}`);
|
|
2765
|
+
out.push("");
|
|
2766
|
+
out.push(`${pad}${RULE}`);
|
|
2767
|
+
out.push("");
|
|
2768
|
+
out.push(`${pad}${C.dim}Press ${C.reset}${C.bold}Enter${C.reset}${C.dim} to continue...${C.reset}`);
|
|
2769
|
+
process.stdout.write(out.join(`
|
|
2770
|
+
`) + `
|
|
2771
|
+
`);
|
|
2772
|
+
}
|
|
2773
|
+
function screenSetup(buddy, hasTokenLogs) {
|
|
2774
|
+
process.stdout.write(CLEAR);
|
|
2775
|
+
const pad = " ";
|
|
2776
|
+
const out = [];
|
|
2777
|
+
out.push("");
|
|
2778
|
+
out.push(`${pad}${C.bold}Setup check${C.reset}`);
|
|
2779
|
+
out.push("");
|
|
2780
|
+
out.push(`${pad}${RULE}`);
|
|
2781
|
+
out.push("");
|
|
2782
|
+
if (buddy) {
|
|
2783
|
+
out.push(`${pad}${C.green}✓${C.reset} Claude Code companion found`);
|
|
2784
|
+
out.push(`${pad} ${C.dim}Your buddy is named ${C.reset}${C.yellow}${buddy.name}${C.reset}${C.dim}.${C.reset}`);
|
|
2785
|
+
} else {
|
|
2786
|
+
out.push(`${pad}${C.yellow}!${C.reset} ${C.dim}No companion in ${C.reset}${C.yellow}~/.claude.json${C.reset}`);
|
|
2787
|
+
out.push(`${pad} ${C.dim}Install Claude Code and enable the companion for a${C.reset}`);
|
|
2788
|
+
out.push(`${pad} ${C.dim}named buddy with personality-driven commentary.${C.reset}`);
|
|
2789
|
+
out.push(`${pad} ${C.dim}Without it your traveler is nameless but still walks.${C.reset}`);
|
|
2790
|
+
}
|
|
2791
|
+
out.push("");
|
|
2792
|
+
if (hasTokenLogs) {
|
|
2793
|
+
out.push(`${pad}${C.green}✓${C.reset} Claude Code token logs found`);
|
|
2794
|
+
out.push(`${pad} ${C.dim}Your buddy already has food to spend.${C.reset}`);
|
|
2795
|
+
} else {
|
|
2796
|
+
out.push(`${pad}${C.yellow}!${C.reset} ${C.dim}No token logs at ${C.reset}${C.yellow}~/.claude/projects/${C.reset}`);
|
|
2797
|
+
out.push(`${pad} ${C.dim}Run ${C.reset}${C.bold}claude${C.reset}${C.dim} at least once so vibejourney has${C.reset}`);
|
|
2798
|
+
out.push(`${pad} ${C.dim}tokens to turn into food. Until then, buddy rests.${C.reset}`);
|
|
2799
|
+
}
|
|
2800
|
+
out.push("");
|
|
2801
|
+
out.push(`${pad}${C.dim}Data lives at ${C.reset}${C.yellow}~/.vibejourney${C.reset}${C.dim}. Start over with ${C.reset}${C.bold}--reset${C.reset}${C.dim}.${C.reset}`);
|
|
2802
|
+
out.push("");
|
|
2803
|
+
out.push(`${pad}${RULE}`);
|
|
2804
|
+
out.push("");
|
|
2805
|
+
out.push(`${pad}${C.dim}Press ${C.reset}${C.bold}Enter${C.reset}${C.dim} to continue...${C.reset}`);
|
|
2806
|
+
process.stdout.write(out.join(`
|
|
2807
|
+
`) + `
|
|
2808
|
+
`);
|
|
2809
|
+
}
|
|
2810
|
+
function wrapText(text, width) {
|
|
2811
|
+
const words = text.split(/\s+/);
|
|
2812
|
+
const lines = [];
|
|
2813
|
+
let line = "";
|
|
2814
|
+
for (const w of words) {
|
|
2815
|
+
const next = line ? `${line} ${w}` : w;
|
|
2816
|
+
if (next.length > width && line) {
|
|
2817
|
+
lines.push(line);
|
|
2818
|
+
line = w;
|
|
2819
|
+
} else {
|
|
2820
|
+
line = next;
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
if (line)
|
|
2824
|
+
lines.push(line);
|
|
2825
|
+
return lines;
|
|
2826
|
+
}
|
|
2827
|
+
function screenBuddy(buddy) {
|
|
2828
|
+
process.stdout.write(CLEAR);
|
|
2829
|
+
const pad = " ";
|
|
2830
|
+
const out = [];
|
|
2831
|
+
out.push("");
|
|
2832
|
+
if (buddy) {
|
|
2833
|
+
out.push(`${pad}${C.bold}Meet ${C.reset}${C.yellow}${buddy.name}${C.reset}`);
|
|
2834
|
+
out.push("");
|
|
2835
|
+
out.push(`${pad}${RULE}`);
|
|
2836
|
+
out.push("");
|
|
2837
|
+
const sprite = renderSprite(buddy, 0);
|
|
2838
|
+
for (const line of sprite) {
|
|
2839
|
+
out.push(`${pad} ${C.white}${line}${C.reset}`);
|
|
2840
|
+
}
|
|
2841
|
+
out.push("");
|
|
2842
|
+
const tag = `${buddy.rarity} ${buddy.species}${buddy.shiny ? " · ✨ shiny" : ""}`;
|
|
2843
|
+
out.push(`${pad}${C.dim}${tag}${C.reset}`);
|
|
2844
|
+
if (buddy.personality) {
|
|
2845
|
+
out.push("");
|
|
2846
|
+
for (const line of wrapText(buddy.personality, 56)) {
|
|
2847
|
+
out.push(`${pad}${C.dim}"${line}"${C.reset}`);
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
} else {
|
|
2851
|
+
out.push(`${pad}${C.bold}Your traveler awaits${C.reset}`);
|
|
2852
|
+
out.push("");
|
|
2853
|
+
out.push(`${pad}${RULE}`);
|
|
2854
|
+
out.push("");
|
|
2855
|
+
out.push(`${pad}${C.dim}Without a Claude Code companion your buddy will be a${C.reset}`);
|
|
2856
|
+
out.push(`${pad}${C.dim}nameless wanderer. Still exploring, still collecting${C.reset}`);
|
|
2857
|
+
out.push(`${pad}${C.dim}souvenirs, still finding its way — just quietly.${C.reset}`);
|
|
2858
|
+
}
|
|
2859
|
+
out.push("");
|
|
2860
|
+
out.push(`${pad}${RULE}`);
|
|
2861
|
+
out.push("");
|
|
2862
|
+
out.push(`${pad}${C.yellow}The journey begins when you press ${C.reset}${C.bold}Enter${C.reset}${C.yellow}.${C.reset}`);
|
|
2863
|
+
out.push("");
|
|
2864
|
+
process.stdout.write(out.join(`
|
|
2865
|
+
`) + `
|
|
2866
|
+
`);
|
|
2867
|
+
}
|
|
2868
|
+
function printCompact(buddy, hasTokenLogs) {
|
|
2869
|
+
const pad = " ";
|
|
2870
|
+
const out = [];
|
|
2871
|
+
out.push("");
|
|
2872
|
+
out.push(`${pad}${C.bold}\uD83C\uDF0D VibeJourney${C.reset} ${C.dim}— Your vibe coding is also a journey.${C.reset}`);
|
|
2873
|
+
out.push("");
|
|
2874
|
+
out.push(`${pad}Your daily Claude Code tokens feed a buddy that explores`);
|
|
2875
|
+
out.push(`${pad}landmarks and walks between 29 cities while you write code.`);
|
|
2876
|
+
out.push("");
|
|
2877
|
+
if (buddy) {
|
|
2878
|
+
out.push(`${pad}${C.green}✓${C.reset} Companion: ${C.yellow}${buddy.name}${C.reset} ${C.dim}(${buddy.rarity} ${buddy.species})${C.reset}`);
|
|
2879
|
+
} else {
|
|
2880
|
+
out.push(`${pad}${C.yellow}!${C.reset} ${C.dim}No Claude Code companion — buddy will be nameless.${C.reset}`);
|
|
2881
|
+
}
|
|
2882
|
+
if (hasTokenLogs) {
|
|
2883
|
+
out.push(`${pad}${C.green}✓${C.reset} Token logs detected.`);
|
|
2884
|
+
} else {
|
|
2885
|
+
out.push(`${pad}${C.yellow}!${C.reset} ${C.dim}No token history yet — run claude first.${C.reset}`);
|
|
2886
|
+
}
|
|
2887
|
+
out.push("");
|
|
2888
|
+
process.stdout.write(out.join(`
|
|
2889
|
+
`) + `
|
|
2890
|
+
`);
|
|
2891
|
+
}
|
|
2892
|
+
async function runOnboarding(buddy, hasTokenLogs) {
|
|
2893
|
+
const interactive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
2894
|
+
if (!interactive) {
|
|
2895
|
+
printCompact(buddy, hasTokenLogs);
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
screenWelcome();
|
|
2899
|
+
await waitForEnter();
|
|
2900
|
+
screenSetup(buddy, hasTokenLogs);
|
|
2901
|
+
await waitForEnter();
|
|
2902
|
+
screenBuddy(buddy);
|
|
2903
|
+
await waitForEnter();
|
|
2904
|
+
process.stdout.write(CLEAR);
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2632
2907
|
// index.ts
|
|
2633
2908
|
var args = process.argv.slice(2);
|
|
2634
2909
|
if (args[0] === "--help" || args[0] === "-h") {
|
|
@@ -2656,9 +2931,9 @@ if (args[0] === "--help" || args[0] === "-h") {
|
|
|
2656
2931
|
}
|
|
2657
2932
|
if (args[0] === "--reset") {
|
|
2658
2933
|
const { rm } = await import("fs/promises");
|
|
2659
|
-
const { join:
|
|
2660
|
-
const { homedir:
|
|
2661
|
-
const dir =
|
|
2934
|
+
const { join: join7 } = await import("path");
|
|
2935
|
+
const { homedir: homedir7 } = await import("os");
|
|
2936
|
+
const dir = join7(homedir7(), ".vibejourney");
|
|
2662
2937
|
process.stdout.write(`
|
|
2663
2938
|
This will delete all journey data at ${dir}
|
|
2664
2939
|
`);
|
|
@@ -2671,17 +2946,15 @@ if (args[0] === "--reset") {
|
|
|
2671
2946
|
process.stdin.once("data", (data) => resolve(data.toString().trim()));
|
|
2672
2947
|
});
|
|
2673
2948
|
if (response.toLowerCase() === "yes") {
|
|
2674
|
-
await rm(
|
|
2675
|
-
await rm(
|
|
2676
|
-
|
|
2677
|
-
Journey reset. Run again to start fresh!
|
|
2678
|
-
`);
|
|
2949
|
+
await rm(join7(dir, "state.json"), { force: true });
|
|
2950
|
+
await rm(join7(dir, "journal.jsonl"), { force: true });
|
|
2951
|
+
process.stdin.pause();
|
|
2679
2952
|
} else {
|
|
2680
2953
|
console.log(`
|
|
2681
2954
|
Reset cancelled.
|
|
2682
2955
|
`);
|
|
2956
|
+
process.exit(0);
|
|
2683
2957
|
}
|
|
2684
|
-
process.exit(0);
|
|
2685
2958
|
}
|
|
2686
2959
|
if (args[0] === "--collection") {
|
|
2687
2960
|
const buddy = getLocalCompanion();
|
|
@@ -2734,6 +3007,11 @@ if (args[0] === "--stats") {
|
|
|
2734
3007
|
process.exit(0);
|
|
2735
3008
|
}
|
|
2736
3009
|
async function main() {
|
|
3010
|
+
if (needsOnboarding()) {
|
|
3011
|
+
const buddyForIntro = getLocalCompanion();
|
|
3012
|
+
const hasTokenLogs = await checkTokenLogs();
|
|
3013
|
+
await runOnboarding(buddyForIntro, hasTokenLogs);
|
|
3014
|
+
}
|
|
2737
3015
|
process.stderr.write(`${C.dim}Loading...${C.reset}
|
|
2738
3016
|
`);
|
|
2739
3017
|
const buddy = getLocalCompanion();
|
|
@@ -2841,7 +3119,7 @@ async function main() {
|
|
|
2841
3119
|
let out = `
|
|
2842
3120
|
|
|
2843
3121
|
`;
|
|
2844
|
-
out += `${pad}${C.bold}\uD83C\uDF0D VibeJourney${C.reset}
|
|
3122
|
+
out += `${pad}${C.bold}\uD83C\uDF0D VibeJourney${C.reset} ${C.dim}\u2014 Your vibe coding is also a journey.${C.reset}
|
|
2845
3123
|
`;
|
|
2846
3124
|
out += `${pad}${C.dim}[j] \uD83D\uDCD6 journal \xB7 [c] \uD83C\uDF92 collection \xB7 [s] \uD83D\uDCCA stats \xB7 [r] \uD83D\uDD04 refresh \xB7 [q] exit${C.reset}
|
|
2847
3125
|
`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibejourney",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Your vibe coding is also a journey — your buddy explores the world while you write code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|