@kyo-so/cli 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +297 -0
- package/README.md +98 -5
- package/README.zh-CN.md +297 -0
- package/dist/acp/prompts.d.ts +2 -2
- package/dist/bin/kyoso.js +645 -89
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/setup.d.ts +29 -0
- package/dist/config/schema.d.ts +2 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/types.d.ts +4 -1
- package/dist/index.js +71 -19
- package/dist/workspace/createSnapshot.d.ts +2 -1
- package/examples/claude-only.config.ts +9 -0
- package/examples/codex-only.config.ts +9 -0
- package/package.json +1 -1
package/dist/cli/args.d.ts
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type SetupClient = "codex" | "claude-code";
|
|
2
|
+
export type SetupRunner = "npx" | "bunx";
|
|
3
|
+
export type SetupScope = "project" | "global";
|
|
4
|
+
export type SetupOptions = {
|
|
5
|
+
cwd: string;
|
|
6
|
+
client?: string;
|
|
7
|
+
write: boolean;
|
|
8
|
+
global: boolean;
|
|
9
|
+
runner?: string;
|
|
10
|
+
command?: string;
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
};
|
|
13
|
+
type McpCommand = {
|
|
14
|
+
command: string;
|
|
15
|
+
args: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare function runSetup(options: SetupOptions): Promise<string>;
|
|
18
|
+
export declare function commandForRunner(runner: SetupRunner): McpCommand;
|
|
19
|
+
export declare function buildCodexMcpToml(command: McpCommand): string;
|
|
20
|
+
export declare function buildClaudeMcpEntry(command: McpCommand): Record<string, unknown>;
|
|
21
|
+
export declare function skillDestination(client: SetupClient, scope: SetupScope, cwd: string, home: string): string;
|
|
22
|
+
export declare function detectSetup(options: {
|
|
23
|
+
cwd: string;
|
|
24
|
+
home?: string;
|
|
25
|
+
}): Record<SetupClient, {
|
|
26
|
+
mcp: boolean;
|
|
27
|
+
skill: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
export {};
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare const kyosoConfigSchema: z.ZodObject<{
|
|
|
23
23
|
role: z.ZodEnum<{
|
|
24
24
|
implementation_reviewer: "implementation_reviewer";
|
|
25
25
|
architecture_security_reviewer: "architecture_security_reviewer";
|
|
26
|
+
combined_reviewer: "combined_reviewer";
|
|
26
27
|
}>;
|
|
27
28
|
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
28
29
|
env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
@@ -43,6 +44,7 @@ export declare const kyosoConfigSchema: z.ZodObject<{
|
|
|
43
44
|
role: z.ZodEnum<{
|
|
44
45
|
implementation_reviewer: "implementation_reviewer";
|
|
45
46
|
architecture_security_reviewer: "architecture_security_reviewer";
|
|
47
|
+
combined_reviewer: "combined_reviewer";
|
|
46
48
|
}>;
|
|
47
49
|
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
48
50
|
env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
package/dist/core/constants.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export declare const DEFAULT_MAX_DIFF_BYTES = 300000;
|
|
|
4
4
|
export declare const RAW_OUTPUT_MAX_CHARS = 16384;
|
|
5
5
|
export declare const TRACE_DIR = ".kyoso/traces";
|
|
6
6
|
export declare const KYOSO_CHILD_AGENT = "KYOSO_CHILD_AGENT";
|
|
7
|
-
export declare const KYOSO_VERSION = "0.
|
|
7
|
+
export declare const KYOSO_VERSION = "0.3.0";
|
package/dist/core/types.d.ts
CHANGED
|
@@ -59,7 +59,8 @@ export type CisaSecureByDesignResult = {
|
|
|
59
59
|
notes: string[];
|
|
60
60
|
};
|
|
61
61
|
export type AgentName = "codex" | "claude";
|
|
62
|
-
export type AgentRole = "implementation_reviewer" | "architecture_security_reviewer";
|
|
62
|
+
export type AgentRole = "implementation_reviewer" | "architecture_security_reviewer" | "combined_reviewer";
|
|
63
|
+
export type ReviewMode = "multi_agent" | "single_agent";
|
|
63
64
|
export type NormalizedAgentOpinion = {
|
|
64
65
|
agent: AgentName;
|
|
65
66
|
role: string;
|
|
@@ -110,6 +111,8 @@ export type AgentRunResult = {
|
|
|
110
111
|
export type KyosoResult = {
|
|
111
112
|
decision: KyosoDecision;
|
|
112
113
|
degraded: boolean;
|
|
114
|
+
agentsUsed: AgentName[];
|
|
115
|
+
reviewMode: ReviewMode;
|
|
113
116
|
summaryMarkdown: string;
|
|
114
117
|
findings: KyosoFinding[];
|
|
115
118
|
cisaSecureByDesign?: CisaSecureByDesignResult;
|
package/dist/index.js
CHANGED
|
@@ -183783,7 +183783,11 @@ var agentSchema = exports_external.object({
|
|
|
183783
183783
|
command: exports_external.string(),
|
|
183784
183784
|
args: exports_external.array(exports_external.string()).default([]),
|
|
183785
183785
|
model: exports_external.string().optional(),
|
|
183786
|
-
role: exports_external.enum([
|
|
183786
|
+
role: exports_external.enum([
|
|
183787
|
+
"implementation_reviewer",
|
|
183788
|
+
"architecture_security_reviewer",
|
|
183789
|
+
"combined_reviewer"
|
|
183790
|
+
]),
|
|
183787
183791
|
timeoutMs: exports_external.number().int().positive().default(120000),
|
|
183788
183792
|
env: exports_external.record(exports_external.string(), exports_external.string()).default({}),
|
|
183789
183793
|
auth: exports_external.object({
|
|
@@ -188100,7 +188104,7 @@ function buildOpinion(agent, role, tool) {
|
|
|
188100
188104
|
}
|
|
188101
188105
|
|
|
188102
188106
|
// src/acp/prompts.ts
|
|
188103
|
-
function buildAgentPrompt(tool, request, agent) {
|
|
188107
|
+
function buildAgentPrompt(tool, request, agent, role) {
|
|
188104
188108
|
const shared = [
|
|
188105
188109
|
"You are running as a Kyoso child reviewer.",
|
|
188106
188110
|
"Do not edit files.",
|
|
@@ -188113,15 +188117,26 @@ function buildAgentPrompt(tool, request, agent) {
|
|
|
188113
188117
|
"Use empty arrays when no finding, test, risk, or question exists; do not copy the example finding."
|
|
188114
188118
|
].join(`
|
|
188115
188119
|
`);
|
|
188116
|
-
const
|
|
188117
|
-
|
|
188118
|
-
|
|
188119
|
-
|
|
188120
|
-
`
|
|
188121
|
-
|
|
188122
|
-
|
|
188123
|
-
|
|
188124
|
-
|
|
188120
|
+
const roleInstructions = {
|
|
188121
|
+
implementation_reviewer: [
|
|
188122
|
+
"You are the implementation reviewer role in Kyoso.",
|
|
188123
|
+
"Focus on feasibility, minimal change, existing code consistency, regression risk, tests, migration risk, and maintainability."
|
|
188124
|
+
].join(`
|
|
188125
|
+
`),
|
|
188126
|
+
architecture_security_reviewer: [
|
|
188127
|
+
"You are the architecture and security reviewer role in Kyoso.",
|
|
188128
|
+
"Focus on architecture, threat modeling, authn/authz, secrets, privacy, secure defaults, CISA Secure by Design, and edge cases."
|
|
188129
|
+
].join(`
|
|
188130
|
+
`),
|
|
188131
|
+
combined_reviewer: [
|
|
188132
|
+
"You are the combined reviewer role in Kyoso.",
|
|
188133
|
+
"Cover both implementation review and architecture/security review in one pass.",
|
|
188134
|
+
"First assess feasibility, minimal change, existing code consistency, regression risk, tests, migration risk, and maintainability.",
|
|
188135
|
+
"Then assess architecture, threat modeling, authn/authz, secrets, privacy, secure defaults, CISA Secure by Design, and edge cases.",
|
|
188136
|
+
"Use finding category values so readers can distinguish implementation, architecture, and security concerns."
|
|
188137
|
+
].join(`
|
|
188138
|
+
`)
|
|
188139
|
+
};
|
|
188125
188140
|
const cisaInstruction = tool === "security_review" ? [
|
|
188126
188141
|
"For security_review, include cisaMapping on each security-relevant finding when applicable.",
|
|
188127
188142
|
"Also include cisaSecureByDesign with all four gate dimensions."
|
|
@@ -188129,7 +188144,9 @@ function buildAgentPrompt(tool, request, agent) {
|
|
|
188129
188144
|
`) : "For plan_review and diff_review, include cisaMapping and cisaSecureByDesign only when relevant.";
|
|
188130
188145
|
return `${shared}
|
|
188131
188146
|
|
|
188132
|
-
${
|
|
188147
|
+
Agent: ${agent}
|
|
188148
|
+
Role: ${role}
|
|
188149
|
+
${roleInstructions[role]}
|
|
188133
188150
|
|
|
188134
188151
|
Tool: ${tool}
|
|
188135
188152
|
${cisaInstruction}
|
|
@@ -188716,6 +188733,7 @@ function renderMarkdownResult(tool, result, options = {}) {
|
|
|
188716
188733
|
`**Decision:** ${result.decision}`,
|
|
188717
188734
|
`**Mode:** ${tool}`,
|
|
188718
188735
|
`**Agents:** ${result.agentOpinions.map((opinion) => `${title(opinion.agent)} ${opinion.status}`).join(", ")}`,
|
|
188736
|
+
`**Review mode:** ${formatReviewMode(result)}`,
|
|
188719
188737
|
`**Degraded:** ${String(result.degraded)}`,
|
|
188720
188738
|
"",
|
|
188721
188739
|
"## Summary",
|
|
@@ -188742,7 +188760,11 @@ function renderMarkdownResult(tool, result, options = {}) {
|
|
|
188742
188760
|
lines.push(`### ${title(opinion.agent)}`, "", `${opinion.summary} (${opinion.status})`, "");
|
|
188743
188761
|
}
|
|
188744
188762
|
lines.push("", "## Disagreements", "");
|
|
188745
|
-
|
|
188763
|
+
if (result.reviewMode === "single_agent") {
|
|
188764
|
+
lines.push("- N/A - single-agent review.");
|
|
188765
|
+
} else {
|
|
188766
|
+
lines.push(...result.disagreements.length > 0 ? result.disagreements.map((item) => `- ${item.topic}: ${item.judgeComment}`) : ["- None."]);
|
|
188767
|
+
}
|
|
188746
188768
|
lines.push("", "## Notes", "", "Kyoso did not modify files. Review was performed on a temporary snapshot.");
|
|
188747
188769
|
if (result.audit.networkMode === "unrestricted") {
|
|
188748
188770
|
lines.push("Network mode was unrestricted. File modification policy remained denied.");
|
|
@@ -188756,6 +188778,14 @@ function defaultSummaryText(result) {
|
|
|
188756
188778
|
function title(value) {
|
|
188757
188779
|
return value.slice(0, 1).toUpperCase() + value.slice(1);
|
|
188758
188780
|
}
|
|
188781
|
+
function formatReviewMode(result) {
|
|
188782
|
+
if (result.reviewMode !== "single_agent")
|
|
188783
|
+
return "multi-agent";
|
|
188784
|
+
const opinion = result.agentOpinions[0];
|
|
188785
|
+
const agent = opinion ? title(opinion.agent) : "single agent";
|
|
188786
|
+
const role = opinion?.role === "combined_reviewer" ? "combined role" : "configured role";
|
|
188787
|
+
return `single-agent (${agent}, ${role}; cross-model verification was not performed)`;
|
|
188788
|
+
}
|
|
188759
188789
|
function notes(items) {
|
|
188760
188790
|
return (items[0] ?? "No notes.").replaceAll("|", "\\|");
|
|
188761
188791
|
}
|
|
@@ -189209,8 +189239,8 @@ async function createSnapshot(traceId, tool, request, options = {}) {
|
|
|
189209
189239
|
}
|
|
189210
189240
|
await writeFile2(join3(contextDir, "request.json"), JSON.stringify(stripContents(request), null, 2), "utf8");
|
|
189211
189241
|
await writeFile2(join3(contextDir, "selected_files_manifest.json"), JSON.stringify(buildSelectedFilesManifest(request), null, 2), "utf8");
|
|
189212
|
-
await writeFile2(join3(contextDir, "instructions.codex.md"), buildAgentPrompt(tool, request, "codex"), "utf8");
|
|
189213
|
-
await writeFile2(join3(contextDir, "instructions.claude.md"), buildAgentPrompt(tool, request, "claude"), "utf8");
|
|
189242
|
+
await writeFile2(join3(contextDir, "instructions.codex.md"), buildAgentPrompt(tool, request, "codex", options.agentRoles?.codex ?? "implementation_reviewer"), "utf8");
|
|
189243
|
+
await writeFile2(join3(contextDir, "instructions.claude.md"), buildAgentPrompt(tool, request, "claude", options.agentRoles?.claude ?? "architecture_security_reviewer"), "utf8");
|
|
189214
189244
|
if (request.repoSummary)
|
|
189215
189245
|
await writeFile2(join3(contextDir, "repo_summary.md"), request.repoSummary, "utf8");
|
|
189216
189246
|
if (request.currentPlan)
|
|
@@ -189372,9 +189402,11 @@ async function runReview(tool, request, options = {}) {
|
|
|
189372
189402
|
allowPatterns
|
|
189373
189403
|
});
|
|
189374
189404
|
warnings.push(...built.warnings);
|
|
189405
|
+
const agentRoles = resolveAgentRoles(loaded.config);
|
|
189375
189406
|
snapshot = await createSnapshot(traceId, tool, built.request, {
|
|
189376
189407
|
denyPatterns,
|
|
189377
|
-
allowPatterns
|
|
189408
|
+
allowPatterns,
|
|
189409
|
+
agentRoles
|
|
189378
189410
|
});
|
|
189379
189411
|
await trace.write({
|
|
189380
189412
|
type: "snapshot_created",
|
|
@@ -189394,6 +189426,8 @@ async function runReview(tool, request, options = {}) {
|
|
|
189394
189426
|
trace
|
|
189395
189427
|
});
|
|
189396
189428
|
const normalizedAgentResults = agentResults.map(normalizeAgentRunResult);
|
|
189429
|
+
const agentsUsed = normalizedAgentResults.map((result2) => result2.agent);
|
|
189430
|
+
const reviewMode = agentsUsed.length === 1 ? "single_agent" : "multi_agent";
|
|
189397
189431
|
const completed = normalizedAgentResults.filter((result2) => result2.status === "completed");
|
|
189398
189432
|
const degraded = completed.length !== agentResults.length;
|
|
189399
189433
|
let aggregate = aggregateAgentResults(normalizedAgentResults);
|
|
@@ -189445,6 +189479,8 @@ async function runReview(tool, request, options = {}) {
|
|
|
189445
189479
|
const resultWithoutMarkdown = {
|
|
189446
189480
|
decision,
|
|
189447
189481
|
degraded,
|
|
189482
|
+
agentsUsed,
|
|
189483
|
+
reviewMode,
|
|
189448
189484
|
findings: aggregate.findings,
|
|
189449
189485
|
cisaSecureByDesign: cisa,
|
|
189450
189486
|
disagreements: aggregate.disagreements,
|
|
@@ -189457,7 +189493,7 @@ async function runReview(tool, request, options = {}) {
|
|
|
189457
189493
|
traceId,
|
|
189458
189494
|
startedAt,
|
|
189459
189495
|
completedAt,
|
|
189460
|
-
agentsUsed
|
|
189496
|
+
agentsUsed,
|
|
189461
189497
|
redactionsApplied: secretScan.redactions,
|
|
189462
189498
|
networkMode,
|
|
189463
189499
|
workspaceMode: "temp_snapshot",
|
|
@@ -189516,12 +189552,13 @@ async function runReview(tool, request, options = {}) {
|
|
|
189516
189552
|
}
|
|
189517
189553
|
}
|
|
189518
189554
|
async function runAgents(input) {
|
|
189555
|
+
const agentRoles = resolveAgentRoles(input.config);
|
|
189519
189556
|
const agentInputs = ["codex", "claude"].filter((agent) => input.config.agents[agent].enabled).map((agent) => ({
|
|
189520
189557
|
traceId: input.traceId,
|
|
189521
189558
|
agent,
|
|
189522
|
-
role: input.config.agents[agent].role,
|
|
189559
|
+
role: agentRoles[agent] ?? input.config.agents[agent].role,
|
|
189523
189560
|
tool: input.tool,
|
|
189524
|
-
prompt: buildAgentPrompt(input.tool, input.request, agent),
|
|
189561
|
+
prompt: buildAgentPrompt(input.tool, input.request, agent, agentRoles[agent] ?? input.config.agents[agent].role),
|
|
189525
189562
|
workspaceDir: input.workspaceDir,
|
|
189526
189563
|
timeoutMs: input.request.options?.maxAgentTimeoutMs ?? input.config.agents[agent].timeoutMs ?? DEFAULT_AGENT_TIMEOUT_MS,
|
|
189527
189564
|
networkMode: input.networkMode
|
|
@@ -189530,6 +189567,7 @@ async function runAgents(input) {
|
|
|
189530
189567
|
type: "agent_started",
|
|
189531
189568
|
traceId: input.traceId,
|
|
189532
189569
|
agent: agentInput.agent,
|
|
189570
|
+
role: agentInput.role,
|
|
189533
189571
|
timestamp: new Date().toISOString()
|
|
189534
189572
|
})));
|
|
189535
189573
|
const results = await input.manager.runAll(agentInputs);
|
|
@@ -189538,6 +189576,7 @@ async function runAgents(input) {
|
|
|
189538
189576
|
type: "agent_completed",
|
|
189539
189577
|
traceId: input.traceId,
|
|
189540
189578
|
agent: result.agent,
|
|
189579
|
+
role: result.role,
|
|
189541
189580
|
status: result.status,
|
|
189542
189581
|
startedAt: result.startedAt,
|
|
189543
189582
|
completedAt: result.completedAt,
|
|
@@ -189554,6 +189593,15 @@ async function runAgents(input) {
|
|
|
189554
189593
|
}));
|
|
189555
189594
|
return results;
|
|
189556
189595
|
}
|
|
189596
|
+
function resolveAgentRoles(config2) {
|
|
189597
|
+
const enabledAgents = ["codex", "claude"].filter((agent) => config2.agents[agent].enabled);
|
|
189598
|
+
const singleAgentMode = enabledAgents.length === 1;
|
|
189599
|
+
const roles = {};
|
|
189600
|
+
for (const agent of enabledAgents) {
|
|
189601
|
+
roles[agent] = singleAgentMode ? "combined_reviewer" : config2.agents[agent].role;
|
|
189602
|
+
}
|
|
189603
|
+
return roles;
|
|
189604
|
+
}
|
|
189557
189605
|
function defaultAgentManager(config2) {
|
|
189558
189606
|
if (process.env.KYOSO_TEST_FAKE_AGENTS === "1")
|
|
189559
189607
|
return new FakeAgentManager;
|
|
@@ -189591,6 +189639,8 @@ async function buildSecretBlockResult(input) {
|
|
|
189591
189639
|
const resultWithoutMarkdown = {
|
|
189592
189640
|
decision: "block",
|
|
189593
189641
|
degraded: false,
|
|
189642
|
+
agentsUsed: [],
|
|
189643
|
+
reviewMode: "multi_agent",
|
|
189594
189644
|
findings: [finding],
|
|
189595
189645
|
cisaSecureByDesign: cisa,
|
|
189596
189646
|
disagreements: [],
|
|
@@ -189671,6 +189721,8 @@ async function buildPolicyBlockResult(input) {
|
|
|
189671
189721
|
const resultWithoutMarkdown = {
|
|
189672
189722
|
decision: "block",
|
|
189673
189723
|
degraded: false,
|
|
189724
|
+
agentsUsed: [],
|
|
189725
|
+
reviewMode: "multi_agent",
|
|
189674
189726
|
findings: [input.finding],
|
|
189675
189727
|
cisaSecureByDesign: input.tool === "security_review" ? computeCisaGate([input.finding], []) : undefined,
|
|
189676
189728
|
disagreements: [],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { KyosoReviewRequest, ReviewTool } from "../core/types.js";
|
|
1
|
+
import type { AgentName, AgentRole, KyosoReviewRequest, ReviewTool } from "../core/types.js";
|
|
2
2
|
export type Snapshot = {
|
|
3
3
|
root: string;
|
|
4
4
|
repoDir: string;
|
|
@@ -8,4 +8,5 @@ export type Snapshot = {
|
|
|
8
8
|
export declare function createSnapshot(traceId: string, tool: ReviewTool, request: KyosoReviewRequest, options?: {
|
|
9
9
|
denyPatterns?: string[];
|
|
10
10
|
allowPatterns?: string[];
|
|
11
|
+
agentRoles?: Partial<Record<AgentName, AgentRole>>;
|
|
11
12
|
}): Promise<Snapshot>;
|