@kimbho/kimbho-cli 0.1.18 → 0.1.19
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 +542 -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.19",
|
|
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,46 @@ 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
|
+
}
|
|
18293
18351
|
function looksLikeStaticLandingGoal(value) {
|
|
18294
18352
|
const normalized = value.toLowerCase();
|
|
18295
18353
|
const backendSignals = [
|
|
@@ -18348,6 +18406,9 @@ function looksLikeStaticLandingGoal(value) {
|
|
|
18348
18406
|
if (normalized.includes("blog") && (normalized.includes("make") || normalized.includes("improve") || normalized.includes("enhance") || normalized.includes("redesign")) && !backendSignals.some((signal) => normalized.includes(signal))) {
|
|
18349
18407
|
return true;
|
|
18350
18408
|
}
|
|
18409
|
+
if (looksLikeVisualAdjustmentGoal(normalized) && !backendSignals.some((signal) => normalized.includes(signal))) {
|
|
18410
|
+
return true;
|
|
18411
|
+
}
|
|
18351
18412
|
return false;
|
|
18352
18413
|
}
|
|
18353
18414
|
function sanitizeName(value) {
|
|
@@ -18575,7 +18636,76 @@ async function detectExistingStaticTarget(cwd) {
|
|
|
18575
18636
|
}
|
|
18576
18637
|
return null;
|
|
18577
18638
|
}
|
|
18639
|
+
function rewriteBackgroundInSource(source, background) {
|
|
18640
|
+
const inlinePatterns = [
|
|
18641
|
+
[/background:\s*'[^']*'/, `background: '${background}'`],
|
|
18642
|
+
[/background:\s*"[^"]*"/, `background: "${background}"`],
|
|
18643
|
+
[/background:\s*`[^`]*`/, `background: \`${background}\``]
|
|
18644
|
+
];
|
|
18645
|
+
for (const [pattern, replacement] of inlinePatterns) {
|
|
18646
|
+
if (pattern.test(source)) {
|
|
18647
|
+
return source.replace(pattern, replacement);
|
|
18648
|
+
}
|
|
18649
|
+
}
|
|
18650
|
+
const cssPatterns = [
|
|
18651
|
+
[/background:\s*[^;]+;/, `background: ${background};`],
|
|
18652
|
+
[/background-color:\s*[^;]+;/, `background: ${background};`]
|
|
18653
|
+
];
|
|
18654
|
+
for (const [pattern, replacement] of cssPatterns) {
|
|
18655
|
+
if (pattern.test(source)) {
|
|
18656
|
+
return source.replace(pattern, replacement);
|
|
18657
|
+
}
|
|
18658
|
+
}
|
|
18659
|
+
return source;
|
|
18660
|
+
}
|
|
18661
|
+
async function applyExistingStaticVisualAdjustment(cwd, goal, target) {
|
|
18662
|
+
const adjustment = inferVisualAdjustment(goal);
|
|
18663
|
+
if (!adjustment) {
|
|
18664
|
+
return null;
|
|
18665
|
+
}
|
|
18666
|
+
const candidatePaths = [
|
|
18667
|
+
target.pagePath,
|
|
18668
|
+
target.kind === "next-app" ? "src/app/globals.css" : null,
|
|
18669
|
+
target.kind === "next-pages" ? "styles.css" : null,
|
|
18670
|
+
target.kind === "static-html" ? "styles.css" : null
|
|
18671
|
+
].filter((value) => Boolean(value));
|
|
18672
|
+
for (const relativePath of candidatePaths) {
|
|
18673
|
+
const absolutePath = import_node_path10.default.join(cwd, relativePath);
|
|
18674
|
+
if (!await pathExists(absolutePath)) {
|
|
18675
|
+
continue;
|
|
18676
|
+
}
|
|
18677
|
+
const currentSource = await (0, import_promises10.readFile)(absolutePath, "utf8");
|
|
18678
|
+
if (currentSource.includes(adjustment.background)) {
|
|
18679
|
+
return {
|
|
18680
|
+
preset: "static-landing",
|
|
18681
|
+
projectName: inferProjectName(goal, cwd),
|
|
18682
|
+
summary: `${relativePath} already uses the requested ${adjustment.summaryLabel}.`,
|
|
18683
|
+
artifacts: [
|
|
18684
|
+
absolutePath
|
|
18685
|
+
]
|
|
18686
|
+
};
|
|
18687
|
+
}
|
|
18688
|
+
const nextSource = rewriteBackgroundInSource(currentSource, adjustment.background);
|
|
18689
|
+
if (nextSource === currentSource) {
|
|
18690
|
+
continue;
|
|
18691
|
+
}
|
|
18692
|
+
const artifacts = await writeFiles(cwd, {
|
|
18693
|
+
[relativePath]: nextSource
|
|
18694
|
+
});
|
|
18695
|
+
return {
|
|
18696
|
+
preset: "static-landing",
|
|
18697
|
+
projectName: inferProjectName(goal, cwd),
|
|
18698
|
+
summary: `Updated ${relativePath} with a ${adjustment.summaryLabel}.`,
|
|
18699
|
+
artifacts
|
|
18700
|
+
};
|
|
18701
|
+
}
|
|
18702
|
+
return null;
|
|
18703
|
+
}
|
|
18578
18704
|
async function adaptExistingStaticLanding(cwd, projectName, goal, target) {
|
|
18705
|
+
const adjustedResult = await applyExistingStaticVisualAdjustment(cwd, goal, target);
|
|
18706
|
+
if (adjustedResult) {
|
|
18707
|
+
return adjustedResult;
|
|
18708
|
+
}
|
|
18579
18709
|
const title = inferLandingTitle(goal, projectName);
|
|
18580
18710
|
const content = buildLandingContent(title, inferLandingKind(goal));
|
|
18581
18711
|
const files = {};
|
|
@@ -19364,6 +19494,9 @@ function isVerificationShellCommand(command) {
|
|
|
19364
19494
|
const normalized = command.trim().toLowerCase();
|
|
19365
19495
|
return VERIFICATION_SHELL_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix} `));
|
|
19366
19496
|
}
|
|
19497
|
+
function isLowRiskScaffoldRequest(input) {
|
|
19498
|
+
return input.preset === "static-landing" && typeof input.goal === "string" && looksLikeVisualAdjustmentGoal(input.goal);
|
|
19499
|
+
}
|
|
19367
19500
|
function isDestructiveShellCommand(command) {
|
|
19368
19501
|
return DESTRUCTIVE_SHELL_PATTERNS.some((pattern) => pattern.test(command));
|
|
19369
19502
|
}
|
|
@@ -19432,8 +19565,9 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
19432
19565
|
const sandboxMode = context.sandboxMode ?? "workspace-write";
|
|
19433
19566
|
const approvalMode = context.approvalMode ?? "manual";
|
|
19434
19567
|
const command = typeof input.command === "string" ? input.command : "";
|
|
19568
|
+
const isVerificationCommand2 = isVerificationShellCommand(command);
|
|
19435
19569
|
if (sandboxMode === "read-only") {
|
|
19436
|
-
if (toolId === "shell.exec" && (isReadOnlyShellCommand(command) ||
|
|
19570
|
+
if ((toolId === "shell.exec" || toolId === "tests.run") && (isReadOnlyShellCommand(command) || isVerificationCommand2)) {
|
|
19437
19571
|
return null;
|
|
19438
19572
|
}
|
|
19439
19573
|
if (descriptor.permission !== "safe") {
|
|
@@ -19445,7 +19579,10 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
19445
19579
|
return new ToolApprovalRequiredError(createApprovalRequest(toolId, input, descriptor, context, `Approval required for destructive shell command: ${command}`));
|
|
19446
19580
|
}
|
|
19447
19581
|
}
|
|
19448
|
-
if (toolId === "shell.exec" &&
|
|
19582
|
+
if ((toolId === "shell.exec" || toolId === "tests.run") && isVerificationCommand2) {
|
|
19583
|
+
return null;
|
|
19584
|
+
}
|
|
19585
|
+
if (toolId === "scaffold.generate" && isLowRiskScaffoldRequest(input)) {
|
|
19449
19586
|
return null;
|
|
19450
19587
|
}
|
|
19451
19588
|
if ((toolId === "file.write" || toolId === "file.patch") && sandboxMode === "workspace-write") {
|
|
@@ -27626,6 +27763,37 @@ var MCP_INVENTORY_TIMEOUT_MS = 8e3;
|
|
|
27626
27763
|
function toMcpToolId(serverName, toolName) {
|
|
27627
27764
|
return `mcp.${serverName}.${toolName}`;
|
|
27628
27765
|
}
|
|
27766
|
+
function normalizeMcpCommandSegment(value) {
|
|
27767
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
27768
|
+
}
|
|
27769
|
+
async function resolveMcpServerInventoryByReference(cwd, serverReference) {
|
|
27770
|
+
const inventory = await loadMcpServerInventory(cwd);
|
|
27771
|
+
const normalizedReference = normalizeMcpCommandSegment(serverReference);
|
|
27772
|
+
const server = inventory.find((candidate) => candidate.name === serverReference || normalizeMcpCommandSegment(candidate.name) === normalizedReference);
|
|
27773
|
+
if (!server) {
|
|
27774
|
+
throw new Error(`MCP server ${serverReference} is not configured or did not respond.`);
|
|
27775
|
+
}
|
|
27776
|
+
if (server.warning) {
|
|
27777
|
+
throw new Error(`MCP server ${server.name} is unavailable: ${server.warning}`);
|
|
27778
|
+
}
|
|
27779
|
+
return server;
|
|
27780
|
+
}
|
|
27781
|
+
async function resolveMcpPromptReference(cwd, serverReference, promptReference) {
|
|
27782
|
+
const server = await resolveMcpServerInventoryByReference(cwd, serverReference);
|
|
27783
|
+
const normalizedPromptReference = normalizeMcpCommandSegment(promptReference);
|
|
27784
|
+
const prompt = server.prompts.find((candidate) => candidate.name === promptReference || normalizeMcpCommandSegment(candidate.name) === normalizedPromptReference);
|
|
27785
|
+
if (!prompt) {
|
|
27786
|
+
throw new Error(`MCP prompt ${promptReference} was not found on server ${server.name}.`);
|
|
27787
|
+
}
|
|
27788
|
+
return {
|
|
27789
|
+
serverName: server.name,
|
|
27790
|
+
promptName: prompt.name
|
|
27791
|
+
};
|
|
27792
|
+
}
|
|
27793
|
+
async function resolveMcpServerName(cwd, serverReference) {
|
|
27794
|
+
const server = await resolveMcpServerInventoryByReference(cwd, serverReference);
|
|
27795
|
+
return server.name;
|
|
27796
|
+
}
|
|
27629
27797
|
function permissionFromAnnotations(annotations) {
|
|
27630
27798
|
if (annotations?.destructiveHint) {
|
|
27631
27799
|
return "destructive";
|
|
@@ -27785,23 +27953,24 @@ async function discoverMcpTools(cwd) {
|
|
|
27785
27953
|
}
|
|
27786
27954
|
async function callMcpTool(cwd, serverName, toolName, input) {
|
|
27787
27955
|
const config2 = await loadMcpConfig(cwd);
|
|
27788
|
-
const
|
|
27956
|
+
const resolvedServerName = await resolveMcpServerName(cwd, serverName).catch(() => serverName);
|
|
27957
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27789
27958
|
if (!server || server.enabled === false) {
|
|
27790
27959
|
return {
|
|
27791
|
-
toolId: toMcpToolId(
|
|
27960
|
+
toolId: toMcpToolId(resolvedServerName, toolName),
|
|
27792
27961
|
success: false,
|
|
27793
|
-
summary: `MCP server ${
|
|
27962
|
+
summary: `MCP server ${resolvedServerName} is not configured or is disabled.`,
|
|
27794
27963
|
artifacts: []
|
|
27795
27964
|
};
|
|
27796
27965
|
}
|
|
27797
|
-
const result = await withMcpClient(cwd,
|
|
27966
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.callTool({
|
|
27798
27967
|
name: toolName,
|
|
27799
27968
|
arguments: Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0))
|
|
27800
27969
|
}));
|
|
27801
27970
|
return {
|
|
27802
|
-
toolId: toMcpToolId(
|
|
27971
|
+
toolId: toMcpToolId(resolvedServerName, toolName),
|
|
27803
27972
|
success: !result.isError,
|
|
27804
|
-
summary: result.isError ? `MCP tool ${
|
|
27973
|
+
summary: result.isError ? `MCP tool ${resolvedServerName}/${toolName} reported an error.` : `Ran MCP tool ${resolvedServerName}/${toolName}.`,
|
|
27805
27974
|
stdout: renderMcpContent(result),
|
|
27806
27975
|
artifacts: []
|
|
27807
27976
|
};
|
|
@@ -27823,18 +27992,19 @@ ${"text" in resource ? resource.text : `[binary ${resource.mimeType ?? "resource
|
|
|
27823
27992
|
}).join("\n\n");
|
|
27824
27993
|
}
|
|
27825
27994
|
async function invokeMcpPrompt(cwd, serverName, promptName, args) {
|
|
27995
|
+
const { serverName: resolvedServerName, promptName: resolvedPromptName } = await resolveMcpPromptReference(cwd, serverName, promptName);
|
|
27826
27996
|
const config2 = await loadMcpConfig(cwd);
|
|
27827
|
-
const server = config2.mcpServers[
|
|
27997
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27828
27998
|
if (!server || server.enabled === false) {
|
|
27829
|
-
throw new Error(`MCP server ${
|
|
27999
|
+
throw new Error(`MCP server ${resolvedServerName} is not configured or is disabled.`);
|
|
27830
28000
|
}
|
|
27831
|
-
const result = await withMcpClient(cwd,
|
|
27832
|
-
name:
|
|
28001
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.getPrompt({
|
|
28002
|
+
name: resolvedPromptName,
|
|
27833
28003
|
arguments: args
|
|
27834
28004
|
}));
|
|
27835
28005
|
return {
|
|
27836
|
-
serverName,
|
|
27837
|
-
promptName,
|
|
28006
|
+
serverName: resolvedServerName,
|
|
28007
|
+
promptName: resolvedPromptName,
|
|
27838
28008
|
...result.description ? {
|
|
27839
28009
|
description: result.description
|
|
27840
28010
|
} : {},
|
|
@@ -27842,19 +28012,20 @@ async function invokeMcpPrompt(cwd, serverName, promptName, args) {
|
|
|
27842
28012
|
};
|
|
27843
28013
|
}
|
|
27844
28014
|
async function readMcpResource(cwd, serverName, uri) {
|
|
28015
|
+
const resolvedServerName = await resolveMcpServerName(cwd, serverName);
|
|
27845
28016
|
const config2 = await loadMcpConfig(cwd);
|
|
27846
|
-
const server = config2.mcpServers[
|
|
28017
|
+
const server = config2.mcpServers[resolvedServerName];
|
|
27847
28018
|
if (!server || server.enabled === false) {
|
|
27848
|
-
throw new Error(`MCP server ${
|
|
28019
|
+
throw new Error(`MCP server ${resolvedServerName} is not configured or is disabled.`);
|
|
27849
28020
|
}
|
|
27850
|
-
const result = await withMcpClient(cwd,
|
|
28021
|
+
const result = await withMcpClient(cwd, resolvedServerName, server, async (client) => client.readResource({
|
|
27851
28022
|
uri
|
|
27852
28023
|
}));
|
|
27853
28024
|
const content = result.contents.map((item) => "text" in item ? `resource: ${item.uri}
|
|
27854
28025
|
${item.text}` : `resource: ${item.uri}
|
|
27855
28026
|
[binary ${item.mimeType ?? "resource"}]`).join("\n\n");
|
|
27856
28027
|
return {
|
|
27857
|
-
serverName,
|
|
28028
|
+
serverName: resolvedServerName,
|
|
27858
28029
|
uri,
|
|
27859
28030
|
content
|
|
27860
28031
|
};
|
|
@@ -29177,6 +29348,66 @@ var import_node_path14 = __toESM(require("node:path"), 1);
|
|
|
29177
29348
|
function normalizeGoal(goal) {
|
|
29178
29349
|
return goal.trim().replace(/\s+/g, " ");
|
|
29179
29350
|
}
|
|
29351
|
+
function looksLikeVisualAdjustmentGoal2(goal) {
|
|
29352
|
+
const lower = goal.toLowerCase();
|
|
29353
|
+
const backendSignals = [
|
|
29354
|
+
"api",
|
|
29355
|
+
"database",
|
|
29356
|
+
"backend",
|
|
29357
|
+
"server",
|
|
29358
|
+
"migration",
|
|
29359
|
+
"schema",
|
|
29360
|
+
"prisma",
|
|
29361
|
+
"postgres",
|
|
29362
|
+
"sqlite",
|
|
29363
|
+
"auth",
|
|
29364
|
+
"billing",
|
|
29365
|
+
"webhook"
|
|
29366
|
+
];
|
|
29367
|
+
const editSignals = [
|
|
29368
|
+
"make",
|
|
29369
|
+
"change",
|
|
29370
|
+
"update",
|
|
29371
|
+
"turn",
|
|
29372
|
+
"switch",
|
|
29373
|
+
"set",
|
|
29374
|
+
"use",
|
|
29375
|
+
"refresh",
|
|
29376
|
+
"restyle",
|
|
29377
|
+
"redesign"
|
|
29378
|
+
];
|
|
29379
|
+
const visualSignals = [
|
|
29380
|
+
"background",
|
|
29381
|
+
"color",
|
|
29382
|
+
"green",
|
|
29383
|
+
"amber",
|
|
29384
|
+
"blue",
|
|
29385
|
+
"pink",
|
|
29386
|
+
"purple",
|
|
29387
|
+
"gradient",
|
|
29388
|
+
"theme",
|
|
29389
|
+
"palette",
|
|
29390
|
+
"styling",
|
|
29391
|
+
"style",
|
|
29392
|
+
"look",
|
|
29393
|
+
"visual",
|
|
29394
|
+
"hero"
|
|
29395
|
+
];
|
|
29396
|
+
const pageContextSignals = [
|
|
29397
|
+
"page",
|
|
29398
|
+
"landing",
|
|
29399
|
+
"lnding",
|
|
29400
|
+
"homepage",
|
|
29401
|
+
"home page",
|
|
29402
|
+
"site",
|
|
29403
|
+
"website",
|
|
29404
|
+
"blog"
|
|
29405
|
+
];
|
|
29406
|
+
if (backendSignals.some((signal) => lower.includes(signal))) {
|
|
29407
|
+
return false;
|
|
29408
|
+
}
|
|
29409
|
+
return editSignals.some((signal) => lower.includes(signal)) && visualSignals.some((signal) => lower.includes(signal)) && (pageContextSignals.some((signal) => lower.includes(signal)) || lower.includes("background"));
|
|
29410
|
+
}
|
|
29180
29411
|
function looksLikeStaticSiteGoal(goal) {
|
|
29181
29412
|
const lower = goal.toLowerCase();
|
|
29182
29413
|
const backendSignals = [
|
|
@@ -29235,6 +29466,9 @@ function looksLikeStaticSiteGoal(goal) {
|
|
|
29235
29466
|
if (lower.includes("blog") && (lower.includes("make") || lower.includes("improve") || lower.includes("enhance") || lower.includes("redesign")) && !backendSignals.some((signal) => lower.includes(signal))) {
|
|
29236
29467
|
return true;
|
|
29237
29468
|
}
|
|
29469
|
+
if (looksLikeVisualAdjustmentGoal2(lower)) {
|
|
29470
|
+
return true;
|
|
29471
|
+
}
|
|
29238
29472
|
return false;
|
|
29239
29473
|
}
|
|
29240
29474
|
function inferProjectShape(goal) {
|
|
@@ -31151,7 +31385,10 @@ function isStaticSiteTask(task, request) {
|
|
|
31151
31385
|
}
|
|
31152
31386
|
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
31387
|
}
|
|
31154
|
-
function shouldDelegateTask(task) {
|
|
31388
|
+
function shouldDelegateTask(task, request) {
|
|
31389
|
+
if (looksLikeVisualAdjustmentGoal(request.goal) && isStaticSiteTask(task, request)) {
|
|
31390
|
+
return false;
|
|
31391
|
+
}
|
|
31155
31392
|
return (task.swarmDepth ?? 0) === 0 && task.type === "implementation" && ![
|
|
31156
31393
|
"repo-analyst",
|
|
31157
31394
|
"planner",
|
|
@@ -31168,7 +31405,7 @@ function terminalExpansionTaskIds(tasks) {
|
|
|
31168
31405
|
return terminalIds.length > 0 ? terminalIds : tasks.map((task) => task.id);
|
|
31169
31406
|
}
|
|
31170
31407
|
function createDefaultDelegationPlan(task, request) {
|
|
31171
|
-
if (!shouldDelegateTask(task)) {
|
|
31408
|
+
if (!shouldDelegateTask(task, request)) {
|
|
31172
31409
|
return null;
|
|
31173
31410
|
}
|
|
31174
31411
|
if (task.agentRole === "frontend-specialist" || isStaticSiteTask(task, request)) {
|
|
@@ -31317,6 +31554,53 @@ function createDefaultDelegationPlan(task, request) {
|
|
|
31317
31554
|
}
|
|
31318
31555
|
return null;
|
|
31319
31556
|
}
|
|
31557
|
+
async function detectAppliedVisualAdjustment(cwd, request) {
|
|
31558
|
+
const adjustment = inferVisualAdjustment(request.goal);
|
|
31559
|
+
if (!adjustment) {
|
|
31560
|
+
return null;
|
|
31561
|
+
}
|
|
31562
|
+
const candidates = [
|
|
31563
|
+
"src/app/page.tsx",
|
|
31564
|
+
"src/pages/index.tsx",
|
|
31565
|
+
"src/app/globals.css",
|
|
31566
|
+
"styles.css",
|
|
31567
|
+
"index.html"
|
|
31568
|
+
];
|
|
31569
|
+
for (const relativePath of candidates) {
|
|
31570
|
+
const absolutePath = import_node_path14.default.join(cwd, relativePath);
|
|
31571
|
+
try {
|
|
31572
|
+
await (0, import_promises14.access)(absolutePath);
|
|
31573
|
+
const contents = await (0, import_promises14.readFile)(absolutePath, "utf8");
|
|
31574
|
+
if (contents.includes(adjustment.background)) {
|
|
31575
|
+
return absolutePath;
|
|
31576
|
+
}
|
|
31577
|
+
} catch {
|
|
31578
|
+
}
|
|
31579
|
+
}
|
|
31580
|
+
return null;
|
|
31581
|
+
}
|
|
31582
|
+
async function detectPreferredVerificationCommand(cwd) {
|
|
31583
|
+
const packagePath = import_node_path14.default.join(cwd, "package.json");
|
|
31584
|
+
try {
|
|
31585
|
+
await (0, import_promises14.access)(packagePath);
|
|
31586
|
+
const raw = await (0, import_promises14.readFile)(packagePath, "utf8");
|
|
31587
|
+
const parsed = JSON.parse(raw);
|
|
31588
|
+
const scripts = parsed.scripts ?? {};
|
|
31589
|
+
const packageManager = parsed.packageManager?.startsWith("pnpm") ? "pnpm" : parsed.packageManager?.startsWith("yarn") ? "yarn" : "npm";
|
|
31590
|
+
if (scripts.build) {
|
|
31591
|
+
return packageManager === "yarn" ? "yarn build" : `${packageManager} run build`;
|
|
31592
|
+
}
|
|
31593
|
+
if (scripts.lint) {
|
|
31594
|
+
return packageManager === "yarn" ? "yarn lint" : `${packageManager} run lint`;
|
|
31595
|
+
}
|
|
31596
|
+
if (scripts.test) {
|
|
31597
|
+
return packageManager === "yarn" ? "yarn test" : `${packageManager} run test`;
|
|
31598
|
+
}
|
|
31599
|
+
} catch {
|
|
31600
|
+
return null;
|
|
31601
|
+
}
|
|
31602
|
+
return null;
|
|
31603
|
+
}
|
|
31320
31604
|
function materializeDelegatedTasks(plan, task, label, strategy, members) {
|
|
31321
31605
|
const existingIds = new Set(flattenPlanTasks(plan).filter((candidate) => candidate.id !== task.id).map((candidate) => candidate.id));
|
|
31322
31606
|
const teamMemberIds = members.map((member) => member.id);
|
|
@@ -31952,6 +32236,9 @@ var ExecutionOrchestrator = class {
|
|
|
31952
32236
|
if (request.workspaceState === "existing" && isStaticSiteTask(task, request) && (task.type === "scaffold" || task.type === "implementation")) {
|
|
31953
32237
|
return this.executeDeterministicStaticSiteTask(sessionId, task, request, resolvedApproval, options, emitProgress);
|
|
31954
32238
|
}
|
|
32239
|
+
if (request.workspaceState === "existing" && looksLikeStaticLandingGoal(request.goal) && task.type === "verification") {
|
|
32240
|
+
return this.executeDeterministicVerificationTask(sessionId, task, request, emitProgress, options.signal);
|
|
32241
|
+
}
|
|
31955
32242
|
if (task.type === "scaffold") {
|
|
31956
32243
|
return this.executeScaffoldTask(sessionId, task, request, plan, resolvedApproval, options, emitProgress);
|
|
31957
32244
|
}
|
|
@@ -32086,7 +32373,69 @@ var ExecutionOrchestrator = class {
|
|
|
32086
32373
|
]))
|
|
32087
32374
|
};
|
|
32088
32375
|
}
|
|
32376
|
+
async executeDeterministicVerificationTask(sessionId, task, request, emitProgress, signal) {
|
|
32377
|
+
const command = await detectPreferredVerificationCommand(request.cwd);
|
|
32378
|
+
if (!command) {
|
|
32379
|
+
return {
|
|
32380
|
+
status: "completed",
|
|
32381
|
+
summary: "No build, lint, or test script was found; verification was recorded as not applicable.",
|
|
32382
|
+
toolResults: [],
|
|
32383
|
+
artifacts: []
|
|
32384
|
+
};
|
|
32385
|
+
}
|
|
32386
|
+
const input = {
|
|
32387
|
+
command
|
|
32388
|
+
};
|
|
32389
|
+
if (emitProgress) {
|
|
32390
|
+
await emitProgress({
|
|
32391
|
+
type: "tool-started",
|
|
32392
|
+
sessionId,
|
|
32393
|
+
taskId: task.id,
|
|
32394
|
+
agentRole: task.agentRole,
|
|
32395
|
+
toolId: "tests.run",
|
|
32396
|
+
input
|
|
32397
|
+
});
|
|
32398
|
+
}
|
|
32399
|
+
const result = await this.safeRunTool("tests.run", input, {
|
|
32400
|
+
cwd: request.cwd,
|
|
32401
|
+
taskId: task.id,
|
|
32402
|
+
agentRole: task.agentRole,
|
|
32403
|
+
...signal ? {
|
|
32404
|
+
signal
|
|
32405
|
+
} : {}
|
|
32406
|
+
});
|
|
32407
|
+
if (emitProgress) {
|
|
32408
|
+
await emitProgress({
|
|
32409
|
+
type: "tool-finished",
|
|
32410
|
+
sessionId,
|
|
32411
|
+
taskId: task.id,
|
|
32412
|
+
agentRole: task.agentRole,
|
|
32413
|
+
toolResult: result
|
|
32414
|
+
});
|
|
32415
|
+
}
|
|
32416
|
+
return {
|
|
32417
|
+
status: result.success ? "completed" : "blocked",
|
|
32418
|
+
summary: result.success ? `Verification passed via ${command}.` : `Verification failed via ${command}.`,
|
|
32419
|
+
toolResults: [
|
|
32420
|
+
result
|
|
32421
|
+
],
|
|
32422
|
+
artifacts: result.artifacts
|
|
32423
|
+
};
|
|
32424
|
+
}
|
|
32089
32425
|
async executeDeterministicStaticSiteTask(sessionId, task, request, resolvedApproval, options, emitProgress) {
|
|
32426
|
+
if (looksLikeVisualAdjustmentGoal(request.goal)) {
|
|
32427
|
+
const appliedArtifact = await detectAppliedVisualAdjustment(request.cwd, request);
|
|
32428
|
+
if (appliedArtifact) {
|
|
32429
|
+
return {
|
|
32430
|
+
status: "completed",
|
|
32431
|
+
summary: `Confirmed the requested visual adjustment in ${import_node_path14.default.relative(request.cwd, appliedArtifact) || appliedArtifact}.`,
|
|
32432
|
+
toolResults: [],
|
|
32433
|
+
artifacts: [
|
|
32434
|
+
appliedArtifact
|
|
32435
|
+
]
|
|
32436
|
+
};
|
|
32437
|
+
}
|
|
32438
|
+
}
|
|
32090
32439
|
const config2 = await loadConfig(request.cwd);
|
|
32091
32440
|
const scaffoldInput = {
|
|
32092
32441
|
goal: request.goal,
|
|
@@ -32482,7 +32831,7 @@ var ExecutionOrchestrator = class {
|
|
|
32482
32831
|
}
|
|
32483
32832
|
async maybeExpandReadyTaskGraph(sessionId, request, plan, events, emitProgress) {
|
|
32484
32833
|
const envelope = this.buildEnvelope(request, plan, sessionId);
|
|
32485
|
-
const candidate = envelope.readyTasks.find((task) => shouldDelegateTask(task));
|
|
32834
|
+
const candidate = envelope.readyTasks.find((task) => shouldDelegateTask(task, request));
|
|
32486
32835
|
if (!candidate) {
|
|
32487
32836
|
return {
|
|
32488
32837
|
plan
|
|
@@ -32703,10 +33052,69 @@ function createAgentsCommand() {
|
|
|
32703
33052
|
});
|
|
32704
33053
|
console.log(`Created ${outputPath}`);
|
|
32705
33054
|
});
|
|
33055
|
+
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) => {
|
|
33056
|
+
if (options.team) {
|
|
33057
|
+
const team = await loadAgentTeamById(process.cwd(), id);
|
|
33058
|
+
if (!team) {
|
|
33059
|
+
throw new Error(`Unknown team "${id}".`);
|
|
33060
|
+
}
|
|
33061
|
+
console.log(team.id);
|
|
33062
|
+
console.log(` label: ${team.label}`);
|
|
33063
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
33064
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
33065
|
+
console.log(` strategy: ${team.strategy}`);
|
|
33066
|
+
console.log(` file: ${team.filePath}`);
|
|
33067
|
+
if (team.description) {
|
|
33068
|
+
console.log("");
|
|
33069
|
+
console.log(team.description);
|
|
33070
|
+
}
|
|
33071
|
+
return;
|
|
33072
|
+
}
|
|
33073
|
+
const agent = await loadCustomAgentById(process.cwd(), id);
|
|
33074
|
+
if (!agent) {
|
|
33075
|
+
throw new Error(`Unknown custom agent "${id}".`);
|
|
33076
|
+
}
|
|
33077
|
+
console.log(agent.id);
|
|
33078
|
+
console.log(` label: ${agent.label}`);
|
|
33079
|
+
console.log(` baseRole: ${agent.baseRole}`);
|
|
33080
|
+
console.log(` brainRole: ${agent.brainRole ?? "-"}`);
|
|
33081
|
+
console.log(` purpose: ${agent.purpose ?? "-"}`);
|
|
33082
|
+
console.log(` match: ${agent.match.join(", ") || "-"}`);
|
|
33083
|
+
console.log(` tools: ${agent.tools.join(", ") || "(inherits base role tools)"}`);
|
|
33084
|
+
console.log(` file: ${agent.filePath}`);
|
|
33085
|
+
if (agent.instructions.trim()) {
|
|
33086
|
+
console.log("");
|
|
33087
|
+
console.log(agent.instructions.trim());
|
|
33088
|
+
}
|
|
33089
|
+
});
|
|
33090
|
+
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) => {
|
|
33091
|
+
const outputPath = options.team ? await deleteAgentTeamFile(process.cwd(), id) : await deleteCustomAgentFile(process.cwd(), id);
|
|
33092
|
+
console.log(`Deleted ${outputPath}`);
|
|
33093
|
+
});
|
|
32706
33094
|
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
33095
|
const outputPath = await createAgentTeamFile(process.cwd(), id, agents, options.label);
|
|
32708
33096
|
console.log(`Created ${outputPath}`);
|
|
32709
33097
|
});
|
|
33098
|
+
command.command("team-show").description("Show one markdown-backed team definition.").argument("<id>", "Team id").action(async (id) => {
|
|
33099
|
+
const team = await loadAgentTeamById(process.cwd(), id);
|
|
33100
|
+
if (!team) {
|
|
33101
|
+
throw new Error(`Unknown team "${id}".`);
|
|
33102
|
+
}
|
|
33103
|
+
console.log(team.id);
|
|
33104
|
+
console.log(` label: ${team.label}`);
|
|
33105
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
33106
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
33107
|
+
console.log(` strategy: ${team.strategy}`);
|
|
33108
|
+
console.log(` file: ${team.filePath}`);
|
|
33109
|
+
if (team.description) {
|
|
33110
|
+
console.log("");
|
|
33111
|
+
console.log(team.description);
|
|
33112
|
+
}
|
|
33113
|
+
});
|
|
33114
|
+
command.command("team-delete").description("Delete one markdown-backed team definition.").argument("<id>", "Team id").action(async (id) => {
|
|
33115
|
+
const outputPath = await deleteAgentTeamFile(process.cwd(), id);
|
|
33116
|
+
console.log(`Deleted ${outputPath}`);
|
|
33117
|
+
});
|
|
32710
33118
|
return command;
|
|
32711
33119
|
}
|
|
32712
33120
|
|
|
@@ -33523,7 +33931,7 @@ async function renderMcpInventory(cwd, name) {
|
|
|
33523
33931
|
` prompts: ${server.prompts.length}`,
|
|
33524
33932
|
...server.prompts.slice(0, 10).flatMap((prompt) => [
|
|
33525
33933
|
` - ${prompt.name}${prompt.arguments.length > 0 ? ` (${prompt.arguments.map((argument) => `${argument.name}${argument.required ? "*" : ""}`).join(", ")})` : ""}`,
|
|
33526
|
-
` command: /mcp__${server.name}__${prompt.name}`
|
|
33934
|
+
` command: /mcp__${normalizeMcpCommandSegment(server.name)}__${normalizeMcpCommandSegment(prompt.name)}`
|
|
33527
33935
|
]),
|
|
33528
33936
|
` resources: ${server.resources.length}`,
|
|
33529
33937
|
...server.resources.slice(0, 10).flatMap((resource) => [
|
|
@@ -33549,7 +33957,7 @@ async function renderMcpPromptList(cwd, name) {
|
|
|
33549
33957
|
] : [],
|
|
33550
33958
|
...server.prompts.length > 0 ? server.prompts.flatMap((prompt) => [
|
|
33551
33959
|
` - ${prompt.name}${prompt.arguments.length > 0 ? ` (${prompt.arguments.map((argument) => `${argument.name}${argument.required ? "*" : ""}`).join(", ")})` : ""}`,
|
|
33552
|
-
` command: /mcp__${server.name}__${prompt.name}`
|
|
33960
|
+
` command: /mcp__${normalizeMcpCommandSegment(server.name)}__${normalizeMcpCommandSegment(prompt.name)}`
|
|
33553
33961
|
]) : [
|
|
33554
33962
|
" - no prompts"
|
|
33555
33963
|
]
|
|
@@ -35490,53 +35898,65 @@ function renderBox(lines) {
|
|
|
35490
35898
|
function renderHelp() {
|
|
35491
35899
|
return [
|
|
35492
35900
|
`${color(DIM, "Commands")}`,
|
|
35493
|
-
|
|
35494
|
-
"/
|
|
35495
|
-
"/
|
|
35496
|
-
"/
|
|
35497
|
-
"/
|
|
35901
|
+
`${color(BOLD, "Core")}`,
|
|
35902
|
+
"/status Show active model, workspace, approvals, and sandbox state.",
|
|
35903
|
+
"/ask <prompt> Chat with the focused model without running the agent.",
|
|
35904
|
+
"/plan <goal> Create a structured plan only.",
|
|
35905
|
+
"/run <goal> Execute a goal immediately.",
|
|
35906
|
+
"/resume Continue the latest paused or awaiting-approval session.",
|
|
35907
|
+
"/review Review the current git diff and summarize risk.",
|
|
35908
|
+
"/clear Redraw the shell.",
|
|
35909
|
+
"/quit, /exit Leave the shell.",
|
|
35910
|
+
"",
|
|
35911
|
+
`${color(BOLD, "Model")}`,
|
|
35912
|
+
"/model Show current provider/model state.",
|
|
35498
35913
|
"/model providers List configured providers.",
|
|
35499
35914
|
"/model add <tpl> [id] Add a provider template.",
|
|
35500
35915
|
"/model use <provider> [model] Switch provider/model for all roles.",
|
|
35501
35916
|
"/model find [search] Discover models for the active provider.",
|
|
35502
|
-
"/model select <n> Pick
|
|
35503
|
-
"/model focus <role> Change
|
|
35504
|
-
"
|
|
35917
|
+
"/model select <n> Pick from the last numbered model list.",
|
|
35918
|
+
"/model focus <role> Change focus to planner, coder, reviewer, or fast.",
|
|
35919
|
+
"",
|
|
35920
|
+
`${color(BOLD, "Permissions")}`,
|
|
35921
|
+
"/permissions Show layered approval, sandbox, and trust settings.",
|
|
35505
35922
|
"/permissions auto|manual Change approval mode.",
|
|
35506
35923
|
"/permissions sandbox <mode> Set read-only, workspace-write, or full.",
|
|
35507
35924
|
"/permissions trust <path> Add a trusted directory.",
|
|
35508
35925
|
"/permissions untrust <path> Remove a trusted directory.",
|
|
35509
|
-
"/
|
|
35510
|
-
"/
|
|
35926
|
+
"/approve [id] Approve a pending risky action and continue.",
|
|
35927
|
+
"/approve-all Approve every pending action in the current session.",
|
|
35928
|
+
"/deny [id] Deny a pending risky action.",
|
|
35929
|
+
"",
|
|
35930
|
+
`${color(BOLD, "Memory")}`,
|
|
35931
|
+
"/init [--memory-only] Build config and durable project understanding files.",
|
|
35932
|
+
"/memory Show init/project/user/agent memory paths.",
|
|
35933
|
+
"/memory refresh Re-scan the project and refresh markdown memory.",
|
|
35511
35934
|
"/memory show <scope> Print init, project, user, or agent memory.",
|
|
35512
|
-
"/memory add <scope>
|
|
35935
|
+
"/memory add <scope> ... Append a markdown memory note.",
|
|
35513
35936
|
"/config Show config, memory, and MCP file locations.",
|
|
35937
|
+
"",
|
|
35938
|
+
`${color(BOLD, "MCP")}`,
|
|
35514
35939
|
"/mcp List configured MCP servers.",
|
|
35940
|
+
"/mcp discover [server] Show MCP tools, prompts-as-commands, and resources.",
|
|
35941
|
+
"/mcp prompt <server> <prompt> [key=value ...] Render one MCP prompt.",
|
|
35942
|
+
"/mcp read <server> <uri> Read one MCP resource.",
|
|
35515
35943
|
"/mcp add <name> --command <cmd> [--arg <value>] [--env KEY=VALUE]",
|
|
35516
35944
|
" 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.",
|
|
35945
|
+
"/mcp__server__prompt ... Invoke an MCP prompt directly from the shell.",
|
|
35946
|
+
"@server:uri Attach an MCP resource inside /ask, /plan, or /run prompts.",
|
|
35947
|
+
"",
|
|
35948
|
+
`${color(BOLD, "Agents")}`,
|
|
35523
35949
|
"/agents List custom agents and teams.",
|
|
35950
|
+
"/agents show <id> Show one custom agent definition.",
|
|
35951
|
+
"/agents delete <id> Delete one custom agent definition.",
|
|
35524
35952
|
"/agents create <id> --base <role> Create a markdown custom agent.",
|
|
35525
35953
|
"/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.",
|
|
35954
|
+
"/agents team show <id> Show one team definition.",
|
|
35955
|
+
"/agents team delete <id> Delete one team definition.",
|
|
35537
35956
|
"",
|
|
35538
35957
|
`${color(DIM, "Tip")}`,
|
|
35539
35958
|
"Type build/change requests directly to run the agent. Type plan/design prompts for planning. Use /ask when you want plain chat.",
|
|
35959
|
+
"MCP prompts behave like slash commands, and MCP resources can be attached inline with @server:uri.",
|
|
35540
35960
|
"Legacy aliases like /providers, /models, /select, /use-model, /brain, and /approval still work.",
|
|
35541
35961
|
"Press Ctrl+C during an active run to pause it and return to the shell, then use /resume to continue."
|
|
35542
35962
|
].join("\n");
|
|
@@ -36769,7 +37189,7 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36769
37189
|
}
|
|
36770
37190
|
return;
|
|
36771
37191
|
}
|
|
36772
|
-
if (subcommand === "tools" || subcommand === "inspect") {
|
|
37192
|
+
if (subcommand === "tools" || subcommand === "inspect" || subcommand === "discover") {
|
|
36773
37193
|
const name = tokens[2]?.trim();
|
|
36774
37194
|
for (const line of await renderMcpInventory(cwd, name)) {
|
|
36775
37195
|
console.log(line);
|
|
@@ -36805,10 +37225,12 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36805
37225
|
return;
|
|
36806
37226
|
}
|
|
36807
37227
|
if (subcommand === "read") {
|
|
36808
|
-
const
|
|
36809
|
-
const
|
|
37228
|
+
const shorthand = tokens[2]?.trim();
|
|
37229
|
+
const shorthandMatch = shorthand?.match(/^@([^:\s]+):(.+)$/);
|
|
37230
|
+
const serverName = shorthandMatch ? shorthandMatch[1] : tokens[2]?.trim();
|
|
37231
|
+
const uri = shorthandMatch ? shorthandMatch[2] : tokens.slice(3).join(" ").trim();
|
|
36810
37232
|
if (!serverName || !uri) {
|
|
36811
|
-
throw new Error("Usage: /mcp read <server> <uri>");
|
|
37233
|
+
throw new Error("Usage: /mcp read <server> <uri> | /mcp read @server:uri");
|
|
36812
37234
|
}
|
|
36813
37235
|
for (const line of await renderMcpResourceRead(cwd, serverName, uri)) {
|
|
36814
37236
|
console.log(line);
|
|
@@ -36878,7 +37300,7 @@ async function handleMcpCommand(cwd, tokens) {
|
|
|
36878
37300
|
console.log(`Added MCP server ${name}`);
|
|
36879
37301
|
return;
|
|
36880
37302
|
}
|
|
36881
|
-
throw new Error("Usage: /mcp [list|
|
|
37303
|
+
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
37304
|
}
|
|
36883
37305
|
async function handleAgentsCommand(cwd, tokens) {
|
|
36884
37306
|
const subcommand = tokens[1]?.trim().toLowerCase();
|
|
@@ -36923,6 +37345,38 @@ async function handleAgentsCommand(cwd, tokens) {
|
|
|
36923
37345
|
console.log(`Created ${outputPath}`);
|
|
36924
37346
|
return;
|
|
36925
37347
|
}
|
|
37348
|
+
if (subcommand === "show") {
|
|
37349
|
+
const id = tokens[2]?.trim();
|
|
37350
|
+
if (!id) {
|
|
37351
|
+
throw new Error("Usage: /agents show <id>");
|
|
37352
|
+
}
|
|
37353
|
+
const agent = await loadCustomAgentById(cwd, id);
|
|
37354
|
+
if (!agent) {
|
|
37355
|
+
throw new Error(`Unknown custom agent "${id}".`);
|
|
37356
|
+
}
|
|
37357
|
+
console.log(`${agent.id}`);
|
|
37358
|
+
console.log(` label: ${agent.label}`);
|
|
37359
|
+
console.log(` baseRole: ${agent.baseRole}`);
|
|
37360
|
+
console.log(` brainRole: ${agent.brainRole ?? "-"}`);
|
|
37361
|
+
console.log(` purpose: ${agent.purpose ?? "-"}`);
|
|
37362
|
+
console.log(` match: ${agent.match.join(", ") || "-"}`);
|
|
37363
|
+
console.log(` tools: ${agent.tools.join(", ") || "(inherits base role tools)"}`);
|
|
37364
|
+
console.log(` file: ${agent.filePath}`);
|
|
37365
|
+
if (agent.instructions.trim()) {
|
|
37366
|
+
console.log("");
|
|
37367
|
+
console.log(agent.instructions.trim());
|
|
37368
|
+
}
|
|
37369
|
+
return;
|
|
37370
|
+
}
|
|
37371
|
+
if (subcommand === "delete") {
|
|
37372
|
+
const id = tokens[2]?.trim();
|
|
37373
|
+
if (!id) {
|
|
37374
|
+
throw new Error("Usage: /agents delete <id>");
|
|
37375
|
+
}
|
|
37376
|
+
const outputPath = await deleteCustomAgentFile(cwd, id);
|
|
37377
|
+
console.log(`Deleted ${outputPath}`);
|
|
37378
|
+
return;
|
|
37379
|
+
}
|
|
36926
37380
|
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "create") {
|
|
36927
37381
|
const id = tokens[3]?.trim();
|
|
36928
37382
|
const agentIds = tokens.slice(4).filter((token) => !token.startsWith("--"));
|
|
@@ -36935,7 +37389,37 @@ async function handleAgentsCommand(cwd, tokens) {
|
|
|
36935
37389
|
console.log(`Created ${outputPath}`);
|
|
36936
37390
|
return;
|
|
36937
37391
|
}
|
|
36938
|
-
|
|
37392
|
+
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "show") {
|
|
37393
|
+
const id = tokens[3]?.trim();
|
|
37394
|
+
if (!id) {
|
|
37395
|
+
throw new Error("Usage: /agents team show <id>");
|
|
37396
|
+
}
|
|
37397
|
+
const team = await loadAgentTeamById(cwd, id);
|
|
37398
|
+
if (!team) {
|
|
37399
|
+
throw new Error(`Unknown team "${id}".`);
|
|
37400
|
+
}
|
|
37401
|
+
console.log(`${team.id}`);
|
|
37402
|
+
console.log(` label: ${team.label}`);
|
|
37403
|
+
console.log(` agents: ${team.agents.join(", ") || "-"}`);
|
|
37404
|
+
console.log(` match: ${team.match.join(", ") || "-"}`);
|
|
37405
|
+
console.log(` strategy: ${team.strategy}`);
|
|
37406
|
+
console.log(` file: ${team.filePath}`);
|
|
37407
|
+
if (team.description) {
|
|
37408
|
+
console.log("");
|
|
37409
|
+
console.log(team.description);
|
|
37410
|
+
}
|
|
37411
|
+
return;
|
|
37412
|
+
}
|
|
37413
|
+
if (subcommand === "team" && tokens[2]?.trim().toLowerCase() === "delete") {
|
|
37414
|
+
const id = tokens[3]?.trim();
|
|
37415
|
+
if (!id) {
|
|
37416
|
+
throw new Error("Usage: /agents team delete <id>");
|
|
37417
|
+
}
|
|
37418
|
+
const outputPath = await deleteAgentTeamFile(cwd, id);
|
|
37419
|
+
console.log(`Deleted ${outputPath}`);
|
|
37420
|
+
return;
|
|
37421
|
+
}
|
|
37422
|
+
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
37423
|
}
|
|
36940
37424
|
async function handleModelSurfaceCommand(cwd, tokens, runtime) {
|
|
36941
37425
|
const subcommand = tokens[1]?.trim().toLowerCase();
|