@kimbho/kimbho-cli 0.1.18 → 0.1.20
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/index.cjs +913 -58
- package/dist/index.cjs.map +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10612,7 +10612,7 @@ var {
|
|
|
10612
10612
|
// package.json
|
|
10613
10613
|
var package_default = {
|
|
10614
10614
|
name: "@kimbho/kimbho-cli",
|
|
10615
|
-
version: "0.1.
|
|
10615
|
+
version: "0.1.20",
|
|
10616
10616
|
description: "Kimbho CLI is a terminal-native coding agent for planning, execution, and verification.",
|
|
10617
10617
|
type: "module",
|
|
10618
10618
|
engines: {
|
|
@@ -16124,6 +16124,10 @@ async function loadCustomAgents(cwd) {
|
|
|
16124
16124
|
];
|
|
16125
16125
|
});
|
|
16126
16126
|
}
|
|
16127
|
+
async function loadCustomAgentById(cwd, id) {
|
|
16128
|
+
const agents = await loadCustomAgents(cwd);
|
|
16129
|
+
return agents.find((agent) => agent.id === id) ?? null;
|
|
16130
|
+
}
|
|
16127
16131
|
async function loadAgentTeams(cwd) {
|
|
16128
16132
|
const records = await loadMarkdownRecords(resolveAgentTeamDir(cwd));
|
|
16129
16133
|
return records.map(({ filePath, source }) => {
|
|
@@ -16142,6 +16146,10 @@ async function loadAgentTeams(cwd) {
|
|
|
16142
16146
|
};
|
|
16143
16147
|
});
|
|
16144
16148
|
}
|
|
16149
|
+
async function loadAgentTeamById(cwd, id) {
|
|
16150
|
+
const teams = await loadAgentTeams(cwd);
|
|
16151
|
+
return teams.find((team) => team.id === id) ?? null;
|
|
16152
|
+
}
|
|
16145
16153
|
async function createCustomAgentFile(cwd, id, baseRole, options = {}) {
|
|
16146
16154
|
const directory = resolveCustomAgentDir(cwd);
|
|
16147
16155
|
const filePath = import_node_path5.default.join(directory, `${id}.md`);
|
|
@@ -16176,6 +16184,11 @@ async function createCustomAgentFile(cwd, id, baseRole, options = {}) {
|
|
|
16176
16184
|
`, "utf8");
|
|
16177
16185
|
return filePath;
|
|
16178
16186
|
}
|
|
16187
|
+
async function deleteCustomAgentFile(cwd, id) {
|
|
16188
|
+
const filePath = import_node_path5.default.join(resolveCustomAgentDir(cwd), `${id}.md`);
|
|
16189
|
+
await (0, import_promises5.rm)(filePath);
|
|
16190
|
+
return filePath;
|
|
16191
|
+
}
|
|
16179
16192
|
async function createAgentTeamFile(cwd, id, agentIds, label) {
|
|
16180
16193
|
const directory = resolveAgentTeamDir(cwd);
|
|
16181
16194
|
const filePath = import_node_path5.default.join(directory, `${id}.md`);
|
|
@@ -16199,6 +16212,11 @@ async function createAgentTeamFile(cwd, id, agentIds, label) {
|
|
|
16199
16212
|
`, "utf8");
|
|
16200
16213
|
return filePath;
|
|
16201
16214
|
}
|
|
16215
|
+
async function deleteAgentTeamFile(cwd, id) {
|
|
16216
|
+
const filePath = import_node_path5.default.join(resolveAgentTeamDir(cwd), `${id}.md`);
|
|
16217
|
+
await (0, import_promises5.rm)(filePath);
|
|
16218
|
+
return filePath;
|
|
16219
|
+
}
|
|
16202
16220
|
function scoreCustomAgentMatch(definition, task, request) {
|
|
16203
16221
|
if (definition.baseRole !== task.agentRole) {
|
|
16204
16222
|
return -1;
|
|
@@ -18290,6 +18308,175 @@ var KNOWN_SCAFFOLD_PRESETS = [
|
|
|
18290
18308
|
"static-landing",
|
|
18291
18309
|
"kimbho-cli-monorepo"
|
|
18292
18310
|
];
|
|
18311
|
+
function inferVisualAdjustment(goal) {
|
|
18312
|
+
const normalized = goal.toLowerCase();
|
|
18313
|
+
if (!normalized.includes("background") && !normalized.includes("gradient") && !normalized.includes("theme")) {
|
|
18314
|
+
return null;
|
|
18315
|
+
}
|
|
18316
|
+
if (normalized.includes("green")) {
|
|
18317
|
+
return {
|
|
18318
|
+
summaryLabel: "green background",
|
|
18319
|
+
background: "linear-gradient(180deg, #f4fff6 0%, #d8f3dc 100%)"
|
|
18320
|
+
};
|
|
18321
|
+
}
|
|
18322
|
+
if (normalized.includes("amber") || normalized.includes("gold") || normalized.includes("orange")) {
|
|
18323
|
+
return {
|
|
18324
|
+
summaryLabel: "amber background",
|
|
18325
|
+
background: "linear-gradient(180deg, #fff8e7 0%, #f7d08a 100%)"
|
|
18326
|
+
};
|
|
18327
|
+
}
|
|
18328
|
+
if (normalized.includes("blue")) {
|
|
18329
|
+
return {
|
|
18330
|
+
summaryLabel: "blue background",
|
|
18331
|
+
background: "linear-gradient(180deg, #eef6ff 0%, #cfe3ff 100%)"
|
|
18332
|
+
};
|
|
18333
|
+
}
|
|
18334
|
+
if (normalized.includes("pink") || normalized.includes("rose")) {
|
|
18335
|
+
return {
|
|
18336
|
+
summaryLabel: "rose background",
|
|
18337
|
+
background: "linear-gradient(180deg, #fff3f8 0%, #ffd6e7 100%)"
|
|
18338
|
+
};
|
|
18339
|
+
}
|
|
18340
|
+
if (normalized.includes("purple") || normalized.includes("violet")) {
|
|
18341
|
+
return {
|
|
18342
|
+
summaryLabel: "violet background",
|
|
18343
|
+
background: "linear-gradient(180deg, #f6f2ff 0%, #ddd1ff 100%)"
|
|
18344
|
+
};
|
|
18345
|
+
}
|
|
18346
|
+
return null;
|
|
18347
|
+
}
|
|
18348
|
+
function looksLikeVisualAdjustmentGoal(value) {
|
|
18349
|
+
return inferVisualAdjustment(value) !== null;
|
|
18350
|
+
}
|
|
18351
|
+
function inferSupplementalPages(goal, kind) {
|
|
18352
|
+
const normalized = goal.toLowerCase();
|
|
18353
|
+
const requestSignals = [
|
|
18354
|
+
"add more pages",
|
|
18355
|
+
"add pages",
|
|
18356
|
+
"more pages",
|
|
18357
|
+
"new pages",
|
|
18358
|
+
"new page",
|
|
18359
|
+
"additional pages",
|
|
18360
|
+
"additional page"
|
|
18361
|
+
];
|
|
18362
|
+
const requested = /* @__PURE__ */ new Set();
|
|
18363
|
+
const specificPageSignals = [
|
|
18364
|
+
["about", "about"],
|
|
18365
|
+
["contact", "contact"],
|
|
18366
|
+
["archive", "archive"],
|
|
18367
|
+
["journal", "journal"],
|
|
18368
|
+
["stories", "stories"],
|
|
18369
|
+
["story", "story"],
|
|
18370
|
+
["menu", "menu"],
|
|
18371
|
+
["reservation", "reservations"],
|
|
18372
|
+
["reservations", "reservations"],
|
|
18373
|
+
["shop", "shop"],
|
|
18374
|
+
["services", "services"]
|
|
18375
|
+
];
|
|
18376
|
+
for (const [signal, slug] of specificPageSignals) {
|
|
18377
|
+
if (normalized.includes(signal)) {
|
|
18378
|
+
requested.add(slug);
|
|
18379
|
+
}
|
|
18380
|
+
}
|
|
18381
|
+
const isPageExpansionRequest = requested.size > 0 || requestSignals.some((signal) => normalized.includes(signal));
|
|
18382
|
+
if (!isPageExpansionRequest) {
|
|
18383
|
+
return null;
|
|
18384
|
+
}
|
|
18385
|
+
if (requested.size === 0) {
|
|
18386
|
+
if (kind === "blog") {
|
|
18387
|
+
requested.add("about");
|
|
18388
|
+
requested.add("archive");
|
|
18389
|
+
requested.add("contact");
|
|
18390
|
+
} else if (kind === "restaurant") {
|
|
18391
|
+
requested.add("menu");
|
|
18392
|
+
requested.add("story");
|
|
18393
|
+
requested.add("reservations");
|
|
18394
|
+
} else if (kind === "storefront") {
|
|
18395
|
+
requested.add("shop");
|
|
18396
|
+
requested.add("story");
|
|
18397
|
+
requested.add("contact");
|
|
18398
|
+
} else {
|
|
18399
|
+
requested.add("about");
|
|
18400
|
+
requested.add("services");
|
|
18401
|
+
requested.add("contact");
|
|
18402
|
+
}
|
|
18403
|
+
}
|
|
18404
|
+
const copyBySlug = {
|
|
18405
|
+
about: {
|
|
18406
|
+
title: "About",
|
|
18407
|
+
eyebrow: "Studio notes",
|
|
18408
|
+
lede: "A calmer overview of the people, perspective, and intent behind the project.",
|
|
18409
|
+
body: "Use this page to explain what the site stands for, who it is for, and why the work matters. Keep it human and specific."
|
|
18410
|
+
},
|
|
18411
|
+
contact: {
|
|
18412
|
+
title: "Contact",
|
|
18413
|
+
eyebrow: "Get in touch",
|
|
18414
|
+
lede: "A simple route for collaborations, questions, bookings, or thoughtful replies.",
|
|
18415
|
+
body: "Replace this copy with the right contact method, social links, newsletter details, or inquiry instructions."
|
|
18416
|
+
},
|
|
18417
|
+
archive: {
|
|
18418
|
+
title: "Archive",
|
|
18419
|
+
eyebrow: "Browse the back catalog",
|
|
18420
|
+
lede: "A clean index for essays, notes, dispatches, and the posts worth resurfacing.",
|
|
18421
|
+
body: "Turn this into a chronological archive, tag explorer, or featured reading list as the site grows."
|
|
18422
|
+
},
|
|
18423
|
+
journal: {
|
|
18424
|
+
title: "Journal",
|
|
18425
|
+
eyebrow: "Field notes",
|
|
18426
|
+
lede: "A lighter-weight stream for updates, drafts, studio notes, and ongoing experiments.",
|
|
18427
|
+
body: "Use this page for smaller entries that do not need the weight of longform essays."
|
|
18428
|
+
},
|
|
18429
|
+
stories: {
|
|
18430
|
+
title: "Stories",
|
|
18431
|
+
eyebrow: "Featured writing",
|
|
18432
|
+
lede: "A front door for standout essays, case studies, or narrative pieces.",
|
|
18433
|
+
body: "Pull your strongest writing forward here so visitors can quickly see the tone and quality of the work."
|
|
18434
|
+
},
|
|
18435
|
+
story: {
|
|
18436
|
+
title: "Our Story",
|
|
18437
|
+
eyebrow: "Behind the project",
|
|
18438
|
+
lede: "A richer page for origin, process, values, and the details that build trust.",
|
|
18439
|
+
body: "Tell the story behind the brand or studio in a way that feels personal instead of corporate."
|
|
18440
|
+
},
|
|
18441
|
+
menu: {
|
|
18442
|
+
title: "Menu",
|
|
18443
|
+
eyebrow: "Current offerings",
|
|
18444
|
+
lede: "A dedicated place for featured dishes, seasonal highlights, and signature favorites.",
|
|
18445
|
+
body: "Replace this with menu sections, tasting notes, pricing context, and dietary guidance."
|
|
18446
|
+
},
|
|
18447
|
+
reservations: {
|
|
18448
|
+
title: "Reservations",
|
|
18449
|
+
eyebrow: "Plan your visit",
|
|
18450
|
+
lede: "A conversion-focused page for table bookings, group dining, and private events.",
|
|
18451
|
+
body: "Use this space for booking links, service windows, cancellation policy, and special-event details."
|
|
18452
|
+
},
|
|
18453
|
+
shop: {
|
|
18454
|
+
title: "Shop",
|
|
18455
|
+
eyebrow: "Browse the collection",
|
|
18456
|
+
lede: "A tighter landing point for products, drops, featured items, or curated collections.",
|
|
18457
|
+
body: "Turn this into a product grid, collection overview, or conversion path into your checkout flow."
|
|
18458
|
+
},
|
|
18459
|
+
services: {
|
|
18460
|
+
title: "Services",
|
|
18461
|
+
eyebrow: "What we do",
|
|
18462
|
+
lede: "A practical overview of offers, engagements, deliverables, and working style.",
|
|
18463
|
+
body: "Use this page to clarify the services, retainers, or project formats you want visitors to understand."
|
|
18464
|
+
}
|
|
18465
|
+
};
|
|
18466
|
+
return Array.from(requested).map((slug) => {
|
|
18467
|
+
const resolved = copyBySlug[slug] ?? copyBySlug.about;
|
|
18468
|
+
return {
|
|
18469
|
+
slug,
|
|
18470
|
+
title: resolved.title,
|
|
18471
|
+
eyebrow: resolved.eyebrow,
|
|
18472
|
+
lede: resolved.lede,
|
|
18473
|
+
body: resolved.body
|
|
18474
|
+
};
|
|
18475
|
+
});
|
|
18476
|
+
}
|
|
18477
|
+
function looksLikePageExpansionGoal(value) {
|
|
18478
|
+
return inferSupplementalPages(value, inferLandingKind(value)) !== null;
|
|
18479
|
+
}
|
|
18293
18480
|
function looksLikeStaticLandingGoal(value) {
|
|
18294
18481
|
const normalized = value.toLowerCase();
|
|
18295
18482
|
const backendSignals = [
|
|
@@ -18348,6 +18535,12 @@ function looksLikeStaticLandingGoal(value) {
|
|
|
18348
18535
|
if (normalized.includes("blog") && (normalized.includes("make") || normalized.includes("improve") || normalized.includes("enhance") || normalized.includes("redesign")) && !backendSignals.some((signal) => normalized.includes(signal))) {
|
|
18349
18536
|
return true;
|
|
18350
18537
|
}
|
|
18538
|
+
if (looksLikeVisualAdjustmentGoal(normalized) && !backendSignals.some((signal) => normalized.includes(signal))) {
|
|
18539
|
+
return true;
|
|
18540
|
+
}
|
|
18541
|
+
if (looksLikePageExpansionGoal(normalized) && !backendSignals.some((signal) => normalized.includes(signal))) {
|
|
18542
|
+
return true;
|
|
18543
|
+
}
|
|
18351
18544
|
return false;
|
|
18352
18545
|
}
|
|
18353
18546
|
function sanitizeName(value) {
|
|
@@ -18550,6 +18743,195 @@ function renderNextLandingPage(title, content) {
|
|
|
18550
18743
|
function renderPagesRouterLandingPage(title, content) {
|
|
18551
18744
|
return renderNextLandingPage(title, content);
|
|
18552
18745
|
}
|
|
18746
|
+
function renderNextSupplementalPage(siteTitle, page) {
|
|
18747
|
+
return [
|
|
18748
|
+
`const siteTitle = ${JSON.stringify(siteTitle)};`,
|
|
18749
|
+
`const pageTitle = ${JSON.stringify(page.title)};`,
|
|
18750
|
+
"",
|
|
18751
|
+
"export default function SupplementalPage() {",
|
|
18752
|
+
" return (",
|
|
18753
|
+
" <main",
|
|
18754
|
+
" style={{",
|
|
18755
|
+
" minHeight: '100vh',",
|
|
18756
|
+
" background: 'linear-gradient(180deg, #fffaf2 0%, #f4ede2 100%)',",
|
|
18757
|
+
" color: '#1f1812',",
|
|
18758
|
+
` fontFamily: "Georgia, 'Times New Roman', serif"`,
|
|
18759
|
+
" }}",
|
|
18760
|
+
" >",
|
|
18761
|
+
" <section style={{ maxWidth: 920, margin: '0 auto', padding: '72px 20px 96px' }}>",
|
|
18762
|
+
` <p style={{ textTransform: 'uppercase', letterSpacing: '0.18em', fontSize: 12, color: '#9b5c34', margin: 0 }}>{${JSON.stringify(page.eyebrow)}}</p>`,
|
|
18763
|
+
" <h1 style={{ fontSize: 'clamp(2.8rem, 7vw, 4.8rem)', lineHeight: 0.95, margin: '16px 0 18px' }}>{pageTitle}</h1>",
|
|
18764
|
+
` <p style={{ maxWidth: 680, lineHeight: 1.7, fontSize: '1.08rem', color: '#46372d', margin: 0 }}>{${JSON.stringify(page.lede)}}</p>`,
|
|
18765
|
+
" <section",
|
|
18766
|
+
" style={{",
|
|
18767
|
+
" marginTop: 28,",
|
|
18768
|
+
" background: 'rgba(255,255,255,0.82)',",
|
|
18769
|
+
" border: '1px solid rgba(31,24,18,0.12)',",
|
|
18770
|
+
" borderRadius: 28,",
|
|
18771
|
+
" padding: 28,",
|
|
18772
|
+
" boxShadow: '0 18px 40px rgba(31,24,18,0.06)'",
|
|
18773
|
+
" }}",
|
|
18774
|
+
" >",
|
|
18775
|
+
` <p style={{ marginTop: 0, marginBottom: 0, lineHeight: 1.75, color: '#56453a' }}>{${JSON.stringify(page.body)}}</p>`,
|
|
18776
|
+
" </section>",
|
|
18777
|
+
" <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 28 }}>",
|
|
18778
|
+
" <a href='/' style={{ background: '#c96f3b', color: '#fff', padding: '14px 20px', borderRadius: 999, textDecoration: 'none', fontWeight: 700 }}>Back home</a>",
|
|
18779
|
+
" <span style={{ alignSelf: 'center', color: '#7b6659' }}>{siteTitle}</span>",
|
|
18780
|
+
" </div>",
|
|
18781
|
+
" </section>",
|
|
18782
|
+
" </main>",
|
|
18783
|
+
" );",
|
|
18784
|
+
"}"
|
|
18785
|
+
].join("\n");
|
|
18786
|
+
}
|
|
18787
|
+
function renderStaticSupplementalPage(siteTitle, page) {
|
|
18788
|
+
return [
|
|
18789
|
+
"<!doctype html>",
|
|
18790
|
+
'<html lang="en">',
|
|
18791
|
+
" <head>",
|
|
18792
|
+
' <meta charset="UTF-8" />',
|
|
18793
|
+
' <meta name="viewport" content="width=device-width, initial-scale=1.0" />',
|
|
18794
|
+
` <title>${page.title} | ${siteTitle}</title>`,
|
|
18795
|
+
' <link rel="stylesheet" href="./styles.css" />',
|
|
18796
|
+
" </head>",
|
|
18797
|
+
" <body>",
|
|
18798
|
+
' <main class="shell">',
|
|
18799
|
+
' <section class="hero">',
|
|
18800
|
+
` <p class="eyebrow">${page.eyebrow}</p>`,
|
|
18801
|
+
` <h1>${page.title}</h1>`,
|
|
18802
|
+
` <p class="lede">${page.lede}</p>`,
|
|
18803
|
+
" </section>",
|
|
18804
|
+
' <section class="story">',
|
|
18805
|
+
` <p>${page.body}</p>`,
|
|
18806
|
+
" </section>",
|
|
18807
|
+
' <div class="actions">',
|
|
18808
|
+
' <a href="./index.html" class="button primary">Back home</a>',
|
|
18809
|
+
` <a href="./index.html" class="button secondary">${siteTitle}</a>`,
|
|
18810
|
+
" </div>",
|
|
18811
|
+
" </main>",
|
|
18812
|
+
" </body>",
|
|
18813
|
+
"</html>"
|
|
18814
|
+
].join("\n");
|
|
18815
|
+
}
|
|
18816
|
+
async function inferExistingSiteTitle(cwd, target, fallbackTitle) {
|
|
18817
|
+
const source = await (0, import_promises10.readFile)(import_node_path10.default.join(cwd, target.pagePath), "utf8");
|
|
18818
|
+
const constantMatch = source.match(/const\s+title\s*=\s*["'`](.+?)["'`]/);
|
|
18819
|
+
if (constantMatch?.[1]) {
|
|
18820
|
+
return constantMatch[1];
|
|
18821
|
+
}
|
|
18822
|
+
const headingMatch = source.match(/<h1[^>]*>\s*([^<]+?)\s*<\/h1>/);
|
|
18823
|
+
if (headingMatch?.[1]) {
|
|
18824
|
+
return headingMatch[1];
|
|
18825
|
+
}
|
|
18826
|
+
return fallbackTitle;
|
|
18827
|
+
}
|
|
18828
|
+
function insertNextPageLinks(source, pages) {
|
|
18829
|
+
if (pages.every((page) => source.includes(`href='/${page.slug}'`) || source.includes(`href="/${page.slug}"`))) {
|
|
18830
|
+
return source;
|
|
18831
|
+
}
|
|
18832
|
+
const block = [
|
|
18833
|
+
" <section style={{ marginTop: 26, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 14 }}>",
|
|
18834
|
+
...pages.map((page) => ` <a href='/${page.slug}' style={{ display: 'block', textDecoration: 'none', padding: '18px 20px', borderRadius: 22, background: 'rgba(255,255,255,0.82)', border: '1px solid rgba(31,24,18,0.1)', color: '#1f1812', boxShadow: '0 14px 32px rgba(31,24,18,0.05)' }}><strong>${page.title}</strong><br /><span style={{ color: '#6c5a4e' }}>Explore ${page.title.toLowerCase()}.</span></a>`),
|
|
18835
|
+
" </section>"
|
|
18836
|
+
].join("\n");
|
|
18837
|
+
if (source.includes("</main>")) {
|
|
18838
|
+
return source.replace(/(\s*)<\/main>/, `
|
|
18839
|
+
${block}
|
|
18840
|
+
$1</main>`);
|
|
18841
|
+
}
|
|
18842
|
+
return source;
|
|
18843
|
+
}
|
|
18844
|
+
function insertStaticPageLinks(source, pages) {
|
|
18845
|
+
if (pages.every((page) => source.includes(`./${page.slug}.html`) || source.includes(`"${page.slug}.html"`))) {
|
|
18846
|
+
return source;
|
|
18847
|
+
}
|
|
18848
|
+
const block = [
|
|
18849
|
+
' <section class="grid">',
|
|
18850
|
+
...pages.map((page) => ` <article class="card"><h2>${page.title}</h2><p>${page.lede}</p><a class="button secondary" href="./${page.slug}.html">Open ${page.title}</a></article>`),
|
|
18851
|
+
" </section>"
|
|
18852
|
+
].join("\n");
|
|
18853
|
+
if (source.includes("</main>")) {
|
|
18854
|
+
return source.replace(/(\s*)<\/main>/, `
|
|
18855
|
+
${block}
|
|
18856
|
+
$1</main>`);
|
|
18857
|
+
}
|
|
18858
|
+
return source;
|
|
18859
|
+
}
|
|
18860
|
+
async function applyExistingStaticPageExpansion(cwd, goal, target) {
|
|
18861
|
+
const pages = inferSupplementalPages(goal, inferLandingKind(goal));
|
|
18862
|
+
if (!pages) {
|
|
18863
|
+
return null;
|
|
18864
|
+
}
|
|
18865
|
+
const projectName = inferProjectName(goal, cwd);
|
|
18866
|
+
const siteTitle = await inferExistingSiteTitle(cwd, target, inferLandingTitle(goal, projectName));
|
|
18867
|
+
const files = {};
|
|
18868
|
+
const artifacts = [];
|
|
18869
|
+
let createdPages = 0;
|
|
18870
|
+
if (target.kind === "next-app") {
|
|
18871
|
+
for (const page of pages) {
|
|
18872
|
+
const relativePath = `src/app/${page.slug}/page.tsx`;
|
|
18873
|
+
const absolutePath = import_node_path10.default.join(cwd, relativePath);
|
|
18874
|
+
if (!await pathExists(absolutePath)) {
|
|
18875
|
+
files[relativePath] = renderNextSupplementalPage(siteTitle, page);
|
|
18876
|
+
createdPages += 1;
|
|
18877
|
+
}
|
|
18878
|
+
artifacts.push(absolutePath);
|
|
18879
|
+
}
|
|
18880
|
+
const currentSource = await (0, import_promises10.readFile)(import_node_path10.default.join(cwd, target.pagePath), "utf8");
|
|
18881
|
+
const nextSource = insertNextPageLinks(currentSource, pages);
|
|
18882
|
+
if (nextSource !== currentSource) {
|
|
18883
|
+
files[target.pagePath] = nextSource;
|
|
18884
|
+
}
|
|
18885
|
+
} else if (target.kind === "next-pages") {
|
|
18886
|
+
for (const page of pages) {
|
|
18887
|
+
const relativePath = `src/pages/${page.slug}.tsx`;
|
|
18888
|
+
const absolutePath = import_node_path10.default.join(cwd, relativePath);
|
|
18889
|
+
if (!await pathExists(absolutePath)) {
|
|
18890
|
+
files[relativePath] = renderNextSupplementalPage(siteTitle, page);
|
|
18891
|
+
createdPages += 1;
|
|
18892
|
+
}
|
|
18893
|
+
artifacts.push(absolutePath);
|
|
18894
|
+
}
|
|
18895
|
+
const currentSource = await (0, import_promises10.readFile)(import_node_path10.default.join(cwd, target.pagePath), "utf8");
|
|
18896
|
+
const nextSource = insertNextPageLinks(currentSource, pages);
|
|
18897
|
+
if (nextSource !== currentSource) {
|
|
18898
|
+
files[target.pagePath] = nextSource;
|
|
18899
|
+
}
|
|
18900
|
+
} else {
|
|
18901
|
+
for (const page of pages) {
|
|
18902
|
+
const relativePath = `${page.slug}.html`;
|
|
18903
|
+
const absolutePath = import_node_path10.default.join(cwd, relativePath);
|
|
18904
|
+
if (!await pathExists(absolutePath)) {
|
|
18905
|
+
files[relativePath] = renderStaticSupplementalPage(siteTitle, page);
|
|
18906
|
+
createdPages += 1;
|
|
18907
|
+
}
|
|
18908
|
+
artifacts.push(absolutePath);
|
|
18909
|
+
}
|
|
18910
|
+
const currentSource = await (0, import_promises10.readFile)(import_node_path10.default.join(cwd, target.pagePath), "utf8");
|
|
18911
|
+
const nextSource = insertStaticPageLinks(currentSource, pages);
|
|
18912
|
+
if (nextSource !== currentSource) {
|
|
18913
|
+
files[target.pagePath] = nextSource;
|
|
18914
|
+
}
|
|
18915
|
+
}
|
|
18916
|
+
const writtenArtifacts = Object.keys(files).length > 0 ? await writeFiles(cwd, files) : [];
|
|
18917
|
+
if (createdPages === 0 && writtenArtifacts.length === 0) {
|
|
18918
|
+
return {
|
|
18919
|
+
preset: "static-landing",
|
|
18920
|
+
projectName,
|
|
18921
|
+
summary: `Confirmed the requested pages already exist: ${pages.map((page) => page.title).join(", ")}.`,
|
|
18922
|
+
artifacts: artifacts.sort((left, right) => left.localeCompare(right))
|
|
18923
|
+
};
|
|
18924
|
+
}
|
|
18925
|
+
return {
|
|
18926
|
+
preset: "static-landing",
|
|
18927
|
+
projectName,
|
|
18928
|
+
summary: `Added ${createdPages > 0 ? createdPages : pages.length} supplemental page${(createdPages > 0 ? createdPages : pages.length) === 1 ? "" : "s"}: ${pages.map((page) => page.title).join(", ")}.`,
|
|
18929
|
+
artifacts: Array.from(/* @__PURE__ */ new Set([
|
|
18930
|
+
...artifacts,
|
|
18931
|
+
...writtenArtifacts
|
|
18932
|
+
])).sort((left, right) => left.localeCompare(right))
|
|
18933
|
+
};
|
|
18934
|
+
}
|
|
18553
18935
|
async function detectExistingStaticTarget(cwd) {
|
|
18554
18936
|
const nextAppPage = import_node_path10.default.join(cwd, "src/app/page.tsx");
|
|
18555
18937
|
if (await pathExists(nextAppPage)) {
|
|
@@ -18575,7 +18957,80 @@ async function detectExistingStaticTarget(cwd) {
|
|
|
18575
18957
|
}
|
|
18576
18958
|
return null;
|
|
18577
18959
|
}
|
|
18960
|
+
function rewriteBackgroundInSource(source, background) {
|
|
18961
|
+
const inlinePatterns = [
|
|
18962
|
+
[/background:\s*'[^']*'/, `background: '${background}'`],
|
|
18963
|
+
[/background:\s*"[^"]*"/, `background: "${background}"`],
|
|
18964
|
+
[/background:\s*`[^`]*`/, `background: \`${background}\``]
|
|
18965
|
+
];
|
|
18966
|
+
for (const [pattern, replacement] of inlinePatterns) {
|
|
18967
|
+
if (pattern.test(source)) {
|
|
18968
|
+
return source.replace(pattern, replacement);
|
|
18969
|
+
}
|
|
18970
|
+
}
|
|
18971
|
+
const cssPatterns = [
|
|
18972
|
+
[/background:\s*[^;]+;/, `background: ${background};`],
|
|
18973
|
+
[/background-color:\s*[^;]+;/, `background: ${background};`]
|
|
18974
|
+
];
|
|
18975
|
+
for (const [pattern, replacement] of cssPatterns) {
|
|
18976
|
+
if (pattern.test(source)) {
|
|
18977
|
+
return source.replace(pattern, replacement);
|
|
18978
|
+
}
|
|
18979
|
+
}
|
|
18980
|
+
return source;
|
|
18981
|
+
}
|
|
18982
|
+
async function applyExistingStaticVisualAdjustment(cwd, goal, target) {
|
|
18983
|
+
const adjustment = inferVisualAdjustment(goal);
|
|
18984
|
+
if (!adjustment) {
|
|
18985
|
+
return null;
|
|
18986
|
+
}
|
|
18987
|
+
const candidatePaths = [
|
|
18988
|
+
target.pagePath,
|
|
18989
|
+
target.kind === "next-app" ? "src/app/globals.css" : null,
|
|
18990
|
+
target.kind === "next-pages" ? "styles.css" : null,
|
|
18991
|
+
target.kind === "static-html" ? "styles.css" : null
|
|
18992
|
+
].filter((value) => Boolean(value));
|
|
18993
|
+
for (const relativePath of candidatePaths) {
|
|
18994
|
+
const absolutePath = import_node_path10.default.join(cwd, relativePath);
|
|
18995
|
+
if (!await pathExists(absolutePath)) {
|
|
18996
|
+
continue;
|
|
18997
|
+
}
|
|
18998
|
+
const currentSource = await (0, import_promises10.readFile)(absolutePath, "utf8");
|
|
18999
|
+
if (currentSource.includes(adjustment.background)) {
|
|
19000
|
+
return {
|
|
19001
|
+
preset: "static-landing",
|
|
19002
|
+
projectName: inferProjectName(goal, cwd),
|
|
19003
|
+
summary: `${relativePath} already uses the requested ${adjustment.summaryLabel}.`,
|
|
19004
|
+
artifacts: [
|
|
19005
|
+
absolutePath
|
|
19006
|
+
]
|
|
19007
|
+
};
|
|
19008
|
+
}
|
|
19009
|
+
const nextSource = rewriteBackgroundInSource(currentSource, adjustment.background);
|
|
19010
|
+
if (nextSource === currentSource) {
|
|
19011
|
+
continue;
|
|
19012
|
+
}
|
|
19013
|
+
const artifacts = await writeFiles(cwd, {
|
|
19014
|
+
[relativePath]: nextSource
|
|
19015
|
+
});
|
|
19016
|
+
return {
|
|
19017
|
+
preset: "static-landing",
|
|
19018
|
+
projectName: inferProjectName(goal, cwd),
|
|
19019
|
+
summary: `Updated ${relativePath} with a ${adjustment.summaryLabel}.`,
|
|
19020
|
+
artifacts
|
|
19021
|
+
};
|
|
19022
|
+
}
|
|
19023
|
+
return null;
|
|
19024
|
+
}
|
|
18578
19025
|
async function adaptExistingStaticLanding(cwd, projectName, goal, target) {
|
|
19026
|
+
const pageExpansionResult = await applyExistingStaticPageExpansion(cwd, goal, target);
|
|
19027
|
+
if (pageExpansionResult) {
|
|
19028
|
+
return pageExpansionResult;
|
|
19029
|
+
}
|
|
19030
|
+
const adjustedResult = await applyExistingStaticVisualAdjustment(cwd, goal, target);
|
|
19031
|
+
if (adjustedResult) {
|
|
19032
|
+
return adjustedResult;
|
|
19033
|
+
}
|
|
18579
19034
|
const title = inferLandingTitle(goal, projectName);
|
|
18580
19035
|
const content = buildLandingContent(title, inferLandingKind(goal));
|
|
18581
19036
|
const files = {};
|
|
@@ -19364,6 +19819,9 @@ function isVerificationShellCommand(command) {
|
|
|
19364
19819
|
const normalized = command.trim().toLowerCase();
|
|
19365
19820
|
return VERIFICATION_SHELL_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix} `));
|
|
19366
19821
|
}
|
|
19822
|
+
function isLowRiskScaffoldRequest(input) {
|
|
19823
|
+
return input.preset === "static-landing" && typeof input.goal === "string" && (looksLikeVisualAdjustmentGoal(input.goal) || looksLikePageExpansionGoal(input.goal));
|
|
19824
|
+
}
|
|
19367
19825
|
function isDestructiveShellCommand(command) {
|
|
19368
19826
|
return DESTRUCTIVE_SHELL_PATTERNS.some((pattern) => pattern.test(command));
|
|
19369
19827
|
}
|
|
@@ -19432,8 +19890,9 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
19432
19890
|
const sandboxMode = context.sandboxMode ?? "workspace-write";
|
|
19433
19891
|
const approvalMode = context.approvalMode ?? "manual";
|
|
19434
19892
|
const command = typeof input.command === "string" ? input.command : "";
|
|
19893
|
+
const isVerificationCommand2 = isVerificationShellCommand(command);
|
|
19435
19894
|
if (sandboxMode === "read-only") {
|
|
19436
|
-
if (toolId === "shell.exec" && (isReadOnlyShellCommand(command) ||
|
|
19895
|
+
if ((toolId === "shell.exec" || toolId === "tests.run") && (isReadOnlyShellCommand(command) || isVerificationCommand2)) {
|
|
19437
19896
|
return null;
|
|
19438
19897
|
}
|
|
19439
19898
|
if (descriptor.permission !== "safe") {
|
|
@@ -19445,7 +19904,10 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
19445
19904
|
return new ToolApprovalRequiredError(createApprovalRequest(toolId, input, descriptor, context, `Approval required for destructive shell command: ${command}`));
|
|
19446
19905
|
}
|
|
19447
19906
|
}
|
|
19448
|
-
if (toolId === "shell.exec" &&
|
|
19907
|
+
if ((toolId === "shell.exec" || toolId === "tests.run") && isVerificationCommand2) {
|
|
19908
|
+
return null;
|
|
19909
|
+
}
|
|
19910
|
+
if (toolId === "scaffold.generate" && isLowRiskScaffoldRequest(input)) {
|
|
19449
19911
|
return null;
|
|
19450
19912
|
}
|
|
19451
19913
|
if ((toolId === "file.write" || toolId === "file.patch") && sandboxMode === "workspace-write") {
|
|
@@ -27626,6 +28088,37 @@ var MCP_INVENTORY_TIMEOUT_MS = 8e3;
|
|
|
27626
28088
|
function toMcpToolId(serverName, toolName) {
|
|
27627
28089
|
return `mcp.${serverName}.${toolName}`;
|
|
27628
28090
|
}
|
|
28091
|
+
function normalizeMcpCommandSegment(value) {
|
|
28092
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
28093
|
+
}
|
|
28094
|
+
async function resolveMcpServerInventoryByReference(cwd, serverReference) {
|
|
28095
|
+
const inventory = await loadMcpServerInventory(cwd);
|
|
28096
|
+
const normalizedReference = normalizeMcpCommandSegment(serverReference);
|
|
28097
|
+
const server = inventory.find((candidate) => candidate.name === serverReference || normalizeMcpCommandSegment(candidate.name) === normalizedReference);
|
|
28098
|
+
if (!server) {
|
|
28099
|
+
throw new Error(`MCP server ${serverReference} is not configured or did not respond.`);
|
|
28100
|
+
}
|
|
28101
|
+
if (server.warning) {
|
|
28102
|
+
throw new Error(`MCP server ${server.name} is unavailable: ${server.warning}`);
|
|
28103
|
+
}
|
|
28104
|
+
return server;
|
|
28105
|
+
}
|
|
28106
|
+
async function resolveMcpPromptReference(cwd, serverReference, promptReference) {
|
|
28107
|
+
const server = await resolveMcpServerInventoryByReference(cwd, serverReference);
|
|
28108
|
+
const normalizedPromptReference = normalizeMcpCommandSegment(promptReference);
|
|
28109
|
+
const prompt = server.prompts.find((candidate) => candidate.name === promptReference || normalizeMcpCommandSegment(candidate.name) === normalizedPromptReference);
|
|
28110
|
+
if (!prompt) {
|
|
28111
|
+
throw new Error(`MCP prompt ${promptReference} was not found on server ${server.name}.`);
|
|
28112
|
+
}
|
|
28113
|
+
return {
|
|
28114
|
+
serverName: server.name,
|
|
28115
|
+
promptName: prompt.name
|
|
28116
|
+
};
|
|
28117
|
+
}
|
|
28118
|
+
async function resolveMcpServerName(cwd, serverReference) {
|
|
28119
|
+
const server = await resolveMcpServerInventoryByReference(cwd, serverReference);
|
|
28120
|
+
return server.name;
|
|
28121
|
+
}
|
|
27629
28122
|
function permissionFromAnnotations(annotations) {
|
|
27630
28123
|
if (annotations?.destructiveHint) {
|
|
27631
28124
|
return "destructive";
|
|
@@ -27785,23 +28278,24 @@ async function discoverMcpTools(cwd) {
|
|
|
27785
28278
|
}
|
|
27786
28279
|
async function callMcpTool(cwd, serverName, toolName, input) {
|
|
27787
28280
|
const config2 = await loadMcpConfig(cwd);
|
|
27788
|
-
const
|
|
28281
|
+
const resolvedServerName = await resolveMcpServerName(cwd, serverName).catch(() => serverName);
|
|
28282
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27789
28283
|
if (!server || server.enabled === false) {
|
|
27790
28284
|
return {
|
|
27791
|
-
toolId: toMcpToolId(
|
|
28285
|
+
toolId: toMcpToolId(resolvedServerName, toolName),
|
|
27792
28286
|
success: false,
|
|
27793
|
-
summary: `MCP server ${
|
|
28287
|
+
summary: `MCP server ${resolvedServerName} is not configured or is disabled.`,
|
|
27794
28288
|
artifacts: []
|
|
27795
28289
|
};
|
|
27796
28290
|
}
|
|
27797
|
-
const result = await withMcpClient(cwd,
|
|
28291
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.callTool({
|
|
27798
28292
|
name: toolName,
|
|
27799
28293
|
arguments: Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0))
|
|
27800
28294
|
}));
|
|
27801
28295
|
return {
|
|
27802
|
-
toolId: toMcpToolId(
|
|
28296
|
+
toolId: toMcpToolId(resolvedServerName, toolName),
|
|
27803
28297
|
success: !result.isError,
|
|
27804
|
-
summary: result.isError ? `MCP tool ${
|
|
28298
|
+
summary: result.isError ? `MCP tool ${resolvedServerName}/${toolName} reported an error.` : `Ran MCP tool ${resolvedServerName}/${toolName}.`,
|
|
27805
28299
|
stdout: renderMcpContent(result),
|
|
27806
28300
|
artifacts: []
|
|
27807
28301
|
};
|
|
@@ -27823,18 +28317,19 @@ ${"text" in resource ? resource.text : `[binary ${resource.mimeType ?? "resource
|
|
|
27823
28317
|
}).join("\n\n");
|
|
27824
28318
|
}
|
|
27825
28319
|
async function invokeMcpPrompt(cwd, serverName, promptName, args) {
|
|
28320
|
+
const { serverName: resolvedServerName, promptName: resolvedPromptName } = await resolveMcpPromptReference(cwd, serverName, promptName);
|
|
27826
28321
|
const config2 = await loadMcpConfig(cwd);
|
|
27827
|
-
const server = config2.mcpServers[
|
|
28322
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27828
28323
|
if (!server || server.enabled === false) {
|
|
27829
|
-
throw new Error(`MCP server ${
|
|
28324
|
+
throw new Error(`MCP server ${resolvedServerName} is not configured or is disabled.`);
|
|
27830
28325
|
}
|
|
27831
|
-
const result = await withMcpClient(cwd,
|
|
27832
|
-
name:
|
|
28326
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.getPrompt({
|
|
28327
|
+
name: resolvedPromptName,
|
|
27833
28328
|
arguments: args
|
|
27834
28329
|
}));
|
|
27835
28330
|
return {
|
|
27836
|
-
serverName,
|
|
27837
|
-
promptName,
|
|
28331
|
+
serverName: resolvedServerName,
|
|
28332
|
+
promptName: resolvedPromptName,
|
|
27838
28333
|
...result.description ? {
|
|
27839
28334
|
description: result.description
|
|
27840
28335
|
} : {},
|
|
@@ -27842,19 +28337,20 @@ async function invokeMcpPrompt(cwd, serverName, promptName, args) {
|
|
|
27842
28337
|
};
|
|
27843
28338
|
}
|
|
27844
28339
|
async function readMcpResource(cwd, serverName, uri) {
|
|
28340
|
+
const resolvedServerName = await resolveMcpServerName(cwd, serverName);
|
|
27845
28341
|
const config2 = await loadMcpConfig(cwd);
|
|
27846
|
-
const server = config2.mcpServers[
|
|
28342
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27847
28343
|
if (!server || server.enabled === false) {
|
|
27848
|
-
throw new Error(`MCP server ${
|
|
28344
|
+
throw new Error(`MCP server ${resolvedServerName} is not configured or is disabled.`);
|
|
27849
28345
|
}
|
|
27850
|
-
const result = await withMcpClient(cwd,
|
|
28346
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.readResource({
|
|
27851
28347
|
uri
|
|
27852
28348
|
}));
|
|
27853
28349
|
const content = result.contents.map((item) => "text" in item ? `resource: ${item.uri}
|
|
27854
28350
|
${item.text}` : `resource: ${item.uri}
|
|
27855
28351
|
[binary ${item.mimeType ?? "resource"}]`).join("\n\n");
|
|
27856
28352
|
return {
|
|
27857
|
-
serverName,
|
|
28353
|
+
serverName: resolvedServerName,
|
|
27858
28354
|
uri,
|
|
27859
28355
|
content
|
|
27860
28356
|
};
|
|
@@ -29177,6 +29673,109 @@ var import_node_path14 = __toESM(require("node:path"), 1);
|
|
|
29177
29673
|
function normalizeGoal(goal) {
|
|
29178
29674
|
return goal.trim().replace(/\s+/g, " ");
|
|
29179
29675
|
}
|
|
29676
|
+
function looksLikeVisualAdjustmentGoal2(goal) {
|
|
29677
|
+
const lower = goal.toLowerCase();
|
|
29678
|
+
const backendSignals = [
|
|
29679
|
+
"api",
|
|
29680
|
+
"database",
|
|
29681
|
+
"backend",
|
|
29682
|
+
"server",
|
|
29683
|
+
"migration",
|
|
29684
|
+
"schema",
|
|
29685
|
+
"prisma",
|
|
29686
|
+
"postgres",
|
|
29687
|
+
"sqlite",
|
|
29688
|
+
"auth",
|
|
29689
|
+
"billing",
|
|
29690
|
+
"webhook"
|
|
29691
|
+
];
|
|
29692
|
+
const editSignals = [
|
|
29693
|
+
"make",
|
|
29694
|
+
"change",
|
|
29695
|
+
"update",
|
|
29696
|
+
"turn",
|
|
29697
|
+
"switch",
|
|
29698
|
+
"set",
|
|
29699
|
+
"use",
|
|
29700
|
+
"refresh",
|
|
29701
|
+
"restyle",
|
|
29702
|
+
"redesign"
|
|
29703
|
+
];
|
|
29704
|
+
const visualSignals = [
|
|
29705
|
+
"background",
|
|
29706
|
+
"color",
|
|
29707
|
+
"green",
|
|
29708
|
+
"amber",
|
|
29709
|
+
"blue",
|
|
29710
|
+
"pink",
|
|
29711
|
+
"purple",
|
|
29712
|
+
"gradient",
|
|
29713
|
+
"theme",
|
|
29714
|
+
"palette",
|
|
29715
|
+
"styling",
|
|
29716
|
+
"style",
|
|
29717
|
+
"look",
|
|
29718
|
+
"visual",
|
|
29719
|
+
"hero"
|
|
29720
|
+
];
|
|
29721
|
+
const pageContextSignals = [
|
|
29722
|
+
"page",
|
|
29723
|
+
"landing",
|
|
29724
|
+
"lnding",
|
|
29725
|
+
"homepage",
|
|
29726
|
+
"home page",
|
|
29727
|
+
"site",
|
|
29728
|
+
"website",
|
|
29729
|
+
"blog"
|
|
29730
|
+
];
|
|
29731
|
+
if (backendSignals.some((signal) => lower.includes(signal))) {
|
|
29732
|
+
return false;
|
|
29733
|
+
}
|
|
29734
|
+
return editSignals.some((signal) => lower.includes(signal)) && visualSignals.some((signal) => lower.includes(signal)) && (pageContextSignals.some((signal) => lower.includes(signal)) || lower.includes("background"));
|
|
29735
|
+
}
|
|
29736
|
+
function looksLikePageExpansionGoal2(goal) {
|
|
29737
|
+
const lower = goal.toLowerCase();
|
|
29738
|
+
const backendSignals = [
|
|
29739
|
+
"api",
|
|
29740
|
+
"database",
|
|
29741
|
+
"backend",
|
|
29742
|
+
"server",
|
|
29743
|
+
"migration",
|
|
29744
|
+
"schema",
|
|
29745
|
+
"prisma",
|
|
29746
|
+
"postgres",
|
|
29747
|
+
"sqlite",
|
|
29748
|
+
"auth",
|
|
29749
|
+
"billing",
|
|
29750
|
+
"webhook"
|
|
29751
|
+
];
|
|
29752
|
+
const directSignals = [
|
|
29753
|
+
"add more pages",
|
|
29754
|
+
"add pages",
|
|
29755
|
+
"more pages",
|
|
29756
|
+
"new pages",
|
|
29757
|
+
"new page",
|
|
29758
|
+
"additional pages",
|
|
29759
|
+
"additional page"
|
|
29760
|
+
];
|
|
29761
|
+
const namedPages = [
|
|
29762
|
+
"about",
|
|
29763
|
+
"contact",
|
|
29764
|
+
"archive",
|
|
29765
|
+
"journal",
|
|
29766
|
+
"stories",
|
|
29767
|
+
"story",
|
|
29768
|
+
"menu",
|
|
29769
|
+
"reservation",
|
|
29770
|
+
"reservations",
|
|
29771
|
+
"shop",
|
|
29772
|
+
"services"
|
|
29773
|
+
];
|
|
29774
|
+
if (backendSignals.some((signal) => lower.includes(signal))) {
|
|
29775
|
+
return false;
|
|
29776
|
+
}
|
|
29777
|
+
return directSignals.some((signal) => lower.includes(signal)) || (lower.includes("add") || lower.includes("create") || lower.includes("make")) && lower.includes("page") && namedPages.some((name) => lower.includes(name));
|
|
29778
|
+
}
|
|
29180
29779
|
function looksLikeStaticSiteGoal(goal) {
|
|
29181
29780
|
const lower = goal.toLowerCase();
|
|
29182
29781
|
const backendSignals = [
|
|
@@ -29235,6 +29834,12 @@ function looksLikeStaticSiteGoal(goal) {
|
|
|
29235
29834
|
if (lower.includes("blog") && (lower.includes("make") || lower.includes("improve") || lower.includes("enhance") || lower.includes("redesign")) && !backendSignals.some((signal) => lower.includes(signal))) {
|
|
29236
29835
|
return true;
|
|
29237
29836
|
}
|
|
29837
|
+
if (looksLikeVisualAdjustmentGoal2(lower)) {
|
|
29838
|
+
return true;
|
|
29839
|
+
}
|
|
29840
|
+
if (looksLikePageExpansionGoal2(lower)) {
|
|
29841
|
+
return true;
|
|
29842
|
+
}
|
|
29238
29843
|
return false;
|
|
29239
29844
|
}
|
|
29240
29845
|
function inferProjectShape(goal) {
|
|
@@ -31151,7 +31756,10 @@ function isStaticSiteTask(task, request) {
|
|
|
31151
31756
|
}
|
|
31152
31757
|
return task.filesLikelyTouched.some((filePath) => filePath === "src/app/page.tsx" || filePath === "src/app/layout.tsx" || filePath === "src/pages/index.tsx" || filePath === "index.html" || filePath === "styles.css");
|
|
31153
31758
|
}
|
|
31154
|
-
function shouldDelegateTask(task) {
|
|
31759
|
+
function shouldDelegateTask(task, request) {
|
|
31760
|
+
if ((looksLikeVisualAdjustmentGoal(request.goal) || looksLikePageExpansionGoal(request.goal)) && isStaticSiteTask(task, request)) {
|
|
31761
|
+
return false;
|
|
31762
|
+
}
|
|
31155
31763
|
return (task.swarmDepth ?? 0) === 0 && task.type === "implementation" && ![
|
|
31156
31764
|
"repo-analyst",
|
|
31157
31765
|
"planner",
|
|
@@ -31168,7 +31776,7 @@ function terminalExpansionTaskIds(tasks) {
|
|
|
31168
31776
|
return terminalIds.length > 0 ? terminalIds : tasks.map((task) => task.id);
|
|
31169
31777
|
}
|
|
31170
31778
|
function createDefaultDelegationPlan(task, request) {
|
|
31171
|
-
if (!shouldDelegateTask(task)) {
|
|
31779
|
+
if (!shouldDelegateTask(task, request)) {
|
|
31172
31780
|
return null;
|
|
31173
31781
|
}
|
|
31174
31782
|
if (task.agentRole === "frontend-specialist" || isStaticSiteTask(task, request)) {
|
|
@@ -31317,6 +31925,53 @@ function createDefaultDelegationPlan(task, request) {
|
|
|
31317
31925
|
}
|
|
31318
31926
|
return null;
|
|
31319
31927
|
}
|
|
31928
|
+
async function detectAppliedVisualAdjustment(cwd, request) {
|
|
31929
|
+
const adjustment = inferVisualAdjustment(request.goal);
|
|
31930
|
+
if (!adjustment) {
|
|
31931
|
+
return null;
|
|
31932
|
+
}
|
|
31933
|
+
const candidates = [
|
|
31934
|
+
"src/app/page.tsx",
|
|
31935
|
+
"src/pages/index.tsx",
|
|
31936
|
+
"src/app/globals.css",
|
|
31937
|
+
"styles.css",
|
|
31938
|
+
"index.html"
|
|
31939
|
+
];
|
|
31940
|
+
for (const relativePath of candidates) {
|
|
31941
|
+
const absolutePath = import_node_path14.default.join(cwd, relativePath);
|
|
31942
|
+
try {
|
|
31943
|
+
await (0, import_promises14.access)(absolutePath);
|
|
31944
|
+
const contents = await (0, import_promises14.readFile)(absolutePath, "utf8");
|
|
31945
|
+
if (contents.includes(adjustment.background)) {
|
|
31946
|
+
return absolutePath;
|
|
31947
|
+
}
|
|
31948
|
+
} catch {
|
|
31949
|
+
}
|
|
31950
|
+
}
|
|
31951
|
+
return null;
|
|
31952
|
+
}
|
|
31953
|
+
async function detectPreferredVerificationCommand(cwd) {
|
|
31954
|
+
const packagePath = import_node_path14.default.join(cwd, "package.json");
|
|
31955
|
+
try {
|
|
31956
|
+
await (0, import_promises14.access)(packagePath);
|
|
31957
|
+
const raw = await (0, import_promises14.readFile)(packagePath, "utf8");
|
|
31958
|
+
const parsed = JSON.parse(raw);
|
|
31959
|
+
const scripts = parsed.scripts ?? {};
|
|
31960
|
+
const packageManager = parsed.packageManager?.startsWith("pnpm") ? "pnpm" : parsed.packageManager?.startsWith("yarn") ? "yarn" : "npm";
|
|
31961
|
+
if (scripts.build) {
|
|
31962
|
+
return packageManager === "yarn" ? "yarn build" : `${packageManager} run build`;
|
|
31963
|
+
}
|
|
31964
|
+
if (scripts.lint) {
|
|
31965
|
+
return packageManager === "yarn" ? "yarn lint" : `${packageManager} run lint`;
|
|
31966
|
+
}
|
|
31967
|
+
if (scripts.test) {
|
|
31968
|
+
return packageManager === "yarn" ? "yarn test" : `${packageManager} run test`;
|
|
31969
|
+
}
|
|
31970
|
+
} catch {
|
|
31971
|
+
return null;
|
|
31972
|
+
}
|
|
31973
|
+
return null;
|
|
31974
|
+
}
|
|
31320
31975
|
function materializeDelegatedTasks(plan, task, label, strategy, members) {
|
|
31321
31976
|
const existingIds = new Set(flattenPlanTasks(plan).filter((candidate) => candidate.id !== task.id).map((candidate) => candidate.id));
|
|
31322
31977
|
const teamMemberIds = members.map((member) => member.id);
|
|
@@ -31952,6 +32607,9 @@ var ExecutionOrchestrator = class {
|
|
|
31952
32607
|
if (request.workspaceState === "existing" && isStaticSiteTask(task, request) && (task.type === "scaffold" || task.type === "implementation")) {
|
|
31953
32608
|
return this.executeDeterministicStaticSiteTask(sessionId, task, request, resolvedApproval, options, emitProgress);
|
|
31954
32609
|
}
|
|
32610
|
+
if (request.workspaceState === "existing" && looksLikeStaticLandingGoal(request.goal) && task.type === "verification") {
|
|
32611
|
+
return this.executeDeterministicVerificationTask(sessionId, task, request, emitProgress, options.signal);
|
|
32612
|
+
}
|
|
31955
32613
|
if (task.type === "scaffold") {
|
|
31956
32614
|
return this.executeScaffoldTask(sessionId, task, request, plan, resolvedApproval, options, emitProgress);
|
|
31957
32615
|
}
|
|
@@ -32086,7 +32744,69 @@ var ExecutionOrchestrator = class {
|
|
|
32086
32744
|
]))
|
|
32087
32745
|
};
|
|
32088
32746
|
}
|
|
32747
|
+
async executeDeterministicVerificationTask(sessionId, task, request, emitProgress, signal) {
|
|
32748
|
+
const command = await detectPreferredVerificationCommand(request.cwd);
|
|
32749
|
+
if (!command) {
|
|
32750
|
+
return {
|
|
32751
|
+
status: "completed",
|
|
32752
|
+
summary: "No build, lint, or test script was found; verification was recorded as not applicable.",
|
|
32753
|
+
toolResults: [],
|
|
32754
|
+
artifacts: []
|
|
32755
|
+
};
|
|
32756
|
+
}
|
|
32757
|
+
const input = {
|
|
32758
|
+
command
|
|
32759
|
+
};
|
|
32760
|
+
if (emitProgress) {
|
|
32761
|
+
await emitProgress({
|
|
32762
|
+
type: "tool-started",
|
|
32763
|
+
sessionId,
|
|
32764
|
+
taskId: task.id,
|
|
32765
|
+
agentRole: task.agentRole,
|
|
32766
|
+
toolId: "tests.run",
|
|
32767
|
+
input
|
|
32768
|
+
});
|
|
32769
|
+
}
|
|
32770
|
+
const result = await this.safeRunTool("tests.run", input, {
|
|
32771
|
+
cwd: request.cwd,
|
|
32772
|
+
taskId: task.id,
|
|
32773
|
+
agentRole: task.agentRole,
|
|
32774
|
+
...signal ? {
|
|
32775
|
+
signal
|
|
32776
|
+
} : {}
|
|
32777
|
+
});
|
|
32778
|
+
if (emitProgress) {
|
|
32779
|
+
await emitProgress({
|
|
32780
|
+
type: "tool-finished",
|
|
32781
|
+
sessionId,
|
|
32782
|
+
taskId: task.id,
|
|
32783
|
+
agentRole: task.agentRole,
|
|
32784
|
+
toolResult: result
|
|
32785
|
+
});
|
|
32786
|
+
}
|
|
32787
|
+
return {
|
|
32788
|
+
status: result.success ? "completed" : "blocked",
|
|
32789
|
+
summary: result.success ? `Verification passed via ${command}.` : `Verification failed via ${command}.`,
|
|
32790
|
+
toolResults: [
|
|
32791
|
+
result
|
|
32792
|
+
],
|
|
32793
|
+
artifacts: result.artifacts
|
|
32794
|
+
};
|
|
32795
|
+
}
|
|
32089
32796
|
async executeDeterministicStaticSiteTask(sessionId, task, request, resolvedApproval, options, emitProgress) {
|
|
32797
|
+
if (looksLikeVisualAdjustmentGoal(request.goal)) {
|
|
32798
|
+
const appliedArtifact = await detectAppliedVisualAdjustment(request.cwd, request);
|
|
32799
|
+
if (appliedArtifact) {
|
|
32800
|
+
return {
|
|
32801
|
+
status: "completed",
|
|
32802
|
+
summary: `Confirmed the requested visual adjustment in ${import_node_path14.default.relative(request.cwd, appliedArtifact) || appliedArtifact}.`,
|
|
32803
|
+
toolResults: [],
|
|
32804
|
+
artifacts: [
|
|
32805
|
+
appliedArtifact
|
|
32806
|
+
]
|
|
32807
|
+
};
|
|
32808
|
+
}
|
|
32809
|
+
}
|
|
32090
32810
|
const config2 = await loadConfig(request.cwd);
|
|
32091
32811
|
const scaffoldInput = {
|
|
32092
32812
|
goal: request.goal,
|
|
@@ -32482,7 +33202,7 @@ var ExecutionOrchestrator = class {
|
|
|
32482
33202
|
}
|
|
32483
33203
|
async maybeExpandReadyTaskGraph(sessionId, request, plan, events, emitProgress) {
|
|
32484
33204
|
const envelope = this.buildEnvelope(request, plan, sessionId);
|
|
32485
|
-
const candidate = envelope.readyTasks.find((task) => shouldDelegateTask(task));
|
|
33205
|
+
const candidate = envelope.readyTasks.find((task) => shouldDelegateTask(task, request));
|
|
32486
33206
|
if (!candidate) {
|
|
32487
33207
|
return {
|
|
32488
33208
|
plan
|
|
@@ -32703,10 +33423,69 @@ function createAgentsCommand() {
|
|
|
32703
33423
|
});
|
|
32704
33424
|
console.log(`Created ${outputPath}`);
|
|
32705
33425
|
});
|
|
33426
|
+
command.command("show").description("Show one custom agent or team.").argument("<id>", "Agent or team id").option("--team", "Show a team instead of an agent", false).action(async (id, options) => {
|
|
33427
|
+
if (options.team) {
|
|
33428
|
+
const team = await loadAgentTeamById(process.cwd(), id);
|
|
33429
|
+
if (!team) {
|
|
33430
|
+
throw new Error(`Unknown team "${id}".`);
|
|
33431
|
+
}
|
|
33432
|
+
console.log(team.id);
|
|
33433
|
+
console.log(` label: ${team.label}`);
|
|
33434
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
33435
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
33436
|
+
console.log(` strategy: ${team.strategy}`);
|
|
33437
|
+
console.log(` file: ${team.filePath}`);
|
|
33438
|
+
if (team.description) {
|
|
33439
|
+
console.log("");
|
|
33440
|
+
console.log(team.description);
|
|
33441
|
+
}
|
|
33442
|
+
return;
|
|
33443
|
+
}
|
|
33444
|
+
const agent = await loadCustomAgentById(process.cwd(), id);
|
|
33445
|
+
if (!agent) {
|
|
33446
|
+
throw new Error(`Unknown custom agent "${id}".`);
|
|
33447
|
+
}
|
|
33448
|
+
console.log(agent.id);
|
|
33449
|
+
console.log(` label: ${agent.label}`);
|
|
33450
|
+
console.log(` baseRole: ${agent.baseRole}`);
|
|
33451
|
+
console.log(` brainRole: ${agent.brainRole ?? "-"}`);
|
|
33452
|
+
console.log(` purpose: ${agent.purpose ?? "-"}`);
|
|
33453
|
+
console.log(` match: ${agent.match.join(", ") || "-"}`);
|
|
33454
|
+
console.log(` tools: ${agent.tools.join(", ") || "(inherits base role tools)"}`);
|
|
33455
|
+
console.log(` file: ${agent.filePath}`);
|
|
33456
|
+
if (agent.instructions.trim()) {
|
|
33457
|
+
console.log("");
|
|
33458
|
+
console.log(agent.instructions.trim());
|
|
33459
|
+
}
|
|
33460
|
+
});
|
|
33461
|
+
command.command("delete").description("Delete a custom agent or team markdown file.").argument("<id>", "Agent or team id").option("--team", "Delete a team instead of an agent", false).action(async (id, options) => {
|
|
33462
|
+
const outputPath = options.team ? await deleteAgentTeamFile(process.cwd(), id) : await deleteCustomAgentFile(process.cwd(), id);
|
|
33463
|
+
console.log(`Deleted ${outputPath}`);
|
|
33464
|
+
});
|
|
32706
33465
|
command.command("team-create").description("Create a markdown-backed agent team definition.").argument("<id>", "Team id").argument("<agents...>", "Member agent ids").option("--label <label>", "Human-readable label").action(async (id, agents, options) => {
|
|
32707
33466
|
const outputPath = await createAgentTeamFile(process.cwd(), id, agents, options.label);
|
|
32708
33467
|
console.log(`Created ${outputPath}`);
|
|
32709
33468
|
});
|
|
33469
|
+
command.command("team-show").description("Show one markdown-backed team definition.").argument("<id>", "Team id").action(async (id) => {
|
|
33470
|
+
const team = await loadAgentTeamById(process.cwd(), id);
|
|
33471
|
+
if (!team) {
|
|
33472
|
+
throw new Error(`Unknown team "${id}".`);
|
|
33473
|
+
}
|
|
33474
|
+
console.log(team.id);
|
|
33475
|
+
console.log(` label: ${team.label}`);
|
|
33476
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
33477
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
33478
|
+
console.log(` strategy: ${team.strategy}`);
|
|
33479
|
+
console.log(` file: ${team.filePath}`);
|
|
33480
|
+
if (team.description) {
|
|
33481
|
+
console.log("");
|
|
33482
|
+
console.log(team.description);
|
|
33483
|
+
}
|
|
33484
|
+
});
|
|
33485
|
+
command.command("team-delete").description("Delete one markdown-backed team definition.").argument("<id>", "Team id").action(async (id) => {
|
|
33486
|
+
const outputPath = await deleteAgentTeamFile(process.cwd(), id);
|
|
33487
|
+
console.log(`Deleted ${outputPath}`);
|
|
33488
|
+
});
|
|
32710
33489
|
return command;
|
|
32711
33490
|
}
|
|
32712
33491
|
|
|
@@ -33523,7 +34302,7 @@ async function renderMcpInventory(cwd, name) {
|
|
|
33523
34302
|
` prompts: ${server.prompts.length}`,
|
|
33524
34303
|
...server.prompts.slice(0, 10).flatMap((prompt) => [
|
|
33525
34304
|
` - ${prompt.name}${prompt.arguments.length > 0 ? ` (${prompt.arguments.map((argument) => `${argument.name}${argument.required ? "*" : ""}`).join(", ")})` : ""}`,
|
|
33526
|
-
` command: /mcp__${server.name}__${prompt.name}`
|
|
34305
|
+
` command: /mcp__${normalizeMcpCommandSegment(server.name)}__${normalizeMcpCommandSegment(prompt.name)}`
|
|
33527
34306
|
]),
|
|
33528
34307
|
` resources: ${server.resources.length}`,
|
|
33529
34308
|
...server.resources.slice(0, 10).flatMap((resource) => [
|
|
@@ -33549,7 +34328,7 @@ async function renderMcpPromptList(cwd, name) {
|
|
|
33549
34328
|
] : [],
|
|
33550
34329
|
...server.prompts.length > 0 ? server.prompts.flatMap((prompt) => [
|
|
33551
34330
|
` - ${prompt.name}${prompt.arguments.length > 0 ? ` (${prompt.arguments.map((argument) => `${argument.name}${argument.required ? "*" : ""}`).join(", ")})` : ""}`,
|
|
33552
|
-
` command: /mcp__${server.name}__${prompt.name}`
|
|
34331
|
+
` command: /mcp__${normalizeMcpCommandSegment(server.name)}__${normalizeMcpCommandSegment(prompt.name)}`
|
|
33553
34332
|
]) : [
|
|
33554
34333
|
" - no prompts"
|
|
33555
34334
|
]
|
|
@@ -35490,53 +36269,65 @@ function renderBox(lines) {
|
|
|
35490
36269
|
function renderHelp() {
|
|
35491
36270
|
return [
|
|
35492
36271
|
`${color(DIM, "Commands")}`,
|
|
35493
|
-
|
|
35494
|
-
"/
|
|
35495
|
-
"/
|
|
35496
|
-
"/
|
|
35497
|
-
"/
|
|
36272
|
+
`${color(BOLD, "Core")}`,
|
|
36273
|
+
"/status Show active model, workspace, approvals, and sandbox state.",
|
|
36274
|
+
"/ask <prompt> Chat with the focused model without running the agent.",
|
|
36275
|
+
"/plan <goal> Create a structured plan only.",
|
|
36276
|
+
"/run <goal> Execute a goal immediately.",
|
|
36277
|
+
"/resume Continue the latest paused or awaiting-approval session.",
|
|
36278
|
+
"/review Review the current git diff and summarize risk.",
|
|
36279
|
+
"/clear Redraw the shell.",
|
|
36280
|
+
"/quit, /exit Leave the shell.",
|
|
36281
|
+
"",
|
|
36282
|
+
`${color(BOLD, "Model")}`,
|
|
36283
|
+
"/model Show current provider/model state.",
|
|
35498
36284
|
"/model providers List configured providers.",
|
|
35499
36285
|
"/model add <tpl> [id] Add a provider template.",
|
|
35500
36286
|
"/model use <provider> [model] Switch provider/model for all roles.",
|
|
35501
36287
|
"/model find [search] Discover models for the active provider.",
|
|
35502
|
-
"/model select <n> Pick
|
|
35503
|
-
"/model focus <role> Change
|
|
35504
|
-
"
|
|
36288
|
+
"/model select <n> Pick from the last numbered model list.",
|
|
36289
|
+
"/model focus <role> Change focus to planner, coder, reviewer, or fast.",
|
|
36290
|
+
"",
|
|
36291
|
+
`${color(BOLD, "Permissions")}`,
|
|
36292
|
+
"/permissions Show layered approval, sandbox, and trust settings.",
|
|
35505
36293
|
"/permissions auto|manual Change approval mode.",
|
|
35506
36294
|
"/permissions sandbox <mode> Set read-only, workspace-write, or full.",
|
|
35507
36295
|
"/permissions trust <path> Add a trusted directory.",
|
|
35508
36296
|
"/permissions untrust <path> Remove a trusted directory.",
|
|
35509
|
-
"/
|
|
35510
|
-
"/
|
|
36297
|
+
"/approve [id] Approve a pending risky action and continue.",
|
|
36298
|
+
"/approve-all Approve every pending action in the current session.",
|
|
36299
|
+
"/deny [id] Deny a pending risky action.",
|
|
36300
|
+
"",
|
|
36301
|
+
`${color(BOLD, "Memory")}`,
|
|
36302
|
+
"/init [--memory-only] Build config and durable project understanding files.",
|
|
36303
|
+
"/memory Show init/project/user/agent memory paths.",
|
|
36304
|
+
"/memory refresh Re-scan the project and refresh markdown memory.",
|
|
35511
36305
|
"/memory show <scope> Print init, project, user, or agent memory.",
|
|
35512
|
-
"/memory add <scope>
|
|
36306
|
+
"/memory add <scope> ... Append a markdown memory note.",
|
|
35513
36307
|
"/config Show config, memory, and MCP file locations.",
|
|
36308
|
+
"",
|
|
36309
|
+
`${color(BOLD, "MCP")}`,
|
|
35514
36310
|
"/mcp List configured MCP servers.",
|
|
36311
|
+
"/mcp discover [server] Show MCP tools, prompts-as-commands, and resources.",
|
|
36312
|
+
"/mcp prompt <server> <prompt> [key=value ...] Render one MCP prompt.",
|
|
36313
|
+
"/mcp read <server> <uri> Read one MCP resource.",
|
|
35515
36314
|
"/mcp add <name> --command <cmd> [--arg <value>] [--env KEY=VALUE]",
|
|
35516
36315
|
" Add an MCP stdio server to .mcp.json.",
|
|
35517
|
-
"/
|
|
35518
|
-
"/
|
|
35519
|
-
"
|
|
35520
|
-
|
|
35521
|
-
" Render an MCP prompt.",
|
|
35522
|
-
"/mcp read <server> <uri> Read one MCP resource.",
|
|
36316
|
+
"/mcp__server__prompt ... Invoke an MCP prompt directly from the shell.",
|
|
36317
|
+
"@server:uri Attach an MCP resource inside /ask, /plan, or /run prompts.",
|
|
36318
|
+
"",
|
|
36319
|
+
`${color(BOLD, "Agents")}`,
|
|
35523
36320
|
"/agents List custom agents and teams.",
|
|
36321
|
+
"/agents show <id> Show one custom agent definition.",
|
|
36322
|
+
"/agents delete <id> Delete one custom agent definition.",
|
|
35524
36323
|
"/agents create <id> --base <role> Create a markdown custom agent.",
|
|
35525
36324
|
"/agents team create <id> <agent...> Create a markdown team file.",
|
|
35526
|
-
"/
|
|
35527
|
-
"/
|
|
35528
|
-
"/run <goal> Start a Kimbho execution session for a goal.",
|
|
35529
|
-
"/resume Show the latest saved session.",
|
|
35530
|
-
"/approve [id] Approve a pending risky action and continue the session.",
|
|
35531
|
-
"/approve-all Approve all pending actions in the current session.",
|
|
35532
|
-
"/deny [id] Deny a pending risky action.",
|
|
35533
|
-
"/review Review the current git diff and summarize risk.",
|
|
35534
|
-
"/doctor Check local environment and config.",
|
|
35535
|
-
"/clear Redraw the shell.",
|
|
35536
|
-
"/quit, /exit Leave the shell.",
|
|
36325
|
+
"/agents team show <id> Show one team definition.",
|
|
36326
|
+
"/agents team delete <id> Delete one team definition.",
|
|
35537
36327
|
"",
|
|
35538
36328
|
`${color(DIM, "Tip")}`,
|
|
35539
36329
|
"Type build/change requests directly to run the agent. Type plan/design prompts for planning. Use /ask when you want plain chat.",
|
|
36330
|
+
"MCP prompts behave like slash commands, and MCP resources can be attached inline with @server:uri.",
|
|
35540
36331
|
"Legacy aliases like /providers, /models, /select, /use-model, /brain, and /approval still work.",
|
|
35541
36332
|
"Press Ctrl+C during an active run to pause it and return to the shell, then use /resume to continue."
|
|
35542
36333
|
].join("\n");
|
|
@@ -36769,7 +37560,7 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36769
37560
|
}
|
|
36770
37561
|
return;
|
|
36771
37562
|
}
|
|
36772
|
-
if (subcommand === "tools" || subcommand === "inspect") {
|
|
37563
|
+
if (subcommand === "tools" || subcommand === "inspect" || subcommand === "discover") {
|
|
36773
37564
|
const name = tokens[2]?.trim();
|
|
36774
37565
|
for (const line of await renderMcpInventory(cwd, name)) {
|
|
36775
37566
|
console.log(line);
|
|
@@ -36805,10 +37596,12 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36805
37596
|
return;
|
|
36806
37597
|
}
|
|
36807
37598
|
if (subcommand === "read") {
|
|
36808
|
-
const
|
|
36809
|
-
const
|
|
37599
|
+
const shorthand = tokens[2]?.trim();
|
|
37600
|
+
const shorthandMatch = shorthand?.match(/^@([^:\s]+):(.+)$/);
|
|
37601
|
+
const serverName = shorthandMatch ? shorthandMatch[1] : tokens[2]?.trim();
|
|
37602
|
+
const uri = shorthandMatch ? shorthandMatch[2] : tokens.slice(3).join(" ").trim();
|
|
36810
37603
|
if (!serverName || !uri) {
|
|
36811
|
-
throw new Error("Usage: /mcp read <server> <uri>");
|
|
37604
|
+
throw new Error("Usage: /mcp read <server> <uri> | /mcp read @server:uri");
|
|
36812
37605
|
}
|
|
36813
37606
|
for (const line of await renderMcpResourceRead(cwd, serverName, uri)) {
|
|
36814
37607
|
console.log(line);
|
|
@@ -36878,7 +37671,7 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36878
37671
|
console.log(`Added MCP server ${name}`);
|
|
36879
37672
|
return;
|
|
36880
37673
|
}
|
|
36881
|
-
throw new Error("Usage: /mcp [list|
|
|
37674
|
+
throw new Error("Usage: /mcp [list|discover [server]|prompts [server]|resources [server]|prompt <server> <prompt>|read <server> <uri>|read @server:uri|add <name> --command <cmd>|remove <name>|enable <name>|disable <name>]");
|
|
36882
37675
|
}
|
|
36883
37676
|
async function handleAgentsCommand(cwd, tokens) {
|
|
36884
37677
|
const subcommand = tokens[1]?.trim().toLowerCase();
|
|
@@ -36923,6 +37716,38 @@ async function handleAgentsCommand(cwd, tokens) {
|
|
|
36923
37716
|
console.log(`Created ${outputPath}`);
|
|
36924
37717
|
return;
|
|
36925
37718
|
}
|
|
37719
|
+
if (subcommand === "show") {
|
|
37720
|
+
const id = tokens[2]?.trim();
|
|
37721
|
+
if (!id) {
|
|
37722
|
+
throw new Error("Usage: /agents show <id>");
|
|
37723
|
+
}
|
|
37724
|
+
const agent = await loadCustomAgentById(cwd, id);
|
|
37725
|
+
if (!agent) {
|
|
37726
|
+
throw new Error(`Unknown custom agent "${id}".`);
|
|
37727
|
+
}
|
|
37728
|
+
console.log(`${agent.id}`);
|
|
37729
|
+
console.log(` label: ${agent.label}`);
|
|
37730
|
+
console.log(` baseRole: ${agent.baseRole}`);
|
|
37731
|
+
console.log(` brainRole: ${agent.brainRole ?? "-"}`);
|
|
37732
|
+
console.log(` purpose: ${agent.purpose ?? "-"}`);
|
|
37733
|
+
console.log(` match: ${agent.match.join(", ") || "-"}`);
|
|
37734
|
+
console.log(` tools: ${agent.tools.join(", ") || "(inherits base role tools)"}`);
|
|
37735
|
+
console.log(` file: ${agent.filePath}`);
|
|
37736
|
+
if (agent.instructions.trim()) {
|
|
37737
|
+
console.log("");
|
|
37738
|
+
console.log(agent.instructions.trim());
|
|
37739
|
+
}
|
|
37740
|
+
return;
|
|
37741
|
+
}
|
|
37742
|
+
if (subcommand === "delete") {
|
|
37743
|
+
const id = tokens[2]?.trim();
|
|
37744
|
+
if (!id) {
|
|
37745
|
+
throw new Error("Usage: /agents delete <id>");
|
|
37746
|
+
}
|
|
37747
|
+
const outputPath = await deleteCustomAgentFile(cwd, id);
|
|
37748
|
+
console.log(`Deleted ${outputPath}`);
|
|
37749
|
+
return;
|
|
37750
|
+
}
|
|
36926
37751
|
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "create") {
|
|
36927
37752
|
const id = tokens[3]?.trim();
|
|
36928
37753
|
const agentIds = tokens.slice(4).filter((token) => !token.startsWith("--"));
|
|
@@ -36935,7 +37760,37 @@ async function handleAgentsCommand(cwd, tokens) {
|
|
|
36935
37760
|
console.log(`Created ${outputPath}`);
|
|
36936
37761
|
return;
|
|
36937
37762
|
}
|
|
36938
|
-
|
|
37763
|
+
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "show") {
|
|
37764
|
+
const id = tokens[3]?.trim();
|
|
37765
|
+
if (!id) {
|
|
37766
|
+
throw new Error("Usage: /agents team show <id>");
|
|
37767
|
+
}
|
|
37768
|
+
const team = await loadAgentTeamById(cwd, id);
|
|
37769
|
+
if (!team) {
|
|
37770
|
+
throw new Error(`Unknown team "${id}".`);
|
|
37771
|
+
}
|
|
37772
|
+
console.log(`${team.id}`);
|
|
37773
|
+
console.log(` label: ${team.label}`);
|
|
37774
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
37775
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
37776
|
+
console.log(` strategy: ${team.strategy}`);
|
|
37777
|
+
console.log(` file: ${team.filePath}`);
|
|
37778
|
+
if (team.description) {
|
|
37779
|
+
console.log("");
|
|
37780
|
+
console.log(team.description);
|
|
37781
|
+
}
|
|
37782
|
+
return;
|
|
37783
|
+
}
|
|
37784
|
+
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "delete") {
|
|
37785
|
+
const id = tokens[3]?.trim();
|
|
37786
|
+
if (!id) {
|
|
37787
|
+
throw new Error("Usage: /agents team delete <id>");
|
|
37788
|
+
}
|
|
37789
|
+
const outputPath = await deleteAgentTeamFile(cwd, id);
|
|
37790
|
+
console.log(`Deleted ${outputPath}`);
|
|
37791
|
+
return;
|
|
37792
|
+
}
|
|
37793
|
+
throw new Error("Usage: /agents [list|show <id>|delete <id>|create <id> --base <role>|team create <id> <agent...>|team show <id>|team delete <id>]");
|
|
36939
37794
|
}
|
|
36940
37795
|
async function handleModelSurfaceCommand(cwd, tokens, runtime) {
|
|
36941
37796
|
const subcommand = tokens[1]?.trim().toLowerCase();
|