@joeyshi12/casper 0.7.3 → 0.8.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 +12 -1
- package/dist/agents/casper.json +11 -2
- package/dist/mcp.js +412 -0
- package/dist/server.js +528 -31
- package/dist/web/assets/{abnfDiagram-N423BO3Z-5RMwP9tv.js → abnfDiagram-N423BO3Z-J5DaDTt8.js} +1 -1
- package/dist/web/assets/{arc-DEuUsPX5.js → arc-CXWeATz6.js} +1 -1
- package/dist/web/assets/{architectureDiagram-T3A2C74G-k4h0zktw.js → architectureDiagram-T3A2C74G-ecXfY9My.js} +1 -1
- package/dist/web/assets/{blockDiagram-VBNYF7ZC-qTl9ZS2k.js → blockDiagram-VBNYF7ZC-D5ClKOWV.js} +1 -1
- package/dist/web/assets/{c4Diagram-5PPSVZJV-R6o_zt-Q.js → c4Diagram-5PPSVZJV-BxW2-O4j.js} +1 -1
- package/dist/web/assets/channel-BXz-ycSk.js +1 -0
- package/dist/web/assets/{chunk-2GRJ4B5K-CrJyVfhF.js → chunk-2GRJ4B5K-BBWhz2x0.js} +1 -1
- package/dist/web/assets/{chunk-2Q5K7J3B-BvGurkBq.js → chunk-2Q5K7J3B-CfD68qFQ.js} +1 -1
- package/dist/web/assets/{chunk-5RXB4S5H-DuE267ol.js → chunk-5RXB4S5H-DaznI8_V.js} +1 -1
- package/dist/web/assets/{chunk-5VM5RSS4-DAVY20oh.js → chunk-5VM5RSS4-BYxWXCvw.js} +1 -1
- package/dist/web/assets/{chunk-6Q2QTUOP-DvkSg8Wl.js → chunk-6Q2QTUOP-C8zmDMoc.js} +1 -1
- package/dist/web/assets/{chunk-GF5L2VYU-B8KQ7FAJ.js → chunk-GF5L2VYU-BXGR_P0f.js} +1 -1
- package/dist/web/assets/{chunk-JWPE2WC7-D2J6xFCq.js → chunk-JWPE2WC7-DsHbIvH7.js} +1 -1
- package/dist/web/assets/{chunk-KBJHAD2P-BfgGkRN_.js → chunk-KBJHAD2P-B8G6QD3I.js} +1 -1
- package/dist/web/assets/{chunk-RYQCIY6F-C0uby4vT.js → chunk-RYQCIY6F-B1rujkgY.js} +1 -1
- package/dist/web/assets/{chunk-XXDRQBXY-BAZLB2J1.js → chunk-XXDRQBXY-hjvfwopv.js} +1 -1
- package/dist/web/assets/classDiagram-JCYQIIEL-CRBj8GMD.js +1 -0
- package/dist/web/assets/classDiagram-v2-OCEON4UE-CRBj8GMD.js +1 -0
- package/dist/web/assets/{cose-bilkent-JH36ORCC-8FFjV-r2.js → cose-bilkent-JH36ORCC-D4S1nlYR.js} +1 -1
- package/dist/web/assets/{cynefin-VYW2F7L2-CDT1GZi_.js → cynefin-VYW2F7L2-DtN8m_GE.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-MW4NZA55-DMs5fXGJ.js → cynefinDiagram-MW4NZA55-Dkk-H0Nw.js} +1 -1
- package/dist/web/assets/{dagre-VZM6K2ZE-BUgnrG7T.js → dagre-VZM6K2ZE-BSkCOa-Z.js} +1 -1
- package/dist/web/assets/{diagram-7IWD3JNH-DUJeTMJj.js → diagram-7IWD3JNH-Bses1wzI.js} +1 -1
- package/dist/web/assets/{diagram-B4RE2ZJO-BsVTn5rU.js → diagram-B4RE2ZJO-BW7sntb1.js} +1 -1
- package/dist/web/assets/{diagram-LBJQPF4R--uxNHPeF.js → diagram-LBJQPF4R-DHzgX2HL.js} +1 -1
- package/dist/web/assets/{diagram-Q27KOJAE-GYAROo1s.js → diagram-Q27KOJAE-mcXdgoK9.js} +1 -1
- package/dist/web/assets/{diagram-UB23O5K3-CpJvxU_K.js → diagram-UB23O5K3-BO5P9LAa.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-BXEA7PRR-l3iEqoSP.js → ebnfDiagram-BXEA7PRR-F0zOfsYe.js} +1 -1
- package/dist/web/assets/{erDiagram-JOGREHBK-BoFHrs3B.js → erDiagram-JOGREHBK-aOYH_ZnE.js} +1 -1
- package/dist/web/assets/{flowDiagram-UKHOOZJN-CXMq4-uD.js → flowDiagram-UKHOOZJN-DmtkMJ60.js} +1 -1
- package/dist/web/assets/{ganttDiagram-PKOTCBZU-YMv8lvSL.js → ganttDiagram-PKOTCBZU-BFy8QpeS.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-DS77QQ5N-BgrfufCE.js → gitGraphDiagram-DS77QQ5N-CjbCeQfE.js} +1 -1
- package/dist/web/assets/{index-IBYN7wml.js → index-Bbzvwn2R.js} +207 -53
- package/dist/web/assets/{index-D7QnyK89.css → index-POlrwDS0.css} +1 -1
- package/dist/web/assets/{infoDiagram-6WML65LV-DMpqFKuC.js → infoDiagram-6WML65LV-CGFvyGjJ.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-BKdkzZXu.js → ishikawaDiagram-WSZJBQD7-BbVf1sRd.js} +1 -1
- package/dist/web/assets/{journeyDiagram-NVQOT4AX-NPjJ9Fq8.js → journeyDiagram-NVQOT4AX-BNevDB-1.js} +1 -1
- package/dist/web/assets/{kanban-definition-27J2QSJJ-MSVfDvXb.js → kanban-definition-27J2QSJJ-BdmYFEey.js} +1 -1
- package/dist/web/assets/{linear-Bugxdj26.js → linear-DJt4yr3f.js} +1 -1
- package/dist/web/assets/{mermaid.core-BrC5_l7I.js → mermaid.core-D-YupbG3.js} +5 -5
- package/dist/web/assets/{mindmap-definition-FAOFIHXS-yB60YQKy.js → mindmap-definition-FAOFIHXS-toscoNiP.js} +1 -1
- package/dist/web/assets/{pegDiagram-VL7TDLO6-BfdGiZwB.js → pegDiagram-VL7TDLO6-42qysB7S.js} +1 -1
- package/dist/web/assets/{pieDiagram-7S7Q4E2Y-BuJwU-QQ.js → pieDiagram-7S7Q4E2Y-DeC8rSjm.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-DvYy4rS6.js → quadrantDiagram-CIZ2JOQS-BsmBMVxR.js} +1 -1
- package/dist/web/assets/{railroadDiagram-AXF67PYL-D0Slzbqv.js → railroadDiagram-AXF67PYL-CUEYoy5N.js} +1 -1
- package/dist/web/assets/{requirementDiagram-LRYGKXZP-O1O4JCzu.js → requirementDiagram-LRYGKXZP-QOIVNSdo.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-W5VNT64P-WTewsL_K.js → sankeyDiagram-W5VNT64P-BTvBZ4O6.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-SI44F4Z6-BUoBi4kR.js → sequenceDiagram-SI44F4Z6-PgaCw-bZ.js} +1 -1
- package/dist/web/assets/{sizeCapture-X5ZJPWSS-BV9d3RVn.js → sizeCapture-X5ZJPWSS-xVBXwmWY.js} +1 -1
- package/dist/web/assets/{stateDiagram-OKZ733FA-BqdAeMq4.js → stateDiagram-OKZ733FA-BWvlFx8p.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-UEYNNEHI-CWroHbLn.js +1 -0
- package/dist/web/assets/{swimlanes-SLNWSIFB-Dn0Z0yF4.js → swimlanes-SLNWSIFB-B6SREfpi.js} +2 -2
- package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-B7_kKLQV.js +8 -0
- package/dist/web/assets/{timeline-definition-Z64GVDOM-RXIqWmas.js → timeline-definition-Z64GVDOM-pOrViFO-.js} +1 -1
- package/dist/web/assets/{vennDiagram-T6HMQDX7-Djv2Kody.js → vennDiagram-T6HMQDX7-DXbf3Z8V.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-T6FBY63Y-k8z1iXMI.js → wardleyDiagram-T6FBY63Y-BulJVCrV.js} +1 -1
- package/dist/web/assets/{xychartDiagram-ELKLHX3M-DBRaiGnz.js → xychartDiagram-ELKLHX3M-MI1zCRjW.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-BQC-40u0.js +0 -1
- package/dist/web/assets/classDiagram-JCYQIIEL-9L45zm4i.js +0 -1
- package/dist/web/assets/classDiagram-v2-OCEON4UE-9L45zm4i.js +0 -1
- package/dist/web/assets/stateDiagram-v2-UEYNNEHI-DQeB4eKD.js +0 -1
- package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-Dl6pHbTK.js +0 -8
package/dist/server.js
CHANGED
|
@@ -86,14 +86,38 @@ function sourceFile() {
|
|
|
86
86
|
const workspace = path4.resolve(here, "../../../assets/agents/casper.json");
|
|
87
87
|
return fs3.existsSync(packaged) ? packaged : workspace;
|
|
88
88
|
}
|
|
89
|
-
function
|
|
90
|
-
|
|
89
|
+
function mcpServerPath() {
|
|
90
|
+
const here = path4.dirname(url.fileURLToPath(import.meta.url));
|
|
91
|
+
const candidates = [
|
|
92
|
+
path4.resolve(here, "mcp.js"),
|
|
93
|
+
// bundled: beside server.js
|
|
94
|
+
path4.resolve(here, "../../dist/mcp.js")
|
|
95
|
+
// from source, if built
|
|
96
|
+
];
|
|
97
|
+
return candidates.find((c) => fs3.existsSync(c)) ?? null;
|
|
98
|
+
}
|
|
99
|
+
function withMcpServer(json) {
|
|
100
|
+
const mcp = mcpServerPath();
|
|
101
|
+
if (!mcp) return json;
|
|
102
|
+
const agent = JSON.parse(json);
|
|
103
|
+
agent.mcpServers = {
|
|
104
|
+
casper: {
|
|
105
|
+
command: process.execPath,
|
|
106
|
+
args: [mcp],
|
|
107
|
+
env: {},
|
|
108
|
+
timeout: 1e4
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return JSON.stringify(agent, null, 2) + "\n";
|
|
112
|
+
}
|
|
113
|
+
function sha256(text2) {
|
|
114
|
+
return crypto2.createHash("sha256").update(text2).digest("hex");
|
|
91
115
|
}
|
|
92
116
|
function installAgentFile(home2, dataDir) {
|
|
93
117
|
const src = sourceFile();
|
|
94
118
|
const target = path4.join(home2, ".kiro", "agents", "casper.json");
|
|
95
119
|
if (!fs3.existsSync(src)) return { action: "no-source", target };
|
|
96
|
-
const desired = fs3.readFileSync(src, "utf8");
|
|
120
|
+
const desired = withMcpServer(fs3.readFileSync(src, "utf8"));
|
|
97
121
|
const stampFile = path4.join(dataDir, "agent-stamp");
|
|
98
122
|
const stamp = fs3.existsSync(stampFile) ? fs3.readFileSync(stampFile, "utf8").trim() : "";
|
|
99
123
|
const write = () => {
|
|
@@ -611,20 +635,20 @@ var init_acp = __esm({
|
|
|
611
635
|
});
|
|
612
636
|
|
|
613
637
|
// shared/dist/attachments.js
|
|
614
|
-
function attachmentPaths(
|
|
615
|
-
const line =
|
|
638
|
+
function attachmentPaths(text2) {
|
|
639
|
+
const line = text2.split("\n").find((l) => l.startsWith(ATTACHMENTS_PREFIX));
|
|
616
640
|
if (!line)
|
|
617
641
|
return [];
|
|
618
642
|
return line.slice(ATTACHMENTS_PREFIX.length).split(", ").map((s) => s.trim()).filter(Boolean);
|
|
619
643
|
}
|
|
620
|
-
function imageAttachmentPaths(
|
|
621
|
-
return attachmentPaths(
|
|
644
|
+
function imageAttachmentPaths(text2) {
|
|
645
|
+
return attachmentPaths(text2).filter((p) => {
|
|
622
646
|
const lower = p.toLowerCase();
|
|
623
647
|
return IMAGE_EXTS.some((ext) => lower.endsWith(ext));
|
|
624
648
|
});
|
|
625
649
|
}
|
|
626
|
-
function stripAttachmentsLine(
|
|
627
|
-
return
|
|
650
|
+
function stripAttachmentsLine(text2) {
|
|
651
|
+
return text2.split("\n").filter((l) => !l.startsWith(ATTACHMENTS_PREFIX)).join("\n").trim();
|
|
628
652
|
}
|
|
629
653
|
var ATTACHMENTS_PREFIX, IMAGE_EXTS;
|
|
630
654
|
var init_attachments = __esm({
|
|
@@ -1304,17 +1328,17 @@ async function hydrateTranscript(sessionId) {
|
|
|
1304
1328
|
const pushMsg = (msg) => items.push({ type: "message", message: msg });
|
|
1305
1329
|
if (entry.kind === "Prompt") {
|
|
1306
1330
|
const raw2 = textOf("text");
|
|
1307
|
-
const
|
|
1331
|
+
const text2 = stripAttachmentsLine(raw2);
|
|
1308
1332
|
const imagePaths = imageAttachmentPaths(raw2);
|
|
1309
|
-
if (
|
|
1310
|
-
pushMsg({ id: `u-${baseId}`, role: "user", text, timestamp: ts, imagePaths });
|
|
1333
|
+
if (text2.trim() || imagePaths.length)
|
|
1334
|
+
pushMsg({ id: `u-${baseId}`, role: "user", text: text2, timestamp: ts, imagePaths });
|
|
1311
1335
|
} else if (entry.kind === "AssistantMessage") {
|
|
1312
1336
|
const thinking = textOf("thinking");
|
|
1313
1337
|
if (thinking.trim())
|
|
1314
1338
|
pushMsg({ id: `t-${baseId}`, role: "thinking", text: thinking, timestamp: ts });
|
|
1315
|
-
const
|
|
1316
|
-
if (
|
|
1317
|
-
pushMsg({ id: `a-${baseId}`, role: "assistant", text, timestamp: ts });
|
|
1339
|
+
const text2 = textOf("text");
|
|
1340
|
+
if (text2.trim())
|
|
1341
|
+
pushMsg({ id: `a-${baseId}`, role: "assistant", text: text2, timestamp: ts });
|
|
1318
1342
|
for (const c of content) {
|
|
1319
1343
|
const d = toolUseData(c);
|
|
1320
1344
|
if (!d) continue;
|
|
@@ -2107,8 +2131,8 @@ async function listAgents() {
|
|
|
2107
2131
|
cwd: config.defaultCwd,
|
|
2108
2132
|
maxBuffer: 2 * 1024 * 1024
|
|
2109
2133
|
});
|
|
2110
|
-
const
|
|
2111
|
-
for (const rawLine of
|
|
2134
|
+
const text2 = (stderr || "") + "\n" + (stdout || "");
|
|
2135
|
+
for (const rawLine of text2.split("\n")) {
|
|
2112
2136
|
const line = rawLine.replace(ANSI, "");
|
|
2113
2137
|
const m = /^\s{0,2}(\*\s)?([A-Za-z0-9_-]+)\s{2,}(Global|Workspace|Local)\b/.exec(
|
|
2114
2138
|
line
|
|
@@ -3271,7 +3295,8 @@ var init_server = __esm({
|
|
|
3271
3295
|
// server/src/cli/doctor.ts
|
|
3272
3296
|
var doctor_exports = {};
|
|
3273
3297
|
__export(doctor_exports, {
|
|
3274
|
-
doctor: () => doctor
|
|
3298
|
+
doctor: () => doctor,
|
|
3299
|
+
mcpWiring: () => mcpWiring
|
|
3275
3300
|
});
|
|
3276
3301
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3277
3302
|
import fs14 from "node:fs";
|
|
@@ -3289,6 +3314,28 @@ function which(bin) {
|
|
|
3289
3314
|
}
|
|
3290
3315
|
return void 0;
|
|
3291
3316
|
}
|
|
3317
|
+
function mcpWiring(agentJson, resolve) {
|
|
3318
|
+
let servers;
|
|
3319
|
+
try {
|
|
3320
|
+
servers = JSON.parse(agentJson).mcpServers;
|
|
3321
|
+
} catch {
|
|
3322
|
+
return { ok: false, detail: "the agent file is not valid JSON" };
|
|
3323
|
+
}
|
|
3324
|
+
const server = servers?.casper;
|
|
3325
|
+
if (!server) {
|
|
3326
|
+
return { ok: false, detail: "not declared in the agent file, so widgets are unavailable" };
|
|
3327
|
+
}
|
|
3328
|
+
const command = typeof server.command === "string" ? server.command : "";
|
|
3329
|
+
const args = Array.isArray(server.args) ? server.args.filter((a) => typeof a === "string") : [];
|
|
3330
|
+
if (!resolve(command)) {
|
|
3331
|
+
return { ok: false, detail: `${command || "(no command)"} not found - widgets are unavailable` };
|
|
3332
|
+
}
|
|
3333
|
+
const script = args.find((a) => a.endsWith(".js"));
|
|
3334
|
+
if (script && !fs14.existsSync(script)) {
|
|
3335
|
+
return { ok: false, detail: `${script} is gone - delete the agent file and restart to rewrite it` };
|
|
3336
|
+
}
|
|
3337
|
+
return { ok: true, detail: script ?? `${command} ${args.join(" ")}` };
|
|
3338
|
+
}
|
|
3292
3339
|
function checks() {
|
|
3293
3340
|
const out = [];
|
|
3294
3341
|
out.push({
|
|
@@ -3357,11 +3404,16 @@ function checks() {
|
|
|
3357
3404
|
}
|
|
3358
3405
|
);
|
|
3359
3406
|
const agent = path15.join(config.kiroSessionsDir, "..", "..", "agents", "casper.json");
|
|
3407
|
+
const hasAgent = fs14.existsSync(agent);
|
|
3360
3408
|
out.push({
|
|
3361
|
-
ok:
|
|
3409
|
+
ok: hasAgent,
|
|
3362
3410
|
name: "casper agent",
|
|
3363
|
-
detail:
|
|
3411
|
+
detail: hasAgent ? agent : `${agent} missing - it is installed on first run`
|
|
3364
3412
|
});
|
|
3413
|
+
if (hasAgent) {
|
|
3414
|
+
const wiring = mcpWiring(fs14.readFileSync(agent, "utf8"), which);
|
|
3415
|
+
out.push({ ok: wiring.ok, name: "casper mcp", detail: wiring.detail });
|
|
3416
|
+
}
|
|
3365
3417
|
return out;
|
|
3366
3418
|
}
|
|
3367
3419
|
function doctor() {
|
|
@@ -3388,6 +3440,445 @@ var init_doctor = __esm({
|
|
|
3388
3440
|
}
|
|
3389
3441
|
});
|
|
3390
3442
|
|
|
3443
|
+
// server/src/mcp/guidelines.ts
|
|
3444
|
+
function getGuidelines(modules) {
|
|
3445
|
+
const parts = [CORE];
|
|
3446
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3447
|
+
for (const mod of modules) {
|
|
3448
|
+
const sections = MODULE_SECTIONS[mod];
|
|
3449
|
+
if (!sections) continue;
|
|
3450
|
+
for (const section of sections) {
|
|
3451
|
+
if (seen.has(section)) continue;
|
|
3452
|
+
seen.add(section);
|
|
3453
|
+
parts.push(section);
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
return parts.join("\n\n");
|
|
3457
|
+
}
|
|
3458
|
+
var MODULES, CORE, COLOR, UI, CHARTS, SVG, DIAGRAMS, ART, MODULE_SECTIONS;
|
|
3459
|
+
var init_guidelines = __esm({
|
|
3460
|
+
"server/src/mcp/guidelines.ts"() {
|
|
3461
|
+
"use strict";
|
|
3462
|
+
MODULES = ["interactive", "chart", "diagram", "art"];
|
|
3463
|
+
CORE = `# Widgets
|
|
3464
|
+
|
|
3465
|
+
A widget is a self-contained HTML fragment rendered inline in the conversation. No
|
|
3466
|
+
doctype, html, head or body tag - just content. It is not a file and not a
|
|
3467
|
+
deliverable; it is part of what you are saying. Reach for one when a picture
|
|
3468
|
+
answers better than a paragraph.
|
|
3469
|
+
|
|
3470
|
+
## Structure, in this order
|
|
3471
|
+
|
|
3472
|
+
1. A short \`<style>\` block.
|
|
3473
|
+
2. The content markup.
|
|
3474
|
+
3. A single \`<script>\` at the end.
|
|
3475
|
+
|
|
3476
|
+
Order matters. Content renders as it arrives, and scripts run only once the message
|
|
3477
|
+
is complete, so a widget whose script sits at the top looks inert until the end.
|
|
3478
|
+
|
|
3479
|
+
## Hard rules
|
|
3480
|
+
|
|
3481
|
+
- No gradients, drop shadows or blur. They flash while content is patched in.
|
|
3482
|
+
- No HTML comments. They cost tokens and buy nothing.
|
|
3483
|
+
- Two font weights only: 400 and 500. Never 600 or 700.
|
|
3484
|
+
- Sentence case for every label, heading and button. Never Title Case, never ALL CAPS.
|
|
3485
|
+
- Never hardcode a colour that has a variable below.
|
|
3486
|
+
- Size text in px, 11 to 15 for body and labels, up to 18 for a single heading.
|
|
3487
|
+
- Keep the whole widget under 600px tall unless the content genuinely needs more.
|
|
3488
|
+
|
|
3489
|
+
## The sandbox
|
|
3490
|
+
|
|
3491
|
+
The frame has an opaque origin. localStorage, sessionStorage, cookies and requests
|
|
3492
|
+
to Casper all throw or fail. Hold state in a variable for the life of the page.
|
|
3493
|
+
|
|
3494
|
+
Libraries load from these hosts only: cdnjs.cloudflare.com, cdn.jsdelivr.net,
|
|
3495
|
+
unpkg.com, esm.sh. Anything else is refused by the content security policy, as is
|
|
3496
|
+
eval and new Function, so pick libraries that don't rely on them.
|
|
3497
|
+
|
|
3498
|
+
## Theme
|
|
3499
|
+
|
|
3500
|
+
The background is transparent and the app's own variables are set. Use them:
|
|
3501
|
+
|
|
3502
|
+
--color-text-primary, --color-text-secondary
|
|
3503
|
+
--color-background-primary, --color-background-secondary
|
|
3504
|
+
--color-border
|
|
3505
|
+
--color-accent, --color-accent-alt
|
|
3506
|
+
--color-teal, --color-green, --color-yellow, --color-orange, --color-red
|
|
3507
|
+
--font-body, --font-mono
|
|
3508
|
+
|
|
3509
|
+
Read them in script with getComputedStyle(document.documentElement).getPropertyValue.
|
|
3510
|
+
|
|
3511
|
+
## Talking back
|
|
3512
|
+
|
|
3513
|
+
casper.sendPrompt(text) sends a message as if the user typed it, indistinguishable
|
|
3514
|
+
in the transcript from one they wrote. Most widgets need no button at all. Add one
|
|
3515
|
+
only when the obvious next step is a question they would otherwise type out by hand,
|
|
3516
|
+
and never as decoration or to invite engagement. One at most.`;
|
|
3517
|
+
COLOR = `## Colour
|
|
3518
|
+
|
|
3519
|
+
Six accents are available: --color-accent (purple), --color-accent-alt (pink),
|
|
3520
|
+
--color-teal, --color-green, --color-yellow, --color-orange, --color-red.
|
|
3521
|
+
|
|
3522
|
+
Colour encodes meaning, never sequence. If two series differ only by being
|
|
3523
|
+
different series, use one accent at two opacities rather than two hues. Two or
|
|
3524
|
+
three hues per widget is the ceiling.
|
|
3525
|
+
|
|
3526
|
+
Semantics people already expect: green for success or growth, red for error or
|
|
3527
|
+
loss, orange for warning or pending, teal for neutral information, purple for the
|
|
3528
|
+
primary subject.
|
|
3529
|
+
|
|
3530
|
+
For text on a filled background, use --color-background-primary as the text colour
|
|
3531
|
+
rather than black. For a tint, use the accent at 12 to 20 percent opacity with the
|
|
3532
|
+
accent itself as the border.`;
|
|
3533
|
+
UI = `## Components
|
|
3534
|
+
|
|
3535
|
+
Card: background --color-background-secondary, 1px --color-border, radius 10px,
|
|
3536
|
+
padding 12px 14px. No shadow.
|
|
3537
|
+
|
|
3538
|
+
Metric: label 11px --color-text-secondary above a 20px 500-weight value. Group
|
|
3539
|
+
metrics in a grid with 12px gaps, never a table.
|
|
3540
|
+
|
|
3541
|
+
Button: 12px text, background --color-background-secondary, 1px --color-border,
|
|
3542
|
+
radius 6px, padding 5px 10px. On hover, move the border to --color-accent. Never
|
|
3543
|
+
paint a button in an accent colour unless it is the single primary action.
|
|
3544
|
+
|
|
3545
|
+
Input and range: set accent-color to var(--color-accent) and let the browser style
|
|
3546
|
+
the rest.
|
|
3547
|
+
|
|
3548
|
+
Table: only for genuinely tabular data. 1px --color-border between rows, no
|
|
3549
|
+
vertical rules, 12px text, numbers right-aligned in --font-mono.
|
|
3550
|
+
|
|
3551
|
+
Rows of key and value: a flex row with the label in --color-text-secondary and the
|
|
3552
|
+
value in --font-mono, separated by a border-bottom on all but the last.`;
|
|
3553
|
+
CHARTS = `## Charts
|
|
3554
|
+
|
|
3555
|
+
Chart.js from cdn.jsdelivr.net is the default choice. Load it with a script tag
|
|
3556
|
+
before your own script; it will have finished loading by the time your script runs,
|
|
3557
|
+
so there's no need to poll for it.
|
|
3558
|
+
|
|
3559
|
+
Wrap every canvas in a div with position relative and an explicit height, and set
|
|
3560
|
+
maintainAspectRatio to false. Without both, the canvas grows without bound.
|
|
3561
|
+
|
|
3562
|
+
Turn the built-in legend off (plugins.legend.display false) and write the legend as
|
|
3563
|
+
HTML if it's needed - the built-in one ignores the theme.
|
|
3564
|
+
|
|
3565
|
+
Grid lines in --color-border at low opacity, ticks in --color-text-secondary, 11px.
|
|
3566
|
+
Datasets take an accent colour with borderWidth 2 and no point markers unless
|
|
3567
|
+
individual readings matter.
|
|
3568
|
+
|
|
3569
|
+
Format numbers so the sign leads: -$5M, never $-5M. Abbreviate above four digits
|
|
3570
|
+
(12.4k, 3.1M). Percentages get one decimal at most.
|
|
3571
|
+
|
|
3572
|
+
Pick the form from the question: trend over time is a line, comparison across
|
|
3573
|
+
categories is a horizontal bar when labels are words, composition is a stacked bar
|
|
3574
|
+
rather than a pie unless there are three slices or fewer.`;
|
|
3575
|
+
SVG = `## SVG
|
|
3576
|
+
|
|
3577
|
+
Set viewBox and leave width and height off, so the drawing scales to the frame.
|
|
3578
|
+
Compute the viewBox from the content bounds and add 8 units of padding on every
|
|
3579
|
+
side; anything drawn outside is invisible and reviewers will not see the mistake.
|
|
3580
|
+
|
|
3581
|
+
Text width is the usual cause of overflow. At font-size 12 with the body font,
|
|
3582
|
+
budget 6.2px per character for lowercase and 7.4px for uppercase, then size boxes
|
|
3583
|
+
from the longest label rather than by eye.
|
|
3584
|
+
|
|
3585
|
+
Connector paths need fill="none" explicitly. SVG fills paths black by default, so a
|
|
3586
|
+
curve without it renders as a filled blob.
|
|
3587
|
+
|
|
3588
|
+
Define arrowheads once in defs with a marker whose fill is context-stroke, so the
|
|
3589
|
+
head inherits the line colour instead of needing one marker per colour.
|
|
3590
|
+
|
|
3591
|
+
Stroke widths: 1.5 for connectors, 2 for emphasis, 1 for gridlines. Never below 1.`;
|
|
3592
|
+
DIAGRAMS = `## Diagrams
|
|
3593
|
+
|
|
3594
|
+
Two mistakes account for most bad diagrams. First, arrows that cross boxes they
|
|
3595
|
+
have nothing to do with: trace every arrow's straight path and if it passes through
|
|
3596
|
+
a box, route it around or move the box. Second, boxes sized by guess rather than by
|
|
3597
|
+
the longest label they contain.
|
|
3598
|
+
|
|
3599
|
+
Route on the verb, not the noun. "How does a request flow" wants a sequence, "what
|
|
3600
|
+
are the parts" wants a structural diagram, "why is it slow" wants an annotated
|
|
3601
|
+
before and after.
|
|
3602
|
+
|
|
3603
|
+
Budgets: at most four boxes across one tier, at most five words in a label, at most
|
|
3604
|
+
three tiers deep. Beyond that, split into two diagrams or drop detail.
|
|
3605
|
+
|
|
3606
|
+
Label every arrow that isn't obvious, in 10px --color-text-secondary. An unlabelled
|
|
3607
|
+
arrow asserts a relationship without saying which.
|
|
3608
|
+
|
|
3609
|
+
Lay out left to right for flow and top to bottom for hierarchy, and keep a single
|
|
3610
|
+
consistent gap between tiers.`;
|
|
3611
|
+
ART = `## Illustration
|
|
3612
|
+
|
|
3613
|
+
Build from geometry: circles, rounded rectangles, and paths with two or three
|
|
3614
|
+
control points. Detail beyond that reads as noise at conversation size.
|
|
3615
|
+
|
|
3616
|
+
Use flat fills from the palette with no more than three colours plus a background.
|
|
3617
|
+
Depth comes from overlap and size, never from gradients or shadows.
|
|
3618
|
+
|
|
3619
|
+
Animate with CSS on transform and opacity only, 0.3s or slower, and only where the
|
|
3620
|
+
motion carries meaning. Anything faster or busier is a distraction in a chat.
|
|
3621
|
+
|
|
3622
|
+
For anything representational, prefer a diagram with labels. An unlabelled drawing
|
|
3623
|
+
of a concept is decoration.`;
|
|
3624
|
+
MODULE_SECTIONS = {
|
|
3625
|
+
interactive: [UI, COLOR],
|
|
3626
|
+
chart: [UI, COLOR, CHARTS],
|
|
3627
|
+
diagram: [COLOR, SVG, DIAGRAMS],
|
|
3628
|
+
art: [COLOR, SVG, ART]
|
|
3629
|
+
};
|
|
3630
|
+
}
|
|
3631
|
+
});
|
|
3632
|
+
|
|
3633
|
+
// server/src/mcp/choice.ts
|
|
3634
|
+
function validateChoice(data) {
|
|
3635
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
3636
|
+
return "arguments must be an object.";
|
|
3637
|
+
}
|
|
3638
|
+
const d = data;
|
|
3639
|
+
if (typeof d.question !== "string" || !d.question.trim()) {
|
|
3640
|
+
return "question is required: what you are asking the user to decide.";
|
|
3641
|
+
}
|
|
3642
|
+
if (!Array.isArray(d.options) || d.options.length < 2) {
|
|
3643
|
+
return "at least two options are needed.";
|
|
3644
|
+
}
|
|
3645
|
+
if (d.options.length > MAX_OPTIONS) {
|
|
3646
|
+
return `at most ${MAX_OPTIONS} options; ${d.options.length} is too many to tap through.`;
|
|
3647
|
+
}
|
|
3648
|
+
for (const [i, raw] of d.options.entries()) {
|
|
3649
|
+
if (typeof raw !== "object" || raw === null) return `options[${i}] must be an object.`;
|
|
3650
|
+
const o = raw;
|
|
3651
|
+
if (typeof o.label !== "string" || !o.label.trim()) {
|
|
3652
|
+
return `options[${i}].label is required and must be a short phrase.`;
|
|
3653
|
+
}
|
|
3654
|
+
if (o.prompt !== void 0 && typeof o.prompt !== "string") {
|
|
3655
|
+
return `options[${i}].prompt must be a string when given.`;
|
|
3656
|
+
}
|
|
3657
|
+
if (o.detail !== void 0 && typeof o.detail !== "string") {
|
|
3658
|
+
return `options[${i}].detail must be a string when given.`;
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
return null;
|
|
3662
|
+
}
|
|
3663
|
+
var MAX_OPTIONS;
|
|
3664
|
+
var init_choice = __esm({
|
|
3665
|
+
"server/src/mcp/choice.ts"() {
|
|
3666
|
+
"use strict";
|
|
3667
|
+
MAX_OPTIONS = 6;
|
|
3668
|
+
}
|
|
3669
|
+
});
|
|
3670
|
+
|
|
3671
|
+
// server/src/mcp/protocol.ts
|
|
3672
|
+
function ok(id, result) {
|
|
3673
|
+
return { jsonrpc: "2.0", id, result };
|
|
3674
|
+
}
|
|
3675
|
+
function text(body, isError = false) {
|
|
3676
|
+
return { content: [{ type: "text", text: body }], isError };
|
|
3677
|
+
}
|
|
3678
|
+
function callError(id, message) {
|
|
3679
|
+
return ok(id, text(message, true));
|
|
3680
|
+
}
|
|
3681
|
+
function asStringArray(value) {
|
|
3682
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
3683
|
+
}
|
|
3684
|
+
function handleReadMe(id, args) {
|
|
3685
|
+
const modules = asStringArray(args.modules);
|
|
3686
|
+
const known = modules.filter((m) => MODULES.includes(m));
|
|
3687
|
+
if (known.length === 0) {
|
|
3688
|
+
return callError(id, `Name at least one module: ${MODULES.join(", ")}.`);
|
|
3689
|
+
}
|
|
3690
|
+
return ok(id, text(getGuidelines(known)));
|
|
3691
|
+
}
|
|
3692
|
+
function handleShowWidget(id, args) {
|
|
3693
|
+
if (args.i_have_seen_read_me !== true) {
|
|
3694
|
+
return callError(id, "Call read_me first, then set i_have_seen_read_me to true.");
|
|
3695
|
+
}
|
|
3696
|
+
const title = typeof args.title === "string" ? args.title.trim() : "";
|
|
3697
|
+
if (!title) return callError(id, "title is required: a short snake_case identifier.");
|
|
3698
|
+
const code = typeof args.widget_code === "string" ? args.widget_code : "";
|
|
3699
|
+
if (!code.trim()) return callError(id, "widget_code is required.");
|
|
3700
|
+
if (code.length > MAX_WIDGET_CHARS) {
|
|
3701
|
+
return callError(
|
|
3702
|
+
id,
|
|
3703
|
+
`widget_code is ${Math.round(code.length / 1024)} KB, over the ${MAX_WIDGET_CHARS / 1024} KB limit. Simplify it.`
|
|
3704
|
+
);
|
|
3705
|
+
}
|
|
3706
|
+
if (/<(!doctype|html|head|body)\b/i.test(code)) {
|
|
3707
|
+
return callError(id, "Pass a fragment, not a document: drop the doctype, html and body tags.");
|
|
3708
|
+
}
|
|
3709
|
+
return ok(id, text(`Widget "${title}" is on screen. Don't repeat its content in prose.`));
|
|
3710
|
+
}
|
|
3711
|
+
function handleChoice(id, args) {
|
|
3712
|
+
const problem = validateChoice(args);
|
|
3713
|
+
if (problem) return callError(id, problem);
|
|
3714
|
+
return ok(id, text("Options are on screen. Wait for the user to pick one."));
|
|
3715
|
+
}
|
|
3716
|
+
function handleMessage(req, version) {
|
|
3717
|
+
const id = req.id ?? null;
|
|
3718
|
+
const method = req.method ?? "";
|
|
3719
|
+
const params = req.params ?? {};
|
|
3720
|
+
if (method.startsWith("notifications/")) return null;
|
|
3721
|
+
switch (method) {
|
|
3722
|
+
case "initialize": {
|
|
3723
|
+
const asked = typeof params.protocolVersion === "string" ? params.protocolVersion : null;
|
|
3724
|
+
return ok(id, {
|
|
3725
|
+
protocolVersion: asked ?? DEFAULT_PROTOCOL_VERSION,
|
|
3726
|
+
capabilities: { tools: { listChanged: false } },
|
|
3727
|
+
serverInfo: { name: SERVER_NAME, version }
|
|
3728
|
+
});
|
|
3729
|
+
}
|
|
3730
|
+
case "ping":
|
|
3731
|
+
return ok(id, {});
|
|
3732
|
+
case "tools/list":
|
|
3733
|
+
return ok(id, { tools: TOOLS });
|
|
3734
|
+
case "tools/call": {
|
|
3735
|
+
const name = typeof params.name === "string" ? params.name : "";
|
|
3736
|
+
const args = params.arguments ?? {};
|
|
3737
|
+
if (name === "read_me") return handleReadMe(id, args);
|
|
3738
|
+
if (name === "show_widget") return handleShowWidget(id, args);
|
|
3739
|
+
if (name === "show_choice") return handleChoice(id, args);
|
|
3740
|
+
return { jsonrpc: "2.0", id, error: { code: -32602, message: `Unknown tool: ${name}` } };
|
|
3741
|
+
}
|
|
3742
|
+
default:
|
|
3743
|
+
if (id === null) return null;
|
|
3744
|
+
return { jsonrpc: "2.0", id, error: { code: -32601, message: `Unknown method: ${method}` } };
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
var DEFAULT_PROTOCOL_VERSION, SERVER_NAME, MAX_WIDGET_CHARS, TOOLS;
|
|
3748
|
+
var init_protocol = __esm({
|
|
3749
|
+
"server/src/mcp/protocol.ts"() {
|
|
3750
|
+
"use strict";
|
|
3751
|
+
init_guidelines();
|
|
3752
|
+
init_choice();
|
|
3753
|
+
DEFAULT_PROTOCOL_VERSION = "2025-06-18";
|
|
3754
|
+
SERVER_NAME = "casper-generative-ui";
|
|
3755
|
+
MAX_WIDGET_CHARS = 256 * 1024;
|
|
3756
|
+
TOOLS = [
|
|
3757
|
+
{
|
|
3758
|
+
name: "read_me",
|
|
3759
|
+
title: "Widget design guidelines",
|
|
3760
|
+
description: "Read the widget design guidelines. Call this once, before your first show_widget call, with the modules relevant to what you are about to build. Do not mention this call to the user.",
|
|
3761
|
+
inputSchema: {
|
|
3762
|
+
type: "object",
|
|
3763
|
+
properties: {
|
|
3764
|
+
modules: {
|
|
3765
|
+
type: "array",
|
|
3766
|
+
items: { type: "string", enum: [...MODULES] },
|
|
3767
|
+
minItems: 1,
|
|
3768
|
+
description: "interactive for controls, sketches and simulations, chart for data, diagram for structure and flow, art for illustration."
|
|
3769
|
+
}
|
|
3770
|
+
},
|
|
3771
|
+
required: ["modules"]
|
|
3772
|
+
}
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
name: "show_widget",
|
|
3776
|
+
title: "Show widget",
|
|
3777
|
+
description: "Render an interactive widget inline in the conversation. Pass an HTML fragment: no doctype, html or body tag. Style first, then content, then a single script last. Use this instead of describing something visual in prose.",
|
|
3778
|
+
inputSchema: {
|
|
3779
|
+
type: "object",
|
|
3780
|
+
properties: {
|
|
3781
|
+
i_have_seen_read_me: {
|
|
3782
|
+
type: "boolean",
|
|
3783
|
+
description: "True only if you have already called read_me in this conversation."
|
|
3784
|
+
},
|
|
3785
|
+
title: {
|
|
3786
|
+
type: "string",
|
|
3787
|
+
description: "Short snake_case identifier, e.g. compound_interest."
|
|
3788
|
+
},
|
|
3789
|
+
widget_code: {
|
|
3790
|
+
type: "string",
|
|
3791
|
+
description: "The HTML fragment to render."
|
|
3792
|
+
}
|
|
3793
|
+
},
|
|
3794
|
+
required: ["i_have_seen_read_me", "title", "widget_code"]
|
|
3795
|
+
}
|
|
3796
|
+
},
|
|
3797
|
+
{
|
|
3798
|
+
name: "show_choice",
|
|
3799
|
+
title: "Ask the user to choose",
|
|
3800
|
+
description: "Ask the user to pick from a few options, which they tap instead of typing. Use it wherever you would otherwise end a message asking which of several ways to proceed.",
|
|
3801
|
+
inputSchema: {
|
|
3802
|
+
type: "object",
|
|
3803
|
+
properties: {
|
|
3804
|
+
question: { type: "string", description: "What they are deciding." },
|
|
3805
|
+
options: {
|
|
3806
|
+
type: "array",
|
|
3807
|
+
minItems: 2,
|
|
3808
|
+
maxItems: MAX_OPTIONS,
|
|
3809
|
+
items: {
|
|
3810
|
+
type: "object",
|
|
3811
|
+
properties: {
|
|
3812
|
+
label: { type: "string", description: "Short, tappable phrase." },
|
|
3813
|
+
detail: { type: "string", description: "One line of context." },
|
|
3814
|
+
prompt: {
|
|
3815
|
+
type: "string",
|
|
3816
|
+
description: "Message sent when tapped. Defaults to the label."
|
|
3817
|
+
}
|
|
3818
|
+
},
|
|
3819
|
+
required: ["label"]
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
},
|
|
3823
|
+
required: ["question", "options"]
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
];
|
|
3827
|
+
}
|
|
3828
|
+
});
|
|
3829
|
+
|
|
3830
|
+
// server/src/mcp/server.ts
|
|
3831
|
+
var server_exports2 = {};
|
|
3832
|
+
__export(server_exports2, {
|
|
3833
|
+
runMcpServer: () => runMcpServer
|
|
3834
|
+
});
|
|
3835
|
+
import { createInterface } from "node:readline";
|
|
3836
|
+
function runMcpServer() {
|
|
3837
|
+
const rl = createInterface({ input: process.stdin });
|
|
3838
|
+
rl.on("line", (line) => {
|
|
3839
|
+
const trimmed = line.trim();
|
|
3840
|
+
if (!trimmed) return;
|
|
3841
|
+
let req;
|
|
3842
|
+
try {
|
|
3843
|
+
req = JSON.parse(trimmed);
|
|
3844
|
+
} catch {
|
|
3845
|
+
process.stdout.write(
|
|
3846
|
+
JSON.stringify({
|
|
3847
|
+
jsonrpc: "2.0",
|
|
3848
|
+
id: null,
|
|
3849
|
+
error: { code: -32700, message: "Parse error" }
|
|
3850
|
+
}) + "\n"
|
|
3851
|
+
);
|
|
3852
|
+
return;
|
|
3853
|
+
}
|
|
3854
|
+
try {
|
|
3855
|
+
const res = handleMessage(req, VERSION);
|
|
3856
|
+
if (res) process.stdout.write(JSON.stringify(res) + "\n");
|
|
3857
|
+
} catch (err) {
|
|
3858
|
+
process.stderr.write(`casper-mcp: ${err.message}
|
|
3859
|
+
`);
|
|
3860
|
+
if (req.id !== void 0 && req.id !== null) {
|
|
3861
|
+
process.stdout.write(
|
|
3862
|
+
JSON.stringify({
|
|
3863
|
+
jsonrpc: "2.0",
|
|
3864
|
+
id: req.id,
|
|
3865
|
+
error: { code: -32603, message: "Internal error" }
|
|
3866
|
+
}) + "\n"
|
|
3867
|
+
);
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
});
|
|
3871
|
+
rl.on("close", () => process.exit(0));
|
|
3872
|
+
}
|
|
3873
|
+
var VERSION;
|
|
3874
|
+
var init_server2 = __esm({
|
|
3875
|
+
"server/src/mcp/server.ts"() {
|
|
3876
|
+
"use strict";
|
|
3877
|
+
init_protocol();
|
|
3878
|
+
VERSION = true ? "0.8.0" : "dev";
|
|
3879
|
+
}
|
|
3880
|
+
});
|
|
3881
|
+
|
|
3391
3882
|
// server/src/cli/program.ts
|
|
3392
3883
|
import fs15 from "node:fs";
|
|
3393
3884
|
import os4 from "node:os";
|
|
@@ -6523,9 +7014,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
6523
7014
|
helpWidth: context.helpWidth,
|
|
6524
7015
|
outputHasColors: context.hasColors
|
|
6525
7016
|
});
|
|
6526
|
-
const
|
|
6527
|
-
if (context.hasColors) return
|
|
6528
|
-
return this._outputConfiguration.stripColor(
|
|
7017
|
+
const text2 = helper.formatHelp(this, helper);
|
|
7018
|
+
if (context.hasColors) return text2;
|
|
7019
|
+
return this._outputConfiguration.stripColor(text2);
|
|
6529
7020
|
}
|
|
6530
7021
|
/**
|
|
6531
7022
|
* @typedef HelpContext
|
|
@@ -6685,7 +7176,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
6685
7176
|
* @param {(string | Function)} text - string to add, or a function returning a string
|
|
6686
7177
|
* @return {Command} `this` command for chaining
|
|
6687
7178
|
*/
|
|
6688
|
-
addHelpText(position,
|
|
7179
|
+
addHelpText(position, text2) {
|
|
6689
7180
|
const allowedValues = ["beforeAll", "before", "after", "afterAll"];
|
|
6690
7181
|
if (!allowedValues.includes(position)) {
|
|
6691
7182
|
throw new Error(`Unexpected value for position to addHelpText.
|
|
@@ -6694,10 +7185,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
6694
7185
|
const helpEvent = `${position}Help`;
|
|
6695
7186
|
this.on(helpEvent, (context) => {
|
|
6696
7187
|
let helpStr;
|
|
6697
|
-
if (typeof
|
|
6698
|
-
helpStr =
|
|
7188
|
+
if (typeof text2 === "function") {
|
|
7189
|
+
helpStr = text2({ error: context.error, command: context.command });
|
|
6699
7190
|
} else {
|
|
6700
|
-
helpStr =
|
|
7191
|
+
helpStr = text2;
|
|
6701
7192
|
}
|
|
6702
7193
|
if (helpStr) {
|
|
6703
7194
|
context.write(`${helpStr}
|
|
@@ -6764,7 +7255,7 @@ var program = new Command();
|
|
|
6764
7255
|
// server/src/cli/program.ts
|
|
6765
7256
|
init_paths();
|
|
6766
7257
|
init_settings();
|
|
6767
|
-
var
|
|
7258
|
+
var VERSION2 = true ? "0.8.0" : "dev";
|
|
6768
7259
|
async function bootstrap() {
|
|
6769
7260
|
const file = configFilePath();
|
|
6770
7261
|
const settings = readSettings(file);
|
|
@@ -6782,8 +7273,11 @@ async function bootstrap() {
|
|
|
6782
7273
|
process.stdout.write(`casper agent ${agent.action}: ${agent.target}
|
|
6783
7274
|
`);
|
|
6784
7275
|
} else if (agent.action === "kept-yours") {
|
|
6785
|
-
process.stdout.write(
|
|
6786
|
-
`
|
|
7276
|
+
process.stdout.write(
|
|
7277
|
+
`keeping your edited agent file at ${agent.target}
|
|
7278
|
+
Prompt and tool updates are being skipped. Delete it to take them.
|
|
7279
|
+
`
|
|
7280
|
+
);
|
|
6787
7281
|
}
|
|
6788
7282
|
}
|
|
6789
7283
|
function printToken() {
|
|
@@ -6825,7 +7319,7 @@ async function resetToken(value) {
|
|
|
6825
7319
|
}
|
|
6826
7320
|
function buildProgram() {
|
|
6827
7321
|
const program2 = new Command();
|
|
6828
|
-
program2.name("casper").description("Web client for kiro-cli over the Agent Client Protocol").version(
|
|
7322
|
+
program2.name("casper").description("Web client for kiro-cli over the Agent Client Protocol").version(VERSION2, "-v, --version").showHelpAfterError().allowUnknownOption(false).allowExcessArguments(false).addHelpText("after", `
|
|
6829
7323
|
Settings live in ${configFilePath()}.
|
|
6830
7324
|
Update with: npm install -g @joeyshi12/casper`);
|
|
6831
7325
|
program2.command("start").description("run the server in the foreground").allowUnknownOption(false).allowExcessArguments(false).action(async () => {
|
|
@@ -6840,6 +7334,9 @@ Update with: npm install -g @joeyshi12/casper`);
|
|
|
6840
7334
|
program2.command("doctor").description("check kiro-cli, settings, data directory and web app").allowUnknownOption(false).allowExcessArguments(false).action(async () => {
|
|
6841
7335
|
process.exitCode = (await Promise.resolve().then(() => (init_doctor(), doctor_exports))).doctor();
|
|
6842
7336
|
});
|
|
7337
|
+
program2.command("mcp").description("run the generative-UI MCP server on stdio (kiro spawns this itself)").allowUnknownOption(false).allowExcessArguments(false).action(async () => {
|
|
7338
|
+
(await Promise.resolve().then(() => (init_server2(), server_exports2))).runMcpServer();
|
|
7339
|
+
});
|
|
6843
7340
|
const service = program2.command("service").description("manage the systemd user service");
|
|
6844
7341
|
const svcCommand = (name, describe, run) => service.command(name).description(describe).allowUnknownOption(false).allowExcessArguments(false).action(async () => {
|
|
6845
7342
|
process.exitCode = run(await Promise.resolve().then(() => (init_service(), service_exports)));
|