@joeyshi12/casper 0.8.6 → 0.8.8
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/mcp.js +1 -1
- package/dist/server.js +174 -133
- package/dist/web/assets/{abnfDiagram-N423BO3Z-i4fdRJCJ.js → abnfDiagram-N423BO3Z-dD8GuEng.js} +1 -1
- package/dist/web/assets/{arc-CNTtovdQ.js → arc-BrT5U_LP.js} +1 -1
- package/dist/web/assets/{architectureDiagram-T3A2C74G-DduZE2nZ.js → architectureDiagram-T3A2C74G-Bk6pq1Xm.js} +1 -1
- package/dist/web/assets/{blockDiagram-VBNYF7ZC-ByAhziEP.js → blockDiagram-VBNYF7ZC-nMmkAmal.js} +1 -1
- package/dist/web/assets/{c4Diagram-5PPSVZJV-yrt3tSEp.js → c4Diagram-5PPSVZJV-ByqsIevu.js} +1 -1
- package/dist/web/assets/channel-DKLeFBN9.js +1 -0
- package/dist/web/assets/{chunk-2GRJ4B5K-CSdeo0L0.js → chunk-2GRJ4B5K-Dk5J1dTv.js} +1 -1
- package/dist/web/assets/{chunk-2Q5K7J3B-D4G9X5EX.js → chunk-2Q5K7J3B-D-ucNMTq.js} +1 -1
- package/dist/web/assets/{chunk-5RXB4S5H-B_OWWGvR.js → chunk-5RXB4S5H-Ca3yO8vV.js} +1 -1
- package/dist/web/assets/{chunk-5VM5RSS4-B7cnRpAw.js → chunk-5VM5RSS4-Bu0AKdlE.js} +1 -1
- package/dist/web/assets/{chunk-6Q2QTUOP-Qy2FKYGg.js → chunk-6Q2QTUOP-C0g01XOe.js} +1 -1
- package/dist/web/assets/{chunk-GF5L2VYU-BnhYHDi7.js → chunk-GF5L2VYU-B-h7MnmL.js} +1 -1
- package/dist/web/assets/{chunk-JWPE2WC7-DbeWy5Y-.js → chunk-JWPE2WC7-BgEwGAlP.js} +1 -1
- package/dist/web/assets/{chunk-KBJHAD2P-DZsGP_P8.js → chunk-KBJHAD2P-NrU17DU3.js} +1 -1
- package/dist/web/assets/{chunk-RYQCIY6F-LB_aFtph.js → chunk-RYQCIY6F-BqzMscSM.js} +1 -1
- package/dist/web/assets/{chunk-XXDRQBXY-CLWgiD5b.js → chunk-XXDRQBXY-DuAhRVgm.js} +1 -1
- package/dist/web/assets/classDiagram-JCYQIIEL-D8ek01K6.js +1 -0
- package/dist/web/assets/classDiagram-v2-OCEON4UE-D8ek01K6.js +1 -0
- package/dist/web/assets/{cose-bilkent-JH36ORCC-g-7BsXo5.js → cose-bilkent-JH36ORCC-BrGerPmF.js} +1 -1
- package/dist/web/assets/{cynefin-VYW2F7L2-BOGFr3Us.js → cynefin-VYW2F7L2-wgLYEWNl.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-MW4NZA55-CxyNa-7x.js → cynefinDiagram-MW4NZA55-VK-IHzZm.js} +1 -1
- package/dist/web/assets/{dagre-VZM6K2ZE-DfjbiFpB.js → dagre-VZM6K2ZE-DNNj1LbS.js} +1 -1
- package/dist/web/assets/{diagram-7IWD3JNH-CeiPmTYy.js → diagram-7IWD3JNH-CXXXIjt0.js} +1 -1
- package/dist/web/assets/{diagram-B4RE2ZJO-DJVn3KKP.js → diagram-B4RE2ZJO-COXtMeEv.js} +1 -1
- package/dist/web/assets/{diagram-LBJQPF4R-COyh9pF4.js → diagram-LBJQPF4R-vKGeSxFy.js} +1 -1
- package/dist/web/assets/{diagram-Q27KOJAE-QKsIhxbP.js → diagram-Q27KOJAE-C4Lsm9DM.js} +1 -1
- package/dist/web/assets/{diagram-UB23O5K3-B_gx39Gp.js → diagram-UB23O5K3-e_pZTiEr.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-BXEA7PRR-Bpdn9ysk.js → ebnfDiagram-BXEA7PRR-bAwMS4kZ.js} +1 -1
- package/dist/web/assets/{erDiagram-JOGREHBK-BnQtyQgW.js → erDiagram-JOGREHBK-zT-mXzlN.js} +1 -1
- package/dist/web/assets/{flowDiagram-UKHOOZJN-DZTP5Enz.js → flowDiagram-UKHOOZJN-BJZREKw8.js} +1 -1
- package/dist/web/assets/{ganttDiagram-PKOTCBZU-CieyMFHt.js → ganttDiagram-PKOTCBZU-MsCI5Oop.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-DS77QQ5N-DrRXUZVu.js → gitGraphDiagram-DS77QQ5N-CrTLzDOq.js} +1 -1
- package/dist/web/assets/{index-BOwn2Ixs.js → index-1jKtQqrL.js} +65 -64
- package/dist/web/assets/index-DvasuQ2p.css +1 -0
- package/dist/web/assets/{infoDiagram-6WML65LV-CYJG2_PK.js → infoDiagram-6WML65LV-CZF-68Rp.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-Bddz1oRs.js → ishikawaDiagram-WSZJBQD7-0r_z2Yor.js} +1 -1
- package/dist/web/assets/{journeyDiagram-NVQOT4AX-CzcRW94Q.js → journeyDiagram-NVQOT4AX-U8Bc6JlF.js} +1 -1
- package/dist/web/assets/{kanban-definition-27J2QSJJ-CPUQK_3h.js → kanban-definition-27J2QSJJ-BrJ15Haw.js} +1 -1
- package/dist/web/assets/{linear-D9L46R2G.js → linear-Vi7chwnv.js} +1 -1
- package/dist/web/assets/{mermaid.core-CfPzZfnE.js → mermaid.core-cpP24Vzz.js} +5 -5
- package/dist/web/assets/{mindmap-definition-FAOFIHXS-BwAV9mj2.js → mindmap-definition-FAOFIHXS-9-3-DDeb.js} +1 -1
- package/dist/web/assets/{pegDiagram-VL7TDLO6-Dr3kP1zj.js → pegDiagram-VL7TDLO6-Bl_cAnPS.js} +1 -1
- package/dist/web/assets/{pieDiagram-7S7Q4E2Y-DUs-kVVq.js → pieDiagram-7S7Q4E2Y-Bz29FvF6.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-oj0dwtC1.js → quadrantDiagram-CIZ2JOQS-BXSpkyEn.js} +1 -1
- package/dist/web/assets/{railroadDiagram-AXF67PYL-BRh-D40Z.js → railroadDiagram-AXF67PYL-DZqWxSoF.js} +1 -1
- package/dist/web/assets/{requirementDiagram-LRYGKXZP-D-dYL6Gd.js → requirementDiagram-LRYGKXZP-CWEdHghn.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-W5VNT64P-CmUWmT7X.js → sankeyDiagram-W5VNT64P-BGbJYr4X.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-SI44F4Z6-iu1LfaIM.js → sequenceDiagram-SI44F4Z6-p_wF9iET.js} +1 -1
- package/dist/web/assets/{sizeCapture-X5ZJPWSS-5ZLmVlhi.js → sizeCapture-X5ZJPWSS-w3BcIn6X.js} +1 -1
- package/dist/web/assets/{stateDiagram-OKZ733FA-Cn1wvg1w.js → stateDiagram-OKZ733FA-Bz6FXoF6.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-UEYNNEHI-DVcj7931.js +1 -0
- package/dist/web/assets/{swimlanes-SLNWSIFB-_0o7Xy3Y.js → swimlanes-SLNWSIFB-B5rAwYj-.js} +2 -2
- package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-Dv2xZebs.js +8 -0
- package/dist/web/assets/{timeline-definition-Z64GVDOM-DVcHO53x.js → timeline-definition-Z64GVDOM-gsS6Mn-_.js} +1 -1
- package/dist/web/assets/{vennDiagram-T6HMQDX7-CTGvSXQY.js → vennDiagram-T6HMQDX7-DLYvB8dm.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-T6FBY63Y-yB2tMkwc.js → wardleyDiagram-T6FBY63Y-DM2Cz5Yx.js} +1 -1
- package/dist/web/assets/{xychartDiagram-ELKLHX3M-Cj_PZuOR.js → xychartDiagram-ELKLHX3M-CuA0hj28.js} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/dist/web/assets/channel-B58CT03a.js +0 -1
- package/dist/web/assets/classDiagram-JCYQIIEL-DxP2ZBOt.js +0 -1
- package/dist/web/assets/classDiagram-v2-OCEON4UE-DxP2ZBOt.js +0 -1
- package/dist/web/assets/index-iMxQdvho.css +0 -1
- package/dist/web/assets/stateDiagram-v2-UEYNNEHI-pgkNY837.js +0 -1
- package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CauQgrWG.js +0 -8
package/dist/server.js
CHANGED
|
@@ -319,12 +319,10 @@ var init_config = __esm({
|
|
|
319
319
|
*/
|
|
320
320
|
defaultAgent: setting("DEFAULT_AGENT", "defaultAgent", "casper"),
|
|
321
321
|
/**
|
|
322
|
-
* Filesystem root
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* user's home directory) to stop authenticated users from reading system
|
|
327
|
-
* files such as /etc or SSH keys.
|
|
322
|
+
* Filesystem root the file endpoints (/api/fs/dirs, /api/fs/image) are confined to; anything
|
|
323
|
+
* resolving outside it is rejected. Defaults to /, so browsing spans everything the process
|
|
324
|
+
* can read - set a narrower path to keep authenticated users out of system files such as /etc
|
|
325
|
+
* or SSH keys.
|
|
328
326
|
*/
|
|
329
327
|
fileRoot: path5.resolve(setting("CASPER_FILE_ROOT", "fileRoot", "/")),
|
|
330
328
|
/** Directory where kiro-cli persists its own session files. */
|
|
@@ -723,24 +721,66 @@ var init_dist = __esm({
|
|
|
723
721
|
}
|
|
724
722
|
});
|
|
725
723
|
|
|
726
|
-
// server/src/
|
|
724
|
+
// server/src/session/workspaces.ts
|
|
725
|
+
import crypto3 from "node:crypto";
|
|
727
726
|
import fs7 from "node:fs";
|
|
728
|
-
import fsp from "node:fs/promises";
|
|
729
727
|
import path8 from "node:path";
|
|
728
|
+
function workspacesRoot() {
|
|
729
|
+
return path8.join(config.casperDataDir, "workspaces");
|
|
730
|
+
}
|
|
731
|
+
function workspaceDir(workspaceId) {
|
|
732
|
+
return path8.join(workspacesRoot(), workspaceId);
|
|
733
|
+
}
|
|
734
|
+
function createWorkspace() {
|
|
735
|
+
const id = crypto3.randomUUID();
|
|
736
|
+
const dir = workspaceDir(id);
|
|
737
|
+
fs7.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
738
|
+
return { id, dir };
|
|
739
|
+
}
|
|
740
|
+
var init_workspaces = __esm({
|
|
741
|
+
"server/src/session/workspaces.ts"() {
|
|
742
|
+
"use strict";
|
|
743
|
+
init_config();
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
// server/src/session/titles.ts
|
|
748
|
+
function titleFromPrompt(content) {
|
|
749
|
+
const text2 = content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
750
|
+
const words = stripAttachmentsLine(text2).replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim();
|
|
751
|
+
if (!words) return "";
|
|
752
|
+
if (words.length <= MAX_TITLE) return words.replace(/[.,;:!?]+$/, "");
|
|
753
|
+
const cut = words.slice(0, MAX_TITLE);
|
|
754
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
755
|
+
return `${(lastSpace > MAX_TITLE / 2 ? cut.slice(0, lastSpace) : cut).replace(/[.,;:!?]+$/, "")}\u2026`;
|
|
756
|
+
}
|
|
757
|
+
var MAX_TITLE;
|
|
758
|
+
var init_titles = __esm({
|
|
759
|
+
"server/src/session/titles.ts"() {
|
|
760
|
+
"use strict";
|
|
761
|
+
init_dist();
|
|
762
|
+
MAX_TITLE = 60;
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
// server/src/util/paths.ts
|
|
767
|
+
import fs8 from "node:fs";
|
|
768
|
+
import fsp from "node:fs/promises";
|
|
769
|
+
import path9 from "node:path";
|
|
730
770
|
function isWithinRoot(root, target) {
|
|
731
|
-
const resolved =
|
|
732
|
-
if (root ===
|
|
733
|
-
return resolved === root || resolved.startsWith(root +
|
|
771
|
+
const resolved = path9.resolve(target);
|
|
772
|
+
if (root === path9.sep) return true;
|
|
773
|
+
return resolved === root || resolved.startsWith(root + path9.sep);
|
|
734
774
|
}
|
|
735
775
|
function confineToRoot(root, input) {
|
|
736
|
-
const resolved =
|
|
776
|
+
const resolved = path9.resolve(root, input);
|
|
737
777
|
return isWithinRoot(root, resolved) ? resolved : null;
|
|
738
778
|
}
|
|
739
779
|
function resolveRealRoot(root) {
|
|
740
780
|
if (realRootCache && realRootCache.root === root) return realRootCache.real;
|
|
741
781
|
let real;
|
|
742
782
|
try {
|
|
743
|
-
real =
|
|
783
|
+
real = fs8.realpathSync(root);
|
|
744
784
|
} catch {
|
|
745
785
|
real = root;
|
|
746
786
|
}
|
|
@@ -1221,8 +1261,8 @@ var init_TurnState = __esm({
|
|
|
1221
1261
|
});
|
|
1222
1262
|
|
|
1223
1263
|
// server/src/session/kiroFiles.ts
|
|
1224
|
-
import
|
|
1225
|
-
import
|
|
1264
|
+
import fs9 from "node:fs/promises";
|
|
1265
|
+
import path10 from "node:path";
|
|
1226
1266
|
function isContentBlock(v) {
|
|
1227
1267
|
return isRecord(v) && typeof v.kind === "string";
|
|
1228
1268
|
}
|
|
@@ -1274,7 +1314,7 @@ function summarize(j) {
|
|
|
1274
1314
|
async function listPersistedSessions(log) {
|
|
1275
1315
|
let files;
|
|
1276
1316
|
try {
|
|
1277
|
-
files = await
|
|
1317
|
+
files = await fs9.readdir(config.kiroSessionsDir);
|
|
1278
1318
|
} catch {
|
|
1279
1319
|
return [];
|
|
1280
1320
|
}
|
|
@@ -1283,7 +1323,7 @@ async function listPersistedSessions(log) {
|
|
|
1283
1323
|
await Promise.all(
|
|
1284
1324
|
jsonFiles.map(async (f) => {
|
|
1285
1325
|
try {
|
|
1286
|
-
const raw = await
|
|
1326
|
+
const raw = await fs9.readFile(path10.join(config.kiroSessionsDir, f), "utf8");
|
|
1287
1327
|
summaries.push(summarize(JSON.parse(raw)));
|
|
1288
1328
|
} catch (err) {
|
|
1289
1329
|
log.debug({ err, f }, "kiroFiles: skipping unreadable session file");
|
|
@@ -1296,18 +1336,18 @@ async function listPersistedSessions(log) {
|
|
|
1296
1336
|
async function deletePersistedSession(sessionId) {
|
|
1297
1337
|
if (!isValidSessionId(sessionId)) return;
|
|
1298
1338
|
const targets = [
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1339
|
+
path10.join(config.kiroSessionsDir, `${sessionId}.json`),
|
|
1340
|
+
path10.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
|
|
1341
|
+
path10.join(config.kiroSessionsDir, `${sessionId}.history`),
|
|
1342
|
+
path10.join(config.kiroSessionsDir, sessionId)
|
|
1303
1343
|
];
|
|
1304
|
-
await Promise.all(targets.map((f) =>
|
|
1344
|
+
await Promise.all(targets.map((f) => fs9.rm(f, { recursive: true, force: true })));
|
|
1305
1345
|
}
|
|
1306
1346
|
async function readPersistedSession(sessionId) {
|
|
1307
1347
|
if (!isValidSessionId(sessionId)) return null;
|
|
1308
1348
|
try {
|
|
1309
|
-
const raw = await
|
|
1310
|
-
|
|
1349
|
+
const raw = await fs9.readFile(
|
|
1350
|
+
path10.join(config.kiroSessionsDir, `${sessionId}.json`),
|
|
1311
1351
|
"utf8"
|
|
1312
1352
|
);
|
|
1313
1353
|
return summarize(JSON.parse(raw));
|
|
@@ -1319,8 +1359,8 @@ async function hydrateTranscript(sessionId) {
|
|
|
1319
1359
|
if (!isValidSessionId(sessionId)) return [];
|
|
1320
1360
|
let raw;
|
|
1321
1361
|
try {
|
|
1322
|
-
raw = await
|
|
1323
|
-
|
|
1362
|
+
raw = await fs9.readFile(
|
|
1363
|
+
path10.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
|
|
1324
1364
|
"utf8"
|
|
1325
1365
|
);
|
|
1326
1366
|
} catch {
|
|
@@ -1435,17 +1475,17 @@ var init_sessionStore = __esm({
|
|
|
1435
1475
|
});
|
|
1436
1476
|
|
|
1437
1477
|
// server/src/session/SessionManager.ts
|
|
1438
|
-
import
|
|
1439
|
-
import
|
|
1478
|
+
import fs10 from "node:fs";
|
|
1479
|
+
import path11 from "node:path";
|
|
1440
1480
|
function resolveCwd(input) {
|
|
1441
1481
|
const raw = input?.trim();
|
|
1442
|
-
const abs = raw ?
|
|
1482
|
+
const abs = raw ? path11.resolve(config.defaultCwd, raw) : config.defaultCwd;
|
|
1443
1483
|
if (!isWithinRoot(config.fileRoot, abs)) {
|
|
1444
1484
|
throw new Error(`Working directory is outside the allowed root: ${abs}`);
|
|
1445
1485
|
}
|
|
1446
1486
|
let stat;
|
|
1447
1487
|
try {
|
|
1448
|
-
stat =
|
|
1488
|
+
stat = fs10.statSync(abs);
|
|
1449
1489
|
} catch {
|
|
1450
1490
|
stat = void 0;
|
|
1451
1491
|
}
|
|
@@ -1453,7 +1493,7 @@ function resolveCwd(input) {
|
|
|
1453
1493
|
throw new Error(`Working directory path is a file, not a directory: ${abs}`);
|
|
1454
1494
|
}
|
|
1455
1495
|
if (!stat) {
|
|
1456
|
-
|
|
1496
|
+
fs10.mkdirSync(abs, { recursive: true });
|
|
1457
1497
|
}
|
|
1458
1498
|
return abs;
|
|
1459
1499
|
}
|
|
@@ -1485,6 +1525,8 @@ var init_SessionManager = __esm({
|
|
|
1485
1525
|
"use strict";
|
|
1486
1526
|
init_dist();
|
|
1487
1527
|
init_config();
|
|
1528
|
+
init_workspaces();
|
|
1529
|
+
init_titles();
|
|
1488
1530
|
init_paths2();
|
|
1489
1531
|
init_KiroProcess();
|
|
1490
1532
|
init_EventStore();
|
|
@@ -1551,17 +1593,10 @@ var init_SessionManager = __esm({
|
|
|
1551
1593
|
if (s) s.title = title.trim() || s.title;
|
|
1552
1594
|
}
|
|
1553
1595
|
/**
|
|
1554
|
-
* Re-point a session at a different working directory
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1557
|
-
*
|
|
1558
|
-
* The target is validated and created exactly like a new session's cwd, so a
|
|
1559
|
-
* folder is only created on this explicit action - never silently on resume.
|
|
1560
|
-
* Any live kiro process was spawned with the old cwd, so it's disposed here;
|
|
1561
|
-
* the next turn respawns in the new directory with the transcript intact
|
|
1562
|
-
* (kiro reloads the session from its own file).
|
|
1563
|
-
*
|
|
1564
|
-
* Returns the resolved absolute path.
|
|
1596
|
+
* Re-point a session at a different working directory, for when the original was moved
|
|
1597
|
+
* or deleted. Validates and creates the target exactly like a new session's cwd, so a
|
|
1598
|
+
* folder is only created on this explicit action. Any live process was spawned with the
|
|
1599
|
+
* old cwd, so it is disposed and the next turn respawns in the new one, transcript intact.
|
|
1565
1600
|
*/
|
|
1566
1601
|
async setSessionCwd(sessionId, input) {
|
|
1567
1602
|
const resolved = resolveCwd(input);
|
|
@@ -1709,7 +1744,7 @@ var init_SessionManager = __esm({
|
|
|
1709
1744
|
// -------------------------------------------------------------------------
|
|
1710
1745
|
/** Create a new session. Spawns immediately so we get a real kiro sessionId. */
|
|
1711
1746
|
async createSession(opts) {
|
|
1712
|
-
const cwd = resolveCwd(opts.cwd);
|
|
1747
|
+
const cwd = opts.freshWorkspace ? createWorkspace().dir : resolveCwd(opts.cwd);
|
|
1713
1748
|
const tempId = `pending-${Date.now()}-${Math.floor(this.sessions.size)}`;
|
|
1714
1749
|
const store = new EventStore(tempId);
|
|
1715
1750
|
const s = new Session(tempId, store, cwd);
|
|
@@ -1723,7 +1758,7 @@ var init_SessionManager = __esm({
|
|
|
1723
1758
|
this.evict(s.sessionId);
|
|
1724
1759
|
throw err;
|
|
1725
1760
|
}
|
|
1726
|
-
const folder =
|
|
1761
|
+
const folder = opts.freshWorkspace ? "" : path11.basename(s.cwd);
|
|
1727
1762
|
if (folder) {
|
|
1728
1763
|
this.store.setTitle(s.sessionId, folder);
|
|
1729
1764
|
s.title = folder;
|
|
@@ -1740,6 +1775,13 @@ var init_SessionManager = __esm({
|
|
|
1740
1775
|
s.running = true;
|
|
1741
1776
|
s.lastActivity = Date.now();
|
|
1742
1777
|
s.record({ kind: "turn_started", prompt: content });
|
|
1778
|
+
if (!this.store.getTitle(s.sessionId)) {
|
|
1779
|
+
const title = titleFromPrompt(content);
|
|
1780
|
+
if (title) {
|
|
1781
|
+
this.store.setTitle(s.sessionId, title);
|
|
1782
|
+
s.title = title;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1743
1785
|
proc.prompt({ sessionId: s.sessionId, prompt: content }).then((res) => s.record({ kind: "turn_ended", stopReason: res.stopReason })).catch((err) => {
|
|
1744
1786
|
this.log.error({ err, sessionId: s.sessionId }, "prompt turn failed");
|
|
1745
1787
|
const tail = proc.stderrTail();
|
|
@@ -1873,12 +1915,10 @@ ${tail}` : err.message;
|
|
|
1873
1915
|
};
|
|
1874
1916
|
}
|
|
1875
1917
|
/**
|
|
1876
|
-
* The cursor a reconnecting client should start from. Normally the store
|
|
1877
|
-
*
|
|
1878
|
-
*
|
|
1879
|
-
*
|
|
1880
|
-
* turn_started so the WS replays the whole in-flight turn. Guarded against
|
|
1881
|
-
* duplication in case kiro ever persists the prompt at turn start.
|
|
1918
|
+
* The cursor a reconnecting client should start from. Normally the store head, but kiro writes
|
|
1919
|
+
* a turn to its jsonl only once the turn completes, so a hydrated transcript is missing one in
|
|
1920
|
+
* flight. Rewind to just before its turn_started and let the WS replay the whole turn. Guarded
|
|
1921
|
+
* against duplication in case kiro ever persists the prompt at turn start.
|
|
1882
1922
|
*/
|
|
1883
1923
|
replayHead(s, transcript) {
|
|
1884
1924
|
const head = s.store.head();
|
|
@@ -1983,13 +2023,13 @@ var init_rateLimit = __esm({
|
|
|
1983
2023
|
});
|
|
1984
2024
|
|
|
1985
2025
|
// server/src/routes/auth.ts
|
|
1986
|
-
import
|
|
2026
|
+
import crypto4 from "node:crypto";
|
|
1987
2027
|
import fastifyCookie from "@fastify/cookie";
|
|
1988
2028
|
function secretMatches(supplied, expected) {
|
|
1989
2029
|
if (typeof supplied !== "string") return false;
|
|
1990
|
-
const a =
|
|
1991
|
-
const b =
|
|
1992
|
-
return
|
|
2030
|
+
const a = crypto4.createHash("sha256").update(supplied).digest();
|
|
2031
|
+
const b = crypto4.createHash("sha256").update(expected).digest();
|
|
2032
|
+
return crypto4.timingSafeEqual(a, b);
|
|
1993
2033
|
}
|
|
1994
2034
|
function extractToken(req) {
|
|
1995
2035
|
const auth = req.headers["authorization"];
|
|
@@ -2193,9 +2233,9 @@ var init_agents2 = __esm({
|
|
|
2193
2233
|
});
|
|
2194
2234
|
|
|
2195
2235
|
// server/src/routes/fs.ts
|
|
2196
|
-
import
|
|
2236
|
+
import fs11 from "node:fs/promises";
|
|
2197
2237
|
import { createReadStream } from "node:fs";
|
|
2198
|
-
import
|
|
2238
|
+
import path12 from "node:path";
|
|
2199
2239
|
function confinedPath(input) {
|
|
2200
2240
|
return confineToRoot(config.fileRoot, input) ?? confineToRoot(config.casperDataDir, input);
|
|
2201
2241
|
}
|
|
@@ -2206,10 +2246,10 @@ function registerFsRoutes(app) {
|
|
|
2206
2246
|
const input = (req.query.path ?? "").trim();
|
|
2207
2247
|
const base = config.defaultCwd;
|
|
2208
2248
|
const endsWithSep = input.endsWith("/");
|
|
2209
|
-
const resolved = input ?
|
|
2210
|
-
const dir = endsWithSep || !input ? resolved :
|
|
2211
|
-
const prefix = endsWithSep || !input ? "" :
|
|
2212
|
-
const targetKind = await
|
|
2249
|
+
const resolved = input ? path12.resolve(base, input) : base;
|
|
2250
|
+
const dir = endsWithSep || !input ? resolved : path12.dirname(resolved);
|
|
2251
|
+
const prefix = endsWithSep || !input ? "" : path12.basename(resolved);
|
|
2252
|
+
const targetKind = await fs11.stat(resolved).then((s) => s.isDirectory() ? "directory" : "file").catch(() => "missing");
|
|
2213
2253
|
if (confinedPath(dir) === null) {
|
|
2214
2254
|
reply.code(403);
|
|
2215
2255
|
return { error: "Path outside allowed root" };
|
|
@@ -2220,23 +2260,23 @@ function registerFsRoutes(app) {
|
|
|
2220
2260
|
}
|
|
2221
2261
|
let entries = [];
|
|
2222
2262
|
try {
|
|
2223
|
-
const dirents = await
|
|
2263
|
+
const dirents = await fs11.readdir(realDir, { withFileTypes: true });
|
|
2224
2264
|
const candidates = dirents.filter((d) => !d.name.startsWith("."));
|
|
2225
2265
|
const checks2 = await Promise.all(
|
|
2226
2266
|
candidates.map(async (d) => {
|
|
2227
2267
|
if (d.isDirectory()) return d.name;
|
|
2228
2268
|
if (!d.isSymbolicLink()) return null;
|
|
2229
|
-
const full =
|
|
2269
|
+
const full = path12.join(realDir, d.name);
|
|
2230
2270
|
const real = await realConfineToRoot(config.fileRoot, full);
|
|
2231
2271
|
if (!real) return null;
|
|
2232
2272
|
try {
|
|
2233
|
-
return (await
|
|
2273
|
+
return (await fs11.stat(real)).isDirectory() ? d.name : null;
|
|
2234
2274
|
} catch {
|
|
2235
2275
|
return null;
|
|
2236
2276
|
}
|
|
2237
2277
|
})
|
|
2238
2278
|
);
|
|
2239
|
-
entries = checks2.filter((name) => name !== null).filter((name) => name.toLowerCase().startsWith(prefix.toLowerCase())).sort((a, b) => a.localeCompare(b)).slice(0, 20).map((name) =>
|
|
2279
|
+
entries = checks2.filter((name) => name !== null).filter((name) => name.toLowerCase().startsWith(prefix.toLowerCase())).sort((a, b) => a.localeCompare(b)).slice(0, 20).map((name) => path12.join(dir, name));
|
|
2240
2280
|
} catch {
|
|
2241
2281
|
entries = [];
|
|
2242
2282
|
}
|
|
@@ -2251,7 +2291,7 @@ function registerFsRoutes(app) {
|
|
|
2251
2291
|
reply.code(400);
|
|
2252
2292
|
return { error: "path parameter is required" };
|
|
2253
2293
|
}
|
|
2254
|
-
if (!
|
|
2294
|
+
if (!path12.isAbsolute(filePath)) {
|
|
2255
2295
|
reply.code(400);
|
|
2256
2296
|
return { error: "path must be absolute" };
|
|
2257
2297
|
}
|
|
@@ -2260,7 +2300,7 @@ function registerFsRoutes(app) {
|
|
|
2260
2300
|
reply.code(403);
|
|
2261
2301
|
return { error: "Path outside allowed root" };
|
|
2262
2302
|
}
|
|
2263
|
-
const ext =
|
|
2303
|
+
const ext = path12.extname(resolved).toLowerCase();
|
|
2264
2304
|
const mime = IMAGE_MIMES[ext];
|
|
2265
2305
|
if (!mime) {
|
|
2266
2306
|
reply.code(400);
|
|
@@ -2273,7 +2313,7 @@ function registerFsRoutes(app) {
|
|
|
2273
2313
|
}
|
|
2274
2314
|
let stat;
|
|
2275
2315
|
try {
|
|
2276
|
-
stat = await
|
|
2316
|
+
stat = await fs11.stat(real);
|
|
2277
2317
|
} catch {
|
|
2278
2318
|
reply.code(404);
|
|
2279
2319
|
return { error: "File not found" };
|
|
@@ -2332,7 +2372,8 @@ function registerSessionRoutes(app, manager) {
|
|
|
2332
2372
|
return await manager.createSession({
|
|
2333
2373
|
cwd: body.cwd,
|
|
2334
2374
|
agentId: body.agentId,
|
|
2335
|
-
modelId: body.modelId
|
|
2375
|
+
modelId: body.modelId,
|
|
2376
|
+
freshWorkspace: body.freshWorkspace
|
|
2336
2377
|
});
|
|
2337
2378
|
} catch (err) {
|
|
2338
2379
|
reply.code(400);
|
|
@@ -2429,7 +2470,7 @@ var init_sessions = __esm({
|
|
|
2429
2470
|
});
|
|
2430
2471
|
|
|
2431
2472
|
// server/src/util/filekind.ts
|
|
2432
|
-
import
|
|
2473
|
+
import path13 from "node:path";
|
|
2433
2474
|
function mimeForExt(ext) {
|
|
2434
2475
|
return MIME_MAP[ext.toLowerCase()] ?? "application/octet-stream";
|
|
2435
2476
|
}
|
|
@@ -2449,7 +2490,7 @@ function looksBinary(buf) {
|
|
|
2449
2490
|
return control / buf.length > 0.3;
|
|
2450
2491
|
}
|
|
2451
2492
|
function classifyKind(name) {
|
|
2452
|
-
const ext =
|
|
2493
|
+
const ext = path13.extname(name).toLowerCase();
|
|
2453
2494
|
if (ext in IMAGE_EXTS2) return "image";
|
|
2454
2495
|
if (TEXT_EXTS.has(ext)) return "text";
|
|
2455
2496
|
return "binary";
|
|
@@ -2559,9 +2600,9 @@ var init_filekind = __esm({
|
|
|
2559
2600
|
});
|
|
2560
2601
|
|
|
2561
2602
|
// server/src/routes/workspace.ts
|
|
2562
|
-
import
|
|
2603
|
+
import fs12 from "node:fs/promises";
|
|
2563
2604
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
2564
|
-
import
|
|
2605
|
+
import path14 from "node:path";
|
|
2565
2606
|
function tooLargeForPreview(size, maxBytes) {
|
|
2566
2607
|
return {
|
|
2567
2608
|
error: `File too large for preview (${(size / 1024 / 1024).toFixed(1)} MB, max ${maxBytes / 1024 / 1024} MB)`
|
|
@@ -2606,7 +2647,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2606
2647
|
}
|
|
2607
2648
|
const workspaceMissing = async () => {
|
|
2608
2649
|
try {
|
|
2609
|
-
return !(await
|
|
2650
|
+
return !(await fs12.stat(cwd)).isDirectory();
|
|
2610
2651
|
} catch {
|
|
2611
2652
|
return true;
|
|
2612
2653
|
}
|
|
@@ -2621,7 +2662,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2621
2662
|
}
|
|
2622
2663
|
let dirents;
|
|
2623
2664
|
try {
|
|
2624
|
-
dirents = await
|
|
2665
|
+
dirents = await fs12.readdir(realTarget, { withFileTypes: true, encoding: "utf8" });
|
|
2625
2666
|
} catch {
|
|
2626
2667
|
return notFound();
|
|
2627
2668
|
}
|
|
@@ -2629,14 +2670,14 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2629
2670
|
for (const d of dirents) {
|
|
2630
2671
|
const name = d.name;
|
|
2631
2672
|
const entryRelative = relative ? `${relative}/${name}` : name;
|
|
2632
|
-
const entryAbsolute =
|
|
2673
|
+
const entryAbsolute = path14.join(realTarget, name);
|
|
2633
2674
|
let kind = d.isDirectory() ? "directory" : d.isFile() ? "file" : null;
|
|
2634
2675
|
let statTarget = entryAbsolute;
|
|
2635
2676
|
if (kind === null && d.isSymbolicLink()) {
|
|
2636
2677
|
const real = await realConfineToRoot(config.fileRoot, entryAbsolute);
|
|
2637
2678
|
if (!real) continue;
|
|
2638
2679
|
try {
|
|
2639
|
-
const st = await
|
|
2680
|
+
const st = await fs12.stat(real);
|
|
2640
2681
|
kind = st.isDirectory() ? "directory" : st.isFile() ? "file" : null;
|
|
2641
2682
|
statTarget = real;
|
|
2642
2683
|
} catch {
|
|
@@ -2648,7 +2689,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2648
2689
|
entries.push({ name, path: entryRelative, type: "directory" });
|
|
2649
2690
|
} else {
|
|
2650
2691
|
try {
|
|
2651
|
-
const stat = await
|
|
2692
|
+
const stat = await fs12.stat(statTarget);
|
|
2652
2693
|
entries.push({
|
|
2653
2694
|
name,
|
|
2654
2695
|
path: entryRelative,
|
|
@@ -2695,7 +2736,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2695
2736
|
}
|
|
2696
2737
|
let stat;
|
|
2697
2738
|
try {
|
|
2698
|
-
stat = await
|
|
2739
|
+
stat = await fs12.stat(realTarget);
|
|
2699
2740
|
} catch {
|
|
2700
2741
|
reply.code(404);
|
|
2701
2742
|
return { error: "File not found" };
|
|
@@ -2708,8 +2749,8 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2708
2749
|
reply.code(413);
|
|
2709
2750
|
return { error: `File too large (${(stat.size / 1024 / 1024).toFixed(1)} MB, max 100 MB)` };
|
|
2710
2751
|
}
|
|
2711
|
-
const ext =
|
|
2712
|
-
const filename =
|
|
2752
|
+
const ext = path14.extname(realTarget);
|
|
2753
|
+
const filename = path14.basename(realTarget);
|
|
2713
2754
|
const asciiName = filename.replace(/[^\w.\-]/g, "_");
|
|
2714
2755
|
reply.header("Content-Type", mimeForExt(ext));
|
|
2715
2756
|
reply.header(
|
|
@@ -2747,7 +2788,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2747
2788
|
}
|
|
2748
2789
|
let stat;
|
|
2749
2790
|
try {
|
|
2750
|
-
stat = await
|
|
2791
|
+
stat = await fs12.stat(realTarget);
|
|
2751
2792
|
} catch {
|
|
2752
2793
|
reply.code(404);
|
|
2753
2794
|
return { error: "File not found" };
|
|
@@ -2756,7 +2797,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2756
2797
|
reply.code(400);
|
|
2757
2798
|
return { error: "Path is not a file" };
|
|
2758
2799
|
}
|
|
2759
|
-
const ext =
|
|
2800
|
+
const ext = path14.extname(realTarget).toLowerCase();
|
|
2760
2801
|
const mime = mimeForExt(ext);
|
|
2761
2802
|
const isImage = mime.startsWith("image/");
|
|
2762
2803
|
const isPdf = mime === "application/pdf";
|
|
@@ -2801,7 +2842,7 @@ function registerWorkspaceRoutes(app, manager) {
|
|
|
2801
2842
|
if (kind === "binary") {
|
|
2802
2843
|
let fh;
|
|
2803
2844
|
try {
|
|
2804
|
-
fh = await
|
|
2845
|
+
fh = await fs12.open(realTarget, "r");
|
|
2805
2846
|
const buf = Buffer.alloc(Math.min(HEXDUMP_BYTES, stat.size));
|
|
2806
2847
|
const { bytesRead } = await fh.read(buf, 0, buf.length, 0);
|
|
2807
2848
|
const head = buf.subarray(0, bytesRead);
|
|
@@ -2851,36 +2892,36 @@ var init_workspace = __esm({
|
|
|
2851
2892
|
|
|
2852
2893
|
// server/src/routes/uploads.ts
|
|
2853
2894
|
import { createReadStream as createReadStream3, createWriteStream } from "node:fs";
|
|
2854
|
-
import
|
|
2855
|
-
import
|
|
2856
|
-
import
|
|
2895
|
+
import fs13 from "node:fs/promises";
|
|
2896
|
+
import path15 from "node:path";
|
|
2897
|
+
import crypto5 from "node:crypto";
|
|
2857
2898
|
import { execFile as execFile3 } from "node:child_process";
|
|
2858
2899
|
import { pipeline } from "node:stream/promises";
|
|
2859
2900
|
function uploadDirFor(sessionId) {
|
|
2860
|
-
return
|
|
2901
|
+
return path15.join(config.casperDataDir, "sessions", sessionId, "uploads");
|
|
2861
2902
|
}
|
|
2862
2903
|
function sanitizeName(raw) {
|
|
2863
|
-
const base =
|
|
2904
|
+
const base = path15.basename(raw).replace(/[^\w.\- ]/g, "_").trim();
|
|
2864
2905
|
if (!base || base === "." || base === "..") return `upload-${Date.now()}`;
|
|
2865
2906
|
return base.replace(/^\.+/, "") || `upload-${Date.now()}`;
|
|
2866
2907
|
}
|
|
2867
2908
|
async function uniquePath(dir, name) {
|
|
2868
|
-
const ext =
|
|
2909
|
+
const ext = path15.extname(name);
|
|
2869
2910
|
const stem = name.slice(0, name.length - ext.length);
|
|
2870
2911
|
let candidate = name;
|
|
2871
2912
|
let n = 1;
|
|
2872
2913
|
while (true) {
|
|
2873
2914
|
try {
|
|
2874
|
-
await
|
|
2915
|
+
await fs13.access(path15.join(dir, candidate));
|
|
2875
2916
|
candidate = `${stem} (${n++})${ext}`;
|
|
2876
2917
|
} catch {
|
|
2877
|
-
return
|
|
2918
|
+
return path15.join(dir, candidate);
|
|
2878
2919
|
}
|
|
2879
2920
|
}
|
|
2880
2921
|
}
|
|
2881
2922
|
function sha256File(absPath) {
|
|
2882
2923
|
return new Promise((resolve, reject) => {
|
|
2883
|
-
const hash =
|
|
2924
|
+
const hash = crypto5.createHash("sha256");
|
|
2884
2925
|
createReadStream3(absPath).on("data", (d) => hash.update(d)).on("end", () => resolve(hash.digest("hex"))).on("error", reject);
|
|
2885
2926
|
});
|
|
2886
2927
|
}
|
|
@@ -2894,7 +2935,7 @@ function fileType(absPath) {
|
|
|
2894
2935
|
async function sampleStrings(absPath, limit = 40) {
|
|
2895
2936
|
let fh;
|
|
2896
2937
|
try {
|
|
2897
|
-
fh = await
|
|
2938
|
+
fh = await fs13.open(absPath, "r");
|
|
2898
2939
|
const buf = Buffer.alloc(STRINGS_SCAN_BYTES);
|
|
2899
2940
|
const { bytesRead } = await fh.read(buf, 0, STRINGS_SCAN_BYTES, 0);
|
|
2900
2941
|
const out = [];
|
|
@@ -2932,7 +2973,7 @@ function registerUploadRoutes(app, manager) {
|
|
|
2932
2973
|
return { error: "Invalid session id" };
|
|
2933
2974
|
}
|
|
2934
2975
|
const uploadDir = uploadDirFor(req.params.id);
|
|
2935
|
-
await
|
|
2976
|
+
await fs13.mkdir(uploadDir, { recursive: true, mode: 448 });
|
|
2936
2977
|
const results = [];
|
|
2937
2978
|
const parts = req.files();
|
|
2938
2979
|
for await (const part of parts) {
|
|
@@ -2946,17 +2987,17 @@ function registerUploadRoutes(app, manager) {
|
|
|
2946
2987
|
return { error: `Failed to store ${name}` };
|
|
2947
2988
|
}
|
|
2948
2989
|
if (part.file.truncated) {
|
|
2949
|
-
await
|
|
2990
|
+
await fs13.rm(dest, { force: true });
|
|
2950
2991
|
reply.code(413);
|
|
2951
2992
|
return {
|
|
2952
2993
|
error: `${name} exceeds the max upload size (${Math.round(config.maxUploadBytes / 1024 / 1024)} MB)`
|
|
2953
2994
|
};
|
|
2954
2995
|
}
|
|
2955
|
-
const stat = await
|
|
2956
|
-
const ext =
|
|
2996
|
+
const stat = await fs13.stat(dest);
|
|
2997
|
+
const ext = path15.extname(dest);
|
|
2957
2998
|
const kind = classifyKind(dest);
|
|
2958
2999
|
const uploaded = {
|
|
2959
|
-
name:
|
|
3000
|
+
name: path15.basename(dest),
|
|
2960
3001
|
// Absolute, because the file sits outside the session's workspace: a
|
|
2961
3002
|
// relative path would resolve against the wrong root for both the agent
|
|
2962
3003
|
// and the image endpoint.
|
|
@@ -3103,7 +3144,7 @@ var init_dispatch = __esm({
|
|
|
3103
3144
|
});
|
|
3104
3145
|
|
|
3105
3146
|
// server/src/ws/dirWatchers.ts
|
|
3106
|
-
import
|
|
3147
|
+
import fs14 from "node:fs";
|
|
3107
3148
|
function diffWatchSet(current, next) {
|
|
3108
3149
|
const have = new Set(current);
|
|
3109
3150
|
const want = new Set(next.slice(0, MAX_WATCHES));
|
|
@@ -3127,7 +3168,7 @@ function createDirWatchers(opts) {
|
|
|
3127
3168
|
const target = await opts.resolve(relative);
|
|
3128
3169
|
if (!target || closed) return;
|
|
3129
3170
|
try {
|
|
3130
|
-
const watcher =
|
|
3171
|
+
const watcher = fs14.watch(target, { persistent: false }, () => {
|
|
3131
3172
|
const existing = timers.get(relative);
|
|
3132
3173
|
if (existing) clearTimeout(existing);
|
|
3133
3174
|
timers.set(
|
|
@@ -3193,7 +3234,7 @@ function registerWsGateway(app, manager) {
|
|
|
3193
3234
|
return null;
|
|
3194
3235
|
}
|
|
3195
3236
|
},
|
|
3196
|
-
onChange: (
|
|
3237
|
+
onChange: (path18) => send(socket, { type: "fs_changed", path: path18 })
|
|
3197
3238
|
});
|
|
3198
3239
|
let alive = true;
|
|
3199
3240
|
let ready = false;
|
|
@@ -3278,7 +3319,7 @@ var init_gateway = __esm({
|
|
|
3278
3319
|
});
|
|
3279
3320
|
|
|
3280
3321
|
// server/src/app.ts
|
|
3281
|
-
import
|
|
3322
|
+
import fs15 from "node:fs";
|
|
3282
3323
|
import Fastify from "fastify";
|
|
3283
3324
|
import cors from "@fastify/cors";
|
|
3284
3325
|
import websocket from "@fastify/websocket";
|
|
@@ -3316,14 +3357,14 @@ async function buildApp() {
|
|
|
3316
3357
|
registerWorkspaceRoutes(app, manager);
|
|
3317
3358
|
registerUploadRoutes(app, manager);
|
|
3318
3359
|
registerWsGateway(app, manager);
|
|
3319
|
-
if (
|
|
3360
|
+
if (fs15.existsSync(config.webDist)) {
|
|
3320
3361
|
await app.register(fastifyStatic, {
|
|
3321
3362
|
root: config.webDist
|
|
3322
3363
|
});
|
|
3323
3364
|
app.setNotFoundHandler((req, reply) => {
|
|
3324
|
-
const
|
|
3325
|
-
const looksLikeAsset =
|
|
3326
|
-
if (
|
|
3365
|
+
const path18 = req.url.split("?")[0] ?? "";
|
|
3366
|
+
const looksLikeAsset = path18.startsWith("/assets/") || /\.[a-zA-Z0-9]+$/.test(path18);
|
|
3367
|
+
if (path18.startsWith("/api/") || path18.startsWith("/ws") || looksLikeAsset) {
|
|
3327
3368
|
reply.code(404).send({ error: "Not found" });
|
|
3328
3369
|
return;
|
|
3329
3370
|
}
|
|
@@ -3397,15 +3438,15 @@ __export(doctor_exports, {
|
|
|
3397
3438
|
mcpWiring: () => mcpWiring
|
|
3398
3439
|
});
|
|
3399
3440
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3400
|
-
import
|
|
3401
|
-
import
|
|
3441
|
+
import fs16 from "node:fs";
|
|
3442
|
+
import path16 from "node:path";
|
|
3402
3443
|
function which(bin) {
|
|
3403
|
-
if (bin.includes("/")) return
|
|
3404
|
-
for (const dir of (process.env.PATH ?? "").split(
|
|
3444
|
+
if (bin.includes("/")) return fs16.existsSync(bin) ? bin : void 0;
|
|
3445
|
+
for (const dir of (process.env.PATH ?? "").split(path16.delimiter)) {
|
|
3405
3446
|
if (dir === "") continue;
|
|
3406
|
-
const candidate =
|
|
3447
|
+
const candidate = path16.join(dir, bin);
|
|
3407
3448
|
try {
|
|
3408
|
-
|
|
3449
|
+
fs16.accessSync(candidate, fs16.constants.X_OK);
|
|
3409
3450
|
return candidate;
|
|
3410
3451
|
} catch {
|
|
3411
3452
|
}
|
|
@@ -3429,7 +3470,7 @@ function mcpWiring(agentJson, resolve) {
|
|
|
3429
3470
|
return { ok: false, detail: `${command || "(no command)"} not found - widgets are unavailable` };
|
|
3430
3471
|
}
|
|
3431
3472
|
const script = args.find((a) => a.endsWith(".js"));
|
|
3432
|
-
if (script && !
|
|
3473
|
+
if (script && !fs16.existsSync(script)) {
|
|
3433
3474
|
return { ok: false, detail: `${script} is gone - delete the agent file and restart to rewrite it` };
|
|
3434
3475
|
}
|
|
3435
3476
|
return { ok: true, detail: script ?? `${command} ${args.join(" ")}` };
|
|
@@ -3461,7 +3502,7 @@ function checks() {
|
|
|
3461
3502
|
const settings = readSettings(config.configFile);
|
|
3462
3503
|
const hasToken = typeof settings.token === "string" && settings.token !== "";
|
|
3463
3504
|
out.push(
|
|
3464
|
-
|
|
3505
|
+
fs16.existsSync(config.configFile) ? {
|
|
3465
3506
|
ok: hasToken,
|
|
3466
3507
|
name: "settings",
|
|
3467
3508
|
detail: hasToken ? `${config.configFile} (token set)` : `${config.configFile} exists but has no token - auth is DISABLED`
|
|
@@ -3471,8 +3512,8 @@ function checks() {
|
|
|
3471
3512
|
detail: `${config.configFile} not found; a token is generated on first run`
|
|
3472
3513
|
}
|
|
3473
3514
|
);
|
|
3474
|
-
if (
|
|
3475
|
-
const mode =
|
|
3515
|
+
if (fs16.existsSync(config.configFile)) {
|
|
3516
|
+
const mode = fs16.statSync(config.configFile).mode & 511;
|
|
3476
3517
|
out.push({
|
|
3477
3518
|
ok: mode === 384,
|
|
3478
3519
|
name: "settings mode",
|
|
@@ -3480,10 +3521,10 @@ function checks() {
|
|
|
3480
3521
|
});
|
|
3481
3522
|
}
|
|
3482
3523
|
try {
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
const db2 =
|
|
3486
|
-
const size =
|
|
3524
|
+
fs16.mkdirSync(config.casperDataDir, { recursive: true });
|
|
3525
|
+
fs16.accessSync(config.casperDataDir, fs16.constants.W_OK);
|
|
3526
|
+
const db2 = path16.join(config.casperDataDir, "casper.db");
|
|
3527
|
+
const size = fs16.existsSync(db2) ? `, casper.db ${(fs16.statSync(db2).size / 1024).toFixed(0)} KB` : "";
|
|
3487
3528
|
out.push({ ok: true, name: "data dir", detail: `${config.casperDataDir} writable${size}` });
|
|
3488
3529
|
} catch (err) {
|
|
3489
3530
|
out.push({
|
|
@@ -3494,22 +3535,22 @@ function checks() {
|
|
|
3494
3535
|
});
|
|
3495
3536
|
}
|
|
3496
3537
|
out.push(
|
|
3497
|
-
|
|
3538
|
+
fs16.existsSync(config.webDist) ? { ok: true, name: "web app", detail: config.webDist } : {
|
|
3498
3539
|
ok: false,
|
|
3499
3540
|
fatal: true,
|
|
3500
3541
|
name: "web app",
|
|
3501
3542
|
detail: `${config.webDist} not found - the package is incomplete or CASPER_WEB_DIST is wrong`
|
|
3502
3543
|
}
|
|
3503
3544
|
);
|
|
3504
|
-
const agent =
|
|
3505
|
-
const hasAgent =
|
|
3545
|
+
const agent = path16.join(config.kiroSessionsDir, "..", "..", "agents", "casper.json");
|
|
3546
|
+
const hasAgent = fs16.existsSync(agent);
|
|
3506
3547
|
out.push({
|
|
3507
3548
|
ok: hasAgent,
|
|
3508
3549
|
name: "casper agent",
|
|
3509
3550
|
detail: hasAgent ? agent : `${agent} missing - it is installed on first run`
|
|
3510
3551
|
});
|
|
3511
3552
|
if (hasAgent) {
|
|
3512
|
-
const wiring = mcpWiring(
|
|
3553
|
+
const wiring = mcpWiring(fs16.readFileSync(agent, "utf8"), which);
|
|
3513
3554
|
out.push({ ok: wiring.ok, name: "casper mcp", detail: wiring.detail });
|
|
3514
3555
|
}
|
|
3515
3556
|
return out;
|
|
@@ -3973,14 +4014,14 @@ var init_server2 = __esm({
|
|
|
3973
4014
|
"server/src/mcp/server.ts"() {
|
|
3974
4015
|
"use strict";
|
|
3975
4016
|
init_protocol();
|
|
3976
|
-
VERSION = true ? "0.8.
|
|
4017
|
+
VERSION = true ? "0.8.8" : "dev";
|
|
3977
4018
|
}
|
|
3978
4019
|
});
|
|
3979
4020
|
|
|
3980
4021
|
// server/src/cli/program.ts
|
|
3981
|
-
import
|
|
4022
|
+
import fs17 from "node:fs";
|
|
3982
4023
|
import os4 from "node:os";
|
|
3983
|
-
import
|
|
4024
|
+
import path17 from "node:path";
|
|
3984
4025
|
|
|
3985
4026
|
// server/node_modules/commander/lib/error.js
|
|
3986
4027
|
var CommanderError = class extends Error {
|
|
@@ -7093,9 +7134,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
7093
7134
|
* @param {string} [path]
|
|
7094
7135
|
* @return {(string|null|Command)}
|
|
7095
7136
|
*/
|
|
7096
|
-
executableDir(
|
|
7097
|
-
if (
|
|
7098
|
-
this._executableDir =
|
|
7137
|
+
executableDir(path18) {
|
|
7138
|
+
if (path18 === void 0) return this._executableDir;
|
|
7139
|
+
this._executableDir = path18;
|
|
7099
7140
|
return this;
|
|
7100
7141
|
}
|
|
7101
7142
|
/**
|
|
@@ -7353,7 +7394,7 @@ var program = new Command();
|
|
|
7353
7394
|
// server/src/cli/program.ts
|
|
7354
7395
|
init_paths();
|
|
7355
7396
|
init_settings();
|
|
7356
|
-
var VERSION2 = true ? "0.8.
|
|
7397
|
+
var VERSION2 = true ? "0.8.8" : "dev";
|
|
7357
7398
|
async function bootstrap() {
|
|
7358
7399
|
const file = configFilePath();
|
|
7359
7400
|
const settings = readSettings(file);
|
|
@@ -7399,8 +7440,8 @@ async function resetToken(value) {
|
|
|
7399
7440
|
updateSettings(file, { token });
|
|
7400
7441
|
process.stdout.write(`wrote a new token to ${file}
|
|
7401
7442
|
`);
|
|
7402
|
-
const dbFile =
|
|
7403
|
-
if (
|
|
7443
|
+
const dbFile = path17.join(dataDirPath(), "casper.db");
|
|
7444
|
+
if (fs17.existsSync(dbFile)) {
|
|
7404
7445
|
const { LoginStore: LoginStore2 } = await Promise.resolve().then(() => (init_logins(), logins_exports));
|
|
7405
7446
|
new LoginStore2().revokeAll();
|
|
7406
7447
|
process.stdout.write("revoked all device sessions\n");
|