Skip to content

Commit b1aa4da

Browse files
chore: generate
1 parent 3072556 commit b1aa4da

6 files changed

Lines changed: 227 additions & 39 deletions

File tree

packages/app/src/components/session/session-header.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,7 @@ export function SessionHeader() {
565565
const baseUrl = globalSDK.url
566566
if (!baseUrl) return
567567
try {
568-
const res = await fetch(
569-
`${baseUrl}/methodology/session/${session.id}/report/download`,
570-
)
568+
const res = await fetch(`${baseUrl}/methodology/session/${session.id}/report/download`)
571569
if (!res.ok) {
572570
showToast({
573571
variant: "error",
@@ -580,10 +578,8 @@ export function SessionHeader() {
580578
const a = document.createElement("a")
581579
a.href = url
582580
a.download =
583-
res.headers
584-
.get("content-disposition")
585-
?.split("filename=")[1]
586-
?.replace(/"/g, "") ?? "report.md"
581+
res.headers.get("content-disposition")?.split("filename=")[1]?.replace(/"/g, "") ??
582+
"report.md"
587583
a.click()
588584
URL.revokeObjectURL(url)
589585
showToast({

packages/cyberstrike/src/cli/cmd/tui/component/dialog-report.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ export function DialogReport(props: { sessionID: string; onGenerate?: () => void
8181
</text>
8282

8383
<box flexDirection="column">
84-
<text fg={theme.text}>
85-
Findings: {findings.length} total
86-
</text>
84+
<text fg={theme.text}>Findings: {findings.length} total</text>
8785
<text fg={theme.textMuted}>
8886
{" "}
8987
<Show when={crit > 0}>
@@ -95,12 +93,8 @@ export function DialogReport(props: { sessionID: string; onGenerate?: () => void
9593
<Show when={med > 0}>
9694
<span style={{ fg: theme.warning }}>{med} Medium</span>{" "}
9795
</Show>
98-
<Show when={low > 0}>
99-
{low} Low{" "}
100-
</Show>
101-
<Show when={info > 0}>
102-
{info} Info
103-
</Show>
96+
<Show when={low > 0}>{low} Low </Show>
97+
<Show when={info > 0}>{info} Info</Show>
10498
</text>
10599
</box>
106100

@@ -123,16 +117,20 @@ export function DialogReport(props: { sessionID: string; onGenerate?: () => void
123117
Validation:{" "}
124118
<Show when={report.validation?.passed} fallback={<span style={{ fg: theme.error }}>FAILED</span>}>
125119
<span style={{ fg: theme.success }}>PASSED</span>
126-
</Show>
127-
{" "}({report.validation?.blockingCount ?? 0} blocking, {report.validation?.warningCount ?? 0} warnings)
128-
</text>
129-
<text fg={theme.text}>
130-
Requests: {report.requests?.total ?? 0} total
120+
</Show>{" "}
121+
({report.validation?.blockingCount ?? 0} blocking, {report.validation?.warningCount ?? 0} warnings)
131122
</text>
123+
<text fg={theme.text}>Requests: {report.requests?.total ?? 0} total</text>
132124
</box>
133125

134126
<box paddingTop={1}>
135-
<text fg={theme.primary} onMouseUp={() => { props.onGenerate?.(); dialog.clear() }}>
127+
<text
128+
fg={theme.primary}
129+
onMouseUp={() => {
130+
props.onGenerate?.()
131+
dialog.clear()
132+
}}
133+
>
136134
Press Enter to generate report via agent
137135
</text>
138136
</box>
@@ -142,7 +140,7 @@ export function DialogReport(props: { sessionID: string; onGenerate?: () => void
142140
</Show>
143141

144142
<box paddingTop={1}>
145-
<text fg={theme.textMuted}>Enter Generate Esc Close</text>
143+
<text fg={theme.textMuted}>Enter Generate Esc Close</text>
146144
</box>
147145
</box>
148146
)

packages/cyberstrike/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,8 @@ export function Session() {
585585
sessionID={route.sessionID}
586586
onGenerate={() => {
587587
prompt.set({
588-
input: "Generate final report with generate_report tool. Fill all AI sections and save to .cyberstrike/reports/",
588+
input:
589+
"Generate final report with generate_report tool. Fill all AI sections and save to .cyberstrike/reports/",
589590
parts: [],
590591
})
591592
}}

packages/cyberstrike/src/server/routes/methodology.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,7 @@ export const MethodologyRoutes = lazy(() =>
402402
const reportsDir = path.join(Instance.worktree, ".cyberstrike", "reports")
403403

404404
const glob = new Bun.Glob("report-*.md")
405-
const files = [...glob.scanSync({ cwd: reportsDir, absolute: true })]
406-
.sort()
407-
.reverse()
405+
const files = [...glob.scanSync({ cwd: reportsDir, absolute: true })].sort().reverse()
408406

409407
if (files.length === 0) return c.json({ error: "No reports found" }, 404)
410408

packages/cyberstrike/src/tool/generate-report.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ const ALL_SECTIONS = [
5353
export const GenerateReportTool = Tool.define("generate_report", {
5454
description: DESCRIPTION,
5555
parameters: z.object({
56-
include_sections: z
57-
.array(z.enum(ALL_SECTIONS))
58-
.optional()
59-
.describe("Sections to include (default: all)"),
56+
include_sections: z.array(z.enum(ALL_SECTIONS)).optional().describe("Sections to include (default: all)"),
6057
}),
6158
async execute(params, ctx) {
6259
const rootSession = Session.root(ctx.sessionID)
@@ -105,7 +102,9 @@ export const GenerateReportTool = Tool.define("generate_report", {
105102

106103
if (sections.includes("validation")) parts.push(formatValidationSection(gates))
107104

108-
parts.push("---\n\n<!-- AI: remediation_priorities -->\n\n---\n\n*Generated by CyberStrike (cyberstrike.io) — AI-Powered Offensive Security Platform*")
105+
parts.push(
106+
"---\n\n<!-- AI: remediation_priorities -->\n\n---\n\n*Generated by CyberStrike (cyberstrike.io) — AI-Powered Offensive Security Platform*",
107+
)
109108

110109
return {
111110
title: `Report: ${vulns.length} findings | ${coverage.coveragePercent}% coverage`,
@@ -174,9 +173,7 @@ function formatVulnTable(vulns: Vulnerability.Info[]): string {
174173
counters[sev] = (counters[sev] ?? 0) + 1
175174
const ref = `${sev}-${String(counters[sev]).padStart(3, "0")}`
176175

177-
lines.push(
178-
`| ${ref} | ${sev} | ${v.title} | ${v.endpoint ?? "—"} | ${v.cwe_id ?? "—"} | ${v.status} |`,
179-
)
176+
lines.push(`| ${ref} | ${sev} | ${v.title} | ${v.endpoint ?? "—"} | ${v.cwe_id ?? "—"} | ${v.status} |`)
180177

181178
details.push("")
182179
details.push(`#### [${ref}] ${v.title}`)
@@ -348,10 +345,7 @@ function formatAttackSurface(intel: Intel.Entry[], requests: Request.Info[], ass
348345
return lines.join("\n")
349346
}
350347

351-
function formatTimeline(
352-
vulns: Vulnerability.Info[],
353-
session: { time: { created: number; updated: number } },
354-
): string {
348+
function formatTimeline(vulns: Vulnerability.Info[], session: { time: { created: number; updated: number } }): string {
355349
const lines: string[] = ["## Assessment Timeline", ""]
356350

357351
const startDate = new Date(session.time.created).toISOString()

packages/sdk/openapi.json

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7991,6 +7991,207 @@
79917991
]
79927992
}
79937993
},
7994+
"/methodology/session/{sessionID}/report/compile": {
7995+
"get": {
7996+
"operationId": "methodology.reportCompile",
7997+
"parameters": [
7998+
{
7999+
"in": "query",
8000+
"name": "directory",
8001+
"schema": {
8002+
"type": "string"
8003+
}
8004+
},
8005+
{
8006+
"in": "path",
8007+
"name": "sessionID",
8008+
"schema": {
8009+
"type": "string"
8010+
},
8011+
"required": true
8012+
}
8013+
],
8014+
"summary": "Compile report data",
8015+
"description": "Compiles all session data into a structured report object for UI rendering.",
8016+
"responses": {
8017+
"200": {
8018+
"description": "Compiled report data",
8019+
"content": {
8020+
"application/json": {
8021+
"schema": {
8022+
"type": "object",
8023+
"properties": {
8024+
"session": {
8025+
"type": "object",
8026+
"properties": {
8027+
"title": {
8028+
"type": "string"
8029+
},
8030+
"duration": {
8031+
"type": "number"
8032+
}
8033+
},
8034+
"required": ["title", "duration"]
8035+
},
8036+
"findings": {
8037+
"type": "array",
8038+
"items": {
8039+
"type": "object",
8040+
"propertyNames": {
8041+
"type": "string"
8042+
},
8043+
"additionalProperties": {}
8044+
}
8045+
},
8046+
"coverage": {
8047+
"type": "object",
8048+
"propertyNames": {
8049+
"type": "string"
8050+
},
8051+
"additionalProperties": {}
8052+
},
8053+
"assetCoverage": {
8054+
"type": "array",
8055+
"items": {
8056+
"type": "object",
8057+
"propertyNames": {
8058+
"type": "string"
8059+
},
8060+
"additionalProperties": {}
8061+
}
8062+
},
8063+
"methodology": {
8064+
"type": "object",
8065+
"propertyNames": {
8066+
"type": "string"
8067+
},
8068+
"additionalProperties": {}
8069+
},
8070+
"chains": {
8071+
"type": "array",
8072+
"items": {
8073+
"type": "object",
8074+
"propertyNames": {
8075+
"type": "string"
8076+
},
8077+
"additionalProperties": {}
8078+
}
8079+
},
8080+
"requests": {
8081+
"type": "object",
8082+
"properties": {
8083+
"total": {
8084+
"type": "number"
8085+
},
8086+
"byMethod": {
8087+
"type": "object",
8088+
"propertyNames": {
8089+
"type": "string"
8090+
},
8091+
"additionalProperties": {
8092+
"type": "number"
8093+
}
8094+
}
8095+
},
8096+
"required": ["total", "byMethod"]
8097+
},
8098+
"agents": {
8099+
"type": "array",
8100+
"items": {
8101+
"type": "object",
8102+
"propertyNames": {
8103+
"type": "string"
8104+
},
8105+
"additionalProperties": {}
8106+
}
8107+
},
8108+
"validation": {
8109+
"type": "object",
8110+
"propertyNames": {
8111+
"type": "string"
8112+
},
8113+
"additionalProperties": {}
8114+
}
8115+
},
8116+
"required": [
8117+
"session",
8118+
"findings",
8119+
"coverage",
8120+
"assetCoverage",
8121+
"methodology",
8122+
"chains",
8123+
"requests",
8124+
"agents",
8125+
"validation"
8126+
]
8127+
}
8128+
}
8129+
}
8130+
},
8131+
"404": {
8132+
"description": "Not found",
8133+
"content": {
8134+
"application/json": {
8135+
"schema": {
8136+
"$ref": "#/components/schemas/NotFoundError"
8137+
}
8138+
}
8139+
}
8140+
}
8141+
},
8142+
"x-codeSamples": [
8143+
{
8144+
"lang": "js",
8145+
"source": "import { createCyberstrikeClient } from \"@cyberstrike-io/sdk\n\nconst client = createCyberstrikeClient()\nawait client.methodology.reportCompile({\n ...\n})"
8146+
}
8147+
]
8148+
}
8149+
},
8150+
"/methodology/session/{sessionID}/report/download": {
8151+
"get": {
8152+
"operationId": "methodology.reportDownload",
8153+
"parameters": [
8154+
{
8155+
"in": "query",
8156+
"name": "directory",
8157+
"schema": {
8158+
"type": "string"
8159+
}
8160+
},
8161+
{
8162+
"in": "path",
8163+
"name": "sessionID",
8164+
"schema": {
8165+
"type": "string"
8166+
},
8167+
"required": true
8168+
}
8169+
],
8170+
"summary": "Download latest report",
8171+
"description": "Returns the most recent generated Markdown report for a session.",
8172+
"responses": {
8173+
"200": {
8174+
"description": "Report markdown file"
8175+
},
8176+
"404": {
8177+
"description": "Not found",
8178+
"content": {
8179+
"application/json": {
8180+
"schema": {
8181+
"$ref": "#/components/schemas/NotFoundError"
8182+
}
8183+
}
8184+
}
8185+
}
8186+
},
8187+
"x-codeSamples": [
8188+
{
8189+
"lang": "js",
8190+
"source": "import { createCyberstrikeClient } from \"@cyberstrike-io/sdk\n\nconst client = createCyberstrikeClient()\nawait client.methodology.reportDownload({\n ...\n})"
8191+
}
8192+
]
8193+
}
8194+
},
79948195
"/instance/dispose": {
79958196
"post": {
79968197
"operationId": "instance.dispose",

0 commit comments

Comments
 (0)