@prestyj/boss 4.10.1 → 4.12.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 +4 -4
- package/dist/{chunk-72J6ZGVA.js → chunk-HYXLQEZL.js} +2294 -522
- package/dist/{chunk-72J6ZGVA.js.map → chunk-HYXLQEZL.js.map} +1 -1
- package/dist/cli.js +27 -266
- 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-HYXLQEZL.js";
|
|
80
81
|
import "./chunk-7QDS2KEP.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 [ez, cc, cx] = await Promise.all([
|
|
128
|
-
discoverEzcoderProjects(),
|
|
129
|
-
discoverClaudeProjects(),
|
|
130
|
-
discoverCodexProjects()
|
|
131
|
-
]);
|
|
132
|
-
const byPath = /* @__PURE__ */ new Map();
|
|
133
|
-
for (const p of [...ez, ...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
|
-
ezcoder: 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 discoverEzcoderProjects() {
|
|
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: ["ezcoder"]
|
|
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: "@prestyj/boss",
|
|
372
|
-
version: "4.
|
|
133
|
+
version: "4.12.0",
|
|
373
134
|
type: "module",
|
|
374
135
|
description: "Orchestrator agent that drives multiple ezcoder 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")
|
|
@@ -3011,11 +2772,11 @@ function renderRoundNoticeBox(lines, context, borderColor) {
|
|
|
3011
2772
|
|
|
3012
2773
|
// src/auto-update.ts
|
|
3013
2774
|
init_esm_shims();
|
|
3014
|
-
import
|
|
3015
|
-
import
|
|
2775
|
+
import path3 from "path";
|
|
2776
|
+
import os from "os";
|
|
3016
2777
|
var updater = createAutoUpdater({
|
|
3017
2778
|
packageName: "@prestyj/boss",
|
|
3018
|
-
stateFilePath: () =>
|
|
2779
|
+
stateFilePath: () => path3.join(os.homedir(), ".ezcoder", "boss", "update-state.json"),
|
|
3019
2780
|
periodicMessage: ({ currentVersion, latestVersion, updateCommand }) => `Ken just pushed a fresh update \u2014 ${currentVersion} \u2192 ${latestVersion}! Restart ezboss to grab it (or run ${updateCommand} if you can't wait).`
|
|
3020
2781
|
});
|
|
3021
2782
|
var checkAndAutoUpdate = updater.checkAndAutoUpdate;
|
|
@@ -3460,14 +3221,14 @@ init_esm_shims();
|
|
|
3460
3221
|
var import_react16 = __toESM(require_react(), 1);
|
|
3461
3222
|
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
3462
3223
|
var SPLASH_LINES = [
|
|
3463
|
-
"
|
|
3464
|
-
"
|
|
3465
|
-
" \u2588\u2588\u2588
|
|
3466
|
-
"\u2591\u2588\u2588\u2588
|
|
3467
|
-
"\u2591\u2588\u2588\u2588
|
|
3468
|
-
"\u2591\
|
|
3469
|
-
" \
|
|
3470
|
-
"
|
|
3224
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ",
|
|
3225
|
+
"\u2591\u2591\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2591\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2588\u2588\u2588 \u2591\u2591\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2588\u2588 ",
|
|
3226
|
+
" \u2591\u2588\u2588\u2588 \u2588 \u2591 \u2591 \u2588\u2588\u2588\u2591 \u2591\u2588\u2588\u2588 \u2591\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 ",
|
|
3227
|
+
" \u2591\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2591\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2591\u2591\u2588\u2588\u2588 \u2588\u2588\u2588\u2591\u2591 \u2588\u2588\u2588\u2591\u2591 ",
|
|
3228
|
+
" \u2591\u2588\u2588\u2588\u2591\u2591\u2588 \u2588\u2588\u2588 \u2591\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2588\u2588\u2588\u2591\u2588\u2588\u2588 \u2591\u2588\u2588\u2588\u2591\u2591\u2588\u2588\u2588\u2588\u2588 \u2591\u2591\u2588\u2588\u2588\u2588\u2588 ",
|
|
3229
|
+
" \u2591\u2588\u2588\u2588 \u2591 \u2588 \u2588\u2588\u2588\u2588 \u2588 \u2591\u2588\u2588\u2588 \u2591\u2588\u2588\u2588\u2591\u2588\u2588\u2588 \u2591\u2588\u2588\u2588 \u2591\u2591\u2591\u2591\u2588\u2588\u2588 \u2591\u2591\u2591\u2591\u2588\u2588\u2588",
|
|
3230
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 ",
|
|
3231
|
+
"\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2591\u2591\u2591\u2591\u2591\u2591 \u2591\u2591\u2591\u2591\u2591\u2591 \u2591\u2591\u2591\u2591\u2591\u2591 "
|
|
3471
3232
|
];
|
|
3472
3233
|
var SPLASH_WIDTH = SPLASH_LINES[0].length;
|
|
3473
3234
|
function colorForLine(lineIdx, totalLines, offset) {
|
|
@@ -3568,11 +3329,11 @@ function parseProjectSpec(raw) {
|
|
|
3568
3329
|
const eq = raw.indexOf("=");
|
|
3569
3330
|
if (eq > 0) {
|
|
3570
3331
|
const name = raw.slice(0, eq);
|
|
3571
|
-
const cwd2 =
|
|
3332
|
+
const cwd2 = path4.resolve(raw.slice(eq + 1));
|
|
3572
3333
|
return { name, cwd: cwd2 };
|
|
3573
3334
|
}
|
|
3574
|
-
const cwd =
|
|
3575
|
-
return { name:
|
|
3335
|
+
const cwd = path4.resolve(raw);
|
|
3336
|
+
return { name: path4.basename(cwd), cwd };
|
|
3576
3337
|
}
|
|
3577
3338
|
function parseArgs(argv) {
|
|
3578
3339
|
const args = {
|