@kenkaiiii/gg-boss 4.10.1 → 4.10.2
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/dist/{chunk-EV37X3XL.js → chunk-UH3DA72U.js} +1026 -281
- package/dist/{chunk-EV37X3XL.js.map → chunk-UH3DA72U.js.map} +1 -1
- package/dist/cli.js +19 -258
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
color,
|
|
33
33
|
createAutoUpdater,
|
|
34
34
|
dim,
|
|
35
|
+
discoverProjects,
|
|
35
36
|
formatHistoryWrite,
|
|
36
37
|
getAppPaths,
|
|
37
38
|
getBossState,
|
|
@@ -76,7 +77,7 @@ import {
|
|
|
76
77
|
use_input_default,
|
|
77
78
|
use_stdout_default,
|
|
78
79
|
wrapPlain
|
|
79
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-UH3DA72U.js";
|
|
80
81
|
import "./chunk-JEGMYLRS.js";
|
|
81
82
|
import {
|
|
82
83
|
source_default
|
|
@@ -88,7 +89,7 @@ import {
|
|
|
88
89
|
|
|
89
90
|
// src/cli.ts
|
|
90
91
|
init_esm_shims();
|
|
91
|
-
import
|
|
92
|
+
import path4 from "path";
|
|
92
93
|
|
|
93
94
|
// src/links.ts
|
|
94
95
|
init_esm_shims();
|
|
@@ -118,246 +119,6 @@ var import_react2 = __toESM(require_react(), 1);
|
|
|
118
119
|
|
|
119
120
|
// src/discover.ts
|
|
120
121
|
init_esm_shims();
|
|
121
|
-
import fs2 from "fs/promises";
|
|
122
|
-
import { createReadStream } from "fs";
|
|
123
|
-
import readline from "readline";
|
|
124
|
-
import os from "os";
|
|
125
|
-
import path2 from "path";
|
|
126
|
-
async function discoverProjects() {
|
|
127
|
-
const [gg, cc, cx] = await Promise.all([
|
|
128
|
-
discoverGgcoderProjects(),
|
|
129
|
-
discoverClaudeProjects(),
|
|
130
|
-
discoverCodexProjects()
|
|
131
|
-
]);
|
|
132
|
-
const byPath = /* @__PURE__ */ new Map();
|
|
133
|
-
for (const p of [...gg, ...cc, ...cx]) {
|
|
134
|
-
const existing = byPath.get(p.path);
|
|
135
|
-
if (!existing) {
|
|
136
|
-
byPath.set(p.path, p);
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
byPath.set(p.path, {
|
|
140
|
-
name: existing.name,
|
|
141
|
-
path: existing.path,
|
|
142
|
-
lastActiveMs: Math.max(existing.lastActiveMs, p.lastActiveMs),
|
|
143
|
-
lastActiveDisplay: "",
|
|
144
|
-
// recomputed below
|
|
145
|
-
sources: mergeSources(existing.sources, p.sources)
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
const merged = Array.from(byPath.values()).map((p) => ({
|
|
149
|
-
...p,
|
|
150
|
-
lastActiveDisplay: formatRelativeTime(p.lastActiveMs)
|
|
151
|
-
}));
|
|
152
|
-
merged.sort((a, b) => b.lastActiveMs - a.lastActiveMs);
|
|
153
|
-
return merged;
|
|
154
|
-
}
|
|
155
|
-
var SOURCE_ORDER = {
|
|
156
|
-
ggcoder: 0,
|
|
157
|
-
"claude-code": 1,
|
|
158
|
-
codex: 2
|
|
159
|
-
};
|
|
160
|
-
function mergeSources(a, b) {
|
|
161
|
-
const set = /* @__PURE__ */ new Set([...a, ...b]);
|
|
162
|
-
return Array.from(set).sort((x, y) => SOURCE_ORDER[x] - SOURCE_ORDER[y]);
|
|
163
|
-
}
|
|
164
|
-
async function discoverGgcoderProjects() {
|
|
165
|
-
const sessionsDir = getAppPaths().sessionsDir;
|
|
166
|
-
let entries;
|
|
167
|
-
try {
|
|
168
|
-
entries = await fs2.readdir(sessionsDir);
|
|
169
|
-
} catch {
|
|
170
|
-
return [];
|
|
171
|
-
}
|
|
172
|
-
const results = [];
|
|
173
|
-
for (const entry of entries) {
|
|
174
|
-
const dir = path2.join(sessionsDir, entry);
|
|
175
|
-
const mtime = await maxJsonlMtime(dir);
|
|
176
|
-
if (mtime === null) continue;
|
|
177
|
-
const decoded = "/" + entry.replace(/_/g, "/");
|
|
178
|
-
if (!await isDirectory(decoded)) continue;
|
|
179
|
-
results.push({
|
|
180
|
-
name: path2.basename(decoded),
|
|
181
|
-
path: decoded,
|
|
182
|
-
lastActiveMs: mtime,
|
|
183
|
-
lastActiveDisplay: formatRelativeTime(mtime),
|
|
184
|
-
sources: ["ggcoder"]
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
return results;
|
|
188
|
-
}
|
|
189
|
-
async function discoverClaudeProjects() {
|
|
190
|
-
const projectsDir = path2.join(os.homedir(), ".claude", "projects");
|
|
191
|
-
let entries;
|
|
192
|
-
try {
|
|
193
|
-
entries = await fs2.readdir(projectsDir);
|
|
194
|
-
} catch {
|
|
195
|
-
return [];
|
|
196
|
-
}
|
|
197
|
-
const results = await Promise.all(
|
|
198
|
-
entries.map(async (entry) => {
|
|
199
|
-
const dir = path2.join(projectsDir, entry);
|
|
200
|
-
const mtime = await maxJsonlMtime(dir);
|
|
201
|
-
if (mtime === null) return null;
|
|
202
|
-
const cwd = await readFirstFromJsonlDir(dir, claudeCwdExtractor) ?? fallbackDashDecode(entry);
|
|
203
|
-
if (!cwd) return null;
|
|
204
|
-
if (!await isDirectory(cwd)) return null;
|
|
205
|
-
return {
|
|
206
|
-
name: path2.basename(cwd),
|
|
207
|
-
path: cwd,
|
|
208
|
-
lastActiveMs: mtime,
|
|
209
|
-
lastActiveDisplay: formatRelativeTime(mtime),
|
|
210
|
-
sources: ["claude-code"]
|
|
211
|
-
};
|
|
212
|
-
})
|
|
213
|
-
);
|
|
214
|
-
return results.filter((p) => p !== null);
|
|
215
|
-
}
|
|
216
|
-
async function discoverCodexProjects() {
|
|
217
|
-
const sessionsDir = path2.join(os.homedir(), ".codex", "sessions");
|
|
218
|
-
if (!await isDirectory(sessionsDir)) return [];
|
|
219
|
-
const files = await collectJsonlFiles(sessionsDir, 4);
|
|
220
|
-
if (files.length === 0) return [];
|
|
221
|
-
files.sort((a, b) => b.mtime - a.mtime);
|
|
222
|
-
const byCwd = /* @__PURE__ */ new Map();
|
|
223
|
-
for (const f of files) {
|
|
224
|
-
const cwd = await readFirstFromFile(f.path, codexCwdExtractor);
|
|
225
|
-
if (!cwd) continue;
|
|
226
|
-
const prev = byCwd.get(cwd);
|
|
227
|
-
if (prev === void 0 || f.mtime > prev) byCwd.set(cwd, f.mtime);
|
|
228
|
-
}
|
|
229
|
-
const results = [];
|
|
230
|
-
for (const [cwd, mtime] of byCwd) {
|
|
231
|
-
if (!await isDirectory(cwd)) continue;
|
|
232
|
-
results.push({
|
|
233
|
-
name: path2.basename(cwd),
|
|
234
|
-
path: cwd,
|
|
235
|
-
lastActiveMs: mtime,
|
|
236
|
-
lastActiveDisplay: formatRelativeTime(mtime),
|
|
237
|
-
sources: ["codex"]
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
return results;
|
|
241
|
-
}
|
|
242
|
-
async function isDirectory(p) {
|
|
243
|
-
try {
|
|
244
|
-
const s = await fs2.stat(p);
|
|
245
|
-
return s.isDirectory();
|
|
246
|
-
} catch {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
async function maxJsonlMtime(dir) {
|
|
251
|
-
if (!await isDirectory(dir)) return null;
|
|
252
|
-
const files = await collectJsonlFiles(dir, 2);
|
|
253
|
-
if (files.length === 0) return null;
|
|
254
|
-
let max = 0;
|
|
255
|
-
for (const f of files) if (f.mtime > max) max = f.mtime;
|
|
256
|
-
return max > 0 ? max : null;
|
|
257
|
-
}
|
|
258
|
-
async function collectJsonlFiles(dir, maxDepth) {
|
|
259
|
-
const out = [];
|
|
260
|
-
await walk(dir, 0);
|
|
261
|
-
return out;
|
|
262
|
-
async function walk(current, depth) {
|
|
263
|
-
let entries;
|
|
264
|
-
try {
|
|
265
|
-
entries = await fs2.readdir(current, { withFileTypes: true });
|
|
266
|
-
} catch {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
for (const e of entries) {
|
|
270
|
-
const full = path2.join(current, e.name);
|
|
271
|
-
if (e.isFile() && e.name.endsWith(".jsonl")) {
|
|
272
|
-
try {
|
|
273
|
-
const s = await fs2.stat(full);
|
|
274
|
-
out.push({ path: full, mtime: s.mtimeMs });
|
|
275
|
-
} catch {
|
|
276
|
-
}
|
|
277
|
-
} else if (e.isDirectory() && depth < maxDepth) {
|
|
278
|
-
await walk(full, depth + 1);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
var claudeCwdExtractor = (line) => {
|
|
284
|
-
try {
|
|
285
|
-
const parsed = JSON.parse(line);
|
|
286
|
-
if (typeof parsed.cwd === "string" && parsed.cwd.startsWith("/")) return parsed.cwd;
|
|
287
|
-
} catch {
|
|
288
|
-
}
|
|
289
|
-
return null;
|
|
290
|
-
};
|
|
291
|
-
var CODEX_CWD_RE = /<cwd>([^<]+)<\/cwd>/;
|
|
292
|
-
var codexCwdExtractor = (line) => {
|
|
293
|
-
try {
|
|
294
|
-
const parsed = JSON.parse(line);
|
|
295
|
-
const cwd = parsed.payload?.cwd;
|
|
296
|
-
if (typeof cwd === "string" && cwd.startsWith("/")) return cwd;
|
|
297
|
-
} catch {
|
|
298
|
-
}
|
|
299
|
-
const m = CODEX_CWD_RE.exec(line);
|
|
300
|
-
if (m && m[1] && m[1].startsWith("/")) return m[1];
|
|
301
|
-
return null;
|
|
302
|
-
};
|
|
303
|
-
async function readFirstFromJsonlDir(dir, extractor) {
|
|
304
|
-
const files = await collectJsonlFiles(dir, 2);
|
|
305
|
-
if (files.length === 0) return null;
|
|
306
|
-
files.sort((a, b) => b.mtime - a.mtime);
|
|
307
|
-
for (const f of files) {
|
|
308
|
-
const v = await readFirstFromFile(f.path, extractor);
|
|
309
|
-
if (v) return v;
|
|
310
|
-
}
|
|
311
|
-
return null;
|
|
312
|
-
}
|
|
313
|
-
async function readFirstFromFile(file, extractor) {
|
|
314
|
-
return new Promise((resolve) => {
|
|
315
|
-
const stream = createReadStream(file, { encoding: "utf-8" });
|
|
316
|
-
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
317
|
-
let lines = 0;
|
|
318
|
-
let done = false;
|
|
319
|
-
const MAX_LINES = 200;
|
|
320
|
-
const finish = (value) => {
|
|
321
|
-
if (done) return;
|
|
322
|
-
done = true;
|
|
323
|
-
resolve(value);
|
|
324
|
-
rl.close();
|
|
325
|
-
stream.destroy();
|
|
326
|
-
};
|
|
327
|
-
rl.on("line", (line) => {
|
|
328
|
-
if (done) return;
|
|
329
|
-
lines++;
|
|
330
|
-
if (lines > MAX_LINES) {
|
|
331
|
-
finish(null);
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const v = extractor(line);
|
|
335
|
-
if (v) finish(v);
|
|
336
|
-
});
|
|
337
|
-
rl.on("close", () => finish(null));
|
|
338
|
-
rl.on("error", () => finish(null));
|
|
339
|
-
stream.on("error", () => finish(null));
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
function fallbackDashDecode(entry) {
|
|
343
|
-
if (!entry.startsWith("-")) return null;
|
|
344
|
-
return "/" + entry.slice(1).replace(/-/g, "/");
|
|
345
|
-
}
|
|
346
|
-
function formatRelativeTime(ms) {
|
|
347
|
-
if (ms === 0) return "\u2014";
|
|
348
|
-
const diff = Date.now() - ms;
|
|
349
|
-
if (diff < 6e4) return "just now";
|
|
350
|
-
const min = 6e4;
|
|
351
|
-
const hour = 60 * min;
|
|
352
|
-
const day = 24 * hour;
|
|
353
|
-
const week = 7 * day;
|
|
354
|
-
const month = 30 * day;
|
|
355
|
-
if (diff < hour) return `${Math.floor(diff / min)}m ago`;
|
|
356
|
-
if (diff < day) return `${Math.floor(diff / hour)}h ago`;
|
|
357
|
-
if (diff < week) return `${Math.floor(diff / day)}d ago`;
|
|
358
|
-
if (diff < month) return `${Math.floor(diff / week)}w ago`;
|
|
359
|
-
return `${Math.floor(diff / month)}mo ago`;
|
|
360
|
-
}
|
|
361
122
|
|
|
362
123
|
// src/banner.tsx
|
|
363
124
|
init_esm_shims();
|
|
@@ -369,7 +130,7 @@ init_esm_shims();
|
|
|
369
130
|
// package.json
|
|
370
131
|
var package_default = {
|
|
371
132
|
name: "@kenkaiiii/gg-boss",
|
|
372
|
-
version: "4.10.
|
|
133
|
+
version: "4.10.2",
|
|
373
134
|
type: "module",
|
|
374
135
|
description: "Orchestrator agent that drives multiple ggcoder sessions across projects from a single chat",
|
|
375
136
|
license: "MIT",
|
|
@@ -649,7 +410,7 @@ async function runLinkCommand() {
|
|
|
649
410
|
process.stdout.write(source_default.hex(COLORS.textDim)("\nCancelled. No changes saved.\n"));
|
|
650
411
|
return;
|
|
651
412
|
}
|
|
652
|
-
const linked = result.selected.map((
|
|
413
|
+
const linked = result.selected.map((path5) => projects.find((p) => p.path === path5)).filter((p) => Boolean(p)).map((p) => ({ name: p.name, cwd: p.path }));
|
|
653
414
|
await saveLinks({ projects: linked });
|
|
654
415
|
process.stdout.write("\n");
|
|
655
416
|
if (linked.length === 0) {
|
|
@@ -676,14 +437,14 @@ async function runLinkCommand() {
|
|
|
676
437
|
|
|
677
438
|
// src/serve-mode.ts
|
|
678
439
|
init_esm_shims();
|
|
679
|
-
import
|
|
680
|
-
import
|
|
440
|
+
import path2 from "path";
|
|
441
|
+
import fs2 from "fs/promises";
|
|
681
442
|
function getTelegramConfigPath() {
|
|
682
|
-
return
|
|
443
|
+
return path2.join(getAppPaths().agentDir, "boss", "telegram.json");
|
|
683
444
|
}
|
|
684
445
|
async function loadBossTelegramConfig() {
|
|
685
446
|
try {
|
|
686
|
-
const raw = await
|
|
447
|
+
const raw = await fs2.readFile(getTelegramConfigPath(), "utf-8");
|
|
687
448
|
const data = JSON.parse(raw);
|
|
688
449
|
if (data.botToken && data.userId) return data;
|
|
689
450
|
return null;
|
|
@@ -693,8 +454,8 @@ async function loadBossTelegramConfig() {
|
|
|
693
454
|
}
|
|
694
455
|
async function saveBossTelegramConfig(config) {
|
|
695
456
|
const file = getTelegramConfigPath();
|
|
696
|
-
await
|
|
697
|
-
await
|
|
457
|
+
await fs2.mkdir(path2.dirname(file), { recursive: true });
|
|
458
|
+
await fs2.writeFile(file, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
698
459
|
}
|
|
699
460
|
function formatItemForTelegram(item) {
|
|
700
461
|
switch (item.kind) {
|
|
@@ -1146,7 +907,7 @@ function printBanner(opts) {
|
|
|
1146
907
|
|
|
1147
908
|
// src/telegram-setup.ts
|
|
1148
909
|
init_esm_shims();
|
|
1149
|
-
import
|
|
910
|
+
import readline from "readline/promises";
|
|
1150
911
|
async function runBossTelegramSetup() {
|
|
1151
912
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
1152
913
|
printSetupBanner();
|
|
@@ -1160,7 +921,7 @@ async function runBossTelegramSetup() {
|
|
|
1160
921
|
`)
|
|
1161
922
|
);
|
|
1162
923
|
}
|
|
1163
|
-
const rl =
|
|
924
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1164
925
|
try {
|
|
1165
926
|
console.log(
|
|
1166
927
|
source_default.hex(COLORS.accent)(" Step 1: Bot Token\n") + source_default.hex(COLORS.textDim)(" 1. Open BotFather: ") + source_default.hex(COLORS.primary).underline("https://t.me/BotFather") + "\n" + source_default.hex(COLORS.textDim)(" 2. Send /newbot and follow the prompts\n") + source_default.hex(COLORS.textDim)(" 3. Copy the bot token\n")
|
|
@@ -3001,11 +2762,11 @@ function renderRoundNoticeBox(lines, context, borderColor) {
|
|
|
3001
2762
|
|
|
3002
2763
|
// src/auto-update.ts
|
|
3003
2764
|
init_esm_shims();
|
|
3004
|
-
import
|
|
3005
|
-
import
|
|
2765
|
+
import path3 from "path";
|
|
2766
|
+
import os from "os";
|
|
3006
2767
|
var updater = createAutoUpdater({
|
|
3007
2768
|
packageName: "@kenkaiiii/gg-boss",
|
|
3008
|
-
stateFilePath: () =>
|
|
2769
|
+
stateFilePath: () => path3.join(os.homedir(), ".gg", "boss", "update-state.json"),
|
|
3009
2770
|
periodicMessage: ({ currentVersion, latestVersion, updateCommand }) => `Ken just pushed a fresh update \u2014 ${currentVersion} \u2192 ${latestVersion}! Restart ggboss to grab it (or run ${updateCommand} if you can't wait).`
|
|
3010
2771
|
});
|
|
3011
2772
|
var checkAndAutoUpdate = updater.checkAndAutoUpdate;
|
|
@@ -3558,11 +3319,11 @@ function parseProjectSpec(raw) {
|
|
|
3558
3319
|
const eq = raw.indexOf("=");
|
|
3559
3320
|
if (eq > 0) {
|
|
3560
3321
|
const name = raw.slice(0, eq);
|
|
3561
|
-
const cwd2 =
|
|
3322
|
+
const cwd2 = path4.resolve(raw.slice(eq + 1));
|
|
3562
3323
|
return { name, cwd: cwd2 };
|
|
3563
3324
|
}
|
|
3564
|
-
const cwd =
|
|
3565
|
-
return { name:
|
|
3325
|
+
const cwd = path4.resolve(raw);
|
|
3326
|
+
return { name: path4.basename(cwd), cwd };
|
|
3566
3327
|
}
|
|
3567
3328
|
function parseArgs(argv) {
|
|
3568
3329
|
const args = {
|