dsh-pentester 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -6
- package/agents/vulnerability/profile.yml +6 -3
- package/lib/build-id.json +1 -1
- package/lib/client.js +993 -403
- package/lib/client.js.map +4 -4
- package/lib/index.js +97 -38
- package/lib/index.js.map +1 -1
- package/package.json +5 -3
package/lib/client.js
CHANGED
|
@@ -40,7 +40,7 @@ __export(plugin_exports, {
|
|
|
40
40
|
setPentesterEndpointState: () => setPentesterEndpointState
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(plugin_exports);
|
|
43
|
-
var
|
|
43
|
+
var import_react20 = __toESM(require("react"), 1);
|
|
44
44
|
|
|
45
45
|
// node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
46
46
|
var external_exports = {};
|
|
@@ -15397,7 +15397,7 @@ function isPentesterRootSession(snapshot, id) {
|
|
|
15397
15397
|
}
|
|
15398
15398
|
|
|
15399
15399
|
// src/ui/client/pentester-view.tsx
|
|
15400
|
-
var
|
|
15400
|
+
var import_react19 = __toESM(require("react"), 1);
|
|
15401
15401
|
|
|
15402
15402
|
// src/ui/client/pentester/navigation.ts
|
|
15403
15403
|
var PENTESTER_TABS = [
|
|
@@ -16100,8 +16100,71 @@ function LegendItem(props) {
|
|
|
16100
16100
|
}
|
|
16101
16101
|
|
|
16102
16102
|
// src/ui/client/pentester/FindingsView.tsx
|
|
16103
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
16104
|
+
var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
16105
|
+
|
|
16106
|
+
// src/ui/client/pentester/CopyAction.tsx
|
|
16103
16107
|
var import_react10 = __toESM(require("react"), 1);
|
|
16104
16108
|
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
16109
|
+
function CopyAction(props) {
|
|
16110
|
+
const { text } = props;
|
|
16111
|
+
const [copied, setCopied] = (0, import_react10.useState)(false);
|
|
16112
|
+
const timerRef = (0, import_react10.useRef)(null);
|
|
16113
|
+
const pendingRef = (0, import_react10.useRef)(false);
|
|
16114
|
+
const handleCopy = (0, import_react10.useCallback)(() => {
|
|
16115
|
+
if (copied || pendingRef.current) return;
|
|
16116
|
+
pendingRef.current = true;
|
|
16117
|
+
void (0, import_dsh_client_ui_primitives3.writeClipboard)(text).then((ok) => {
|
|
16118
|
+
pendingRef.current = false;
|
|
16119
|
+
if (!ok) return;
|
|
16120
|
+
setCopied(true);
|
|
16121
|
+
timerRef.current = setTimeout(() => {
|
|
16122
|
+
setCopied(false);
|
|
16123
|
+
timerRef.current = null;
|
|
16124
|
+
}, 1e3);
|
|
16125
|
+
});
|
|
16126
|
+
}, [text, copied]);
|
|
16127
|
+
(0, import_react10.useEffect)(() => {
|
|
16128
|
+
return () => {
|
|
16129
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
16130
|
+
};
|
|
16131
|
+
}, []);
|
|
16132
|
+
return import_react10.default.createElement(
|
|
16133
|
+
"button",
|
|
16134
|
+
{
|
|
16135
|
+
type: "button",
|
|
16136
|
+
onClick: handleCopy,
|
|
16137
|
+
"aria-label": copied ? "Copied" : "Copy",
|
|
16138
|
+
style: {
|
|
16139
|
+
display: "inline-flex",
|
|
16140
|
+
alignItems: "center",
|
|
16141
|
+
gap: "6px",
|
|
16142
|
+
padding: "4px 8px",
|
|
16143
|
+
border: "none",
|
|
16144
|
+
borderRadius: "6px",
|
|
16145
|
+
background: "transparent",
|
|
16146
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
16147
|
+
cursor: "pointer",
|
|
16148
|
+
fontSize: "13px",
|
|
16149
|
+
lineHeight: "16px",
|
|
16150
|
+
whiteSpace: "nowrap",
|
|
16151
|
+
flexShrink: 0
|
|
16152
|
+
},
|
|
16153
|
+
onMouseEnter: (e) => {
|
|
16154
|
+
e.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover)";
|
|
16155
|
+
e.currentTarget.style.color = "var(--dsw-alias-label-primary)";
|
|
16156
|
+
},
|
|
16157
|
+
onMouseLeave: (e) => {
|
|
16158
|
+
e.currentTarget.style.background = "transparent";
|
|
16159
|
+
e.currentTarget.style.color = "var(--dsw-alias-label-secondary)";
|
|
16160
|
+
}
|
|
16161
|
+
},
|
|
16162
|
+
copied ? import_react10.default.createElement(import_dsh_client_ui_primitives3.IconCheckOutline16, { size: 16 }) : import_react10.default.createElement(import_dsh_client_ui_primitives3.IconCopyOutline16, { size: 16 }),
|
|
16163
|
+
copied ? "Copied" : "Copy"
|
|
16164
|
+
);
|
|
16165
|
+
}
|
|
16166
|
+
|
|
16167
|
+
// src/ui/client/pentester/FindingsView.tsx
|
|
16105
16168
|
var SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
|
|
16106
16169
|
var SEVERITY_LABELS = {
|
|
16107
16170
|
critical: "Critical",
|
|
@@ -16117,176 +16180,594 @@ var SEVERITY_COLORS = {
|
|
|
16117
16180
|
low: "#3b82f6",
|
|
16118
16181
|
info: "#6b7280"
|
|
16119
16182
|
};
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
{ style: { marginBottom: "4px" } },
|
|
16125
|
-
import_react10.default.createElement(
|
|
16126
|
-
"div",
|
|
16127
|
-
{
|
|
16128
|
-
onClick: () => setOpen(!open),
|
|
16129
|
-
style: {
|
|
16130
|
-
display: "flex",
|
|
16131
|
-
alignItems: "center",
|
|
16132
|
-
gap: "6px",
|
|
16133
|
-
padding: "6px 8px",
|
|
16134
|
-
cursor: "pointer",
|
|
16135
|
-
borderRadius: "4px",
|
|
16136
|
-
fontSize: "13px",
|
|
16137
|
-
fontWeight: 600,
|
|
16138
|
-
color: "var(--dsw-fg)",
|
|
16139
|
-
userSelect: "none"
|
|
16140
|
-
}
|
|
16141
|
-
},
|
|
16142
|
-
import_react10.default.createElement("span", {
|
|
16143
|
-
style: { fontSize: "12px", transition: "transform 0.15s", transform: open ? "rotate(90deg)" : "rotate(0deg)" }
|
|
16144
|
-
}, "\u25B6"),
|
|
16145
|
-
import_react10.default.createElement("span", null, props.title)
|
|
16146
|
-
),
|
|
16147
|
-
open && import_react10.default.createElement("div", { style: { paddingLeft: "20px" } }, props.children)
|
|
16148
|
-
);
|
|
16149
|
-
}
|
|
16183
|
+
var FILTER_TABS = [
|
|
16184
|
+
{ id: "all", label: "All" },
|
|
16185
|
+
...SEVERITY_ORDER.map((s) => ({ id: s, label: SEVERITY_LABELS[s] }))
|
|
16186
|
+
];
|
|
16150
16187
|
function FindingsView(props) {
|
|
16151
|
-
const { snapshot, command, sessionId } = props;
|
|
16152
|
-
const [selectedFinding, setSelectedFinding] = (0, import_react10.useState)(null);
|
|
16153
|
-
const [detailContent, setDetailContent] = (0, import_react10.useState)(null);
|
|
16154
|
-
const [detailLoading, setDetailLoading] = (0, import_react10.useState)(false);
|
|
16188
|
+
const { snapshot, command, sessionId, onNavigate } = props;
|
|
16155
16189
|
const findings = snapshot?.findings ?? [];
|
|
16156
|
-
const
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16190
|
+
const [selectedId, setSelectedId] = (0, import_react11.useState)(null);
|
|
16191
|
+
const [detailContent, setDetailContent] = (0, import_react11.useState)(null);
|
|
16192
|
+
const [detailLoading, setDetailLoading] = (0, import_react11.useState)(false);
|
|
16193
|
+
const [detailError, setDetailError] = (0, import_react11.useState)(false);
|
|
16194
|
+
const [filter, setFilter] = (0, import_react11.useState)("all");
|
|
16195
|
+
const [search, setSearch] = (0, import_react11.useState)("");
|
|
16196
|
+
const [focusDone, setFocusDone] = (0, import_react11.useState)(false);
|
|
16197
|
+
const loadSeqRef = (0, import_react11.useRef)(0);
|
|
16198
|
+
const severityCounts = (0, import_react11.useMemo)(() => {
|
|
16199
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
|
|
16200
|
+
for (const f of findings) counts[f.severity]++;
|
|
16201
|
+
return counts;
|
|
16166
16202
|
}, [findings]);
|
|
16167
|
-
const
|
|
16168
|
-
|
|
16203
|
+
const filtered = (0, import_react11.useMemo)(() => {
|
|
16204
|
+
let list = [...findings];
|
|
16205
|
+
if (filter !== "all") list = list.filter((f) => f.severity === filter);
|
|
16206
|
+
if (search.trim() !== "") {
|
|
16207
|
+
const q = search.toLowerCase();
|
|
16208
|
+
list = list.filter(
|
|
16209
|
+
(f) => f.title.toLowerCase().includes(q) || (f.affectedAsset?.toLowerCase().includes(q) ?? false) || f.sourceStage.toLowerCase().includes(q) || f.sourceDelegationId.toLowerCase().includes(q)
|
|
16210
|
+
);
|
|
16211
|
+
}
|
|
16212
|
+
const orderMap = new Map(SEVERITY_ORDER.map((s, i) => [s, i]));
|
|
16213
|
+
list.sort((a, b) => {
|
|
16214
|
+
const oa = orderMap.get(a.severity) ?? 99;
|
|
16215
|
+
const ob = orderMap.get(b.severity) ?? 99;
|
|
16216
|
+
if (oa !== ob) return oa - ob;
|
|
16217
|
+
return 0;
|
|
16218
|
+
});
|
|
16219
|
+
return list;
|
|
16220
|
+
}, [findings, filter, search]);
|
|
16221
|
+
const selectedFinding = (0, import_react11.useMemo)(
|
|
16222
|
+
() => selectedId !== null ? findings.find((f) => f.id === selectedId) ?? null : null,
|
|
16223
|
+
[findings, selectedId]
|
|
16224
|
+
);
|
|
16225
|
+
(0, import_react11.useEffect)(() => {
|
|
16226
|
+
if (props.focusFinding !== void 0 && !focusDone) {
|
|
16227
|
+
const match = findings.find((f) => f.id === props.focusFinding);
|
|
16228
|
+
if (match !== void 0) {
|
|
16229
|
+
setSelectedId(match.id);
|
|
16230
|
+
setFilter("all");
|
|
16231
|
+
setSearch("");
|
|
16232
|
+
setFocusDone(true);
|
|
16233
|
+
}
|
|
16234
|
+
}
|
|
16235
|
+
}, [props.focusFinding, focusDone, findings]);
|
|
16236
|
+
(0, import_react11.useEffect)(() => {
|
|
16237
|
+
setFocusDone(false);
|
|
16238
|
+
}, [props.focusFinding]);
|
|
16239
|
+
const loadDetail = (0, import_react11.useCallback)(async (finding) => {
|
|
16240
|
+
setSelectedId(finding.id);
|
|
16169
16241
|
setDetailContent(null);
|
|
16170
16242
|
setDetailLoading(true);
|
|
16243
|
+
setDetailError(false);
|
|
16244
|
+
const seq = ++loadSeqRef.current;
|
|
16171
16245
|
try {
|
|
16172
16246
|
const result = await command({
|
|
16173
16247
|
kind: "readFinding",
|
|
16174
16248
|
detailFile: finding.detailFile,
|
|
16175
16249
|
sessionId
|
|
16176
16250
|
});
|
|
16251
|
+
if (seq !== loadSeqRef.current) return;
|
|
16177
16252
|
if (result.ok) {
|
|
16178
16253
|
const fileResult = result.value;
|
|
16179
16254
|
setDetailContent(fileResult.content ?? "");
|
|
16255
|
+
setDetailError(false);
|
|
16180
16256
|
} else {
|
|
16181
|
-
setDetailContent(
|
|
16257
|
+
setDetailContent(null);
|
|
16258
|
+
setDetailError(true);
|
|
16182
16259
|
}
|
|
16183
16260
|
} catch {
|
|
16184
|
-
|
|
16261
|
+
if (seq !== loadSeqRef.current) return;
|
|
16262
|
+
setDetailContent(null);
|
|
16263
|
+
setDetailError(true);
|
|
16185
16264
|
} finally {
|
|
16186
|
-
setDetailLoading(false);
|
|
16265
|
+
if (seq === loadSeqRef.current) setDetailLoading(false);
|
|
16187
16266
|
}
|
|
16188
16267
|
}, [command, sessionId]);
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
|
|
16198
|
-
|
|
16199
|
-
|
|
16200
|
-
|
|
16201
|
-
|
|
16202
|
-
|
|
16268
|
+
return import_react11.default.createElement(
|
|
16269
|
+
"div",
|
|
16270
|
+
{
|
|
16271
|
+
style: {
|
|
16272
|
+
display: "flex",
|
|
16273
|
+
flexDirection: "column",
|
|
16274
|
+
height: "100%",
|
|
16275
|
+
minHeight: 0,
|
|
16276
|
+
overflow: "hidden"
|
|
16277
|
+
}
|
|
16278
|
+
},
|
|
16279
|
+
// ── Top: severity summary strip ──────────────────────────────────────
|
|
16280
|
+
import_react11.default.createElement(SeveritySummary, {
|
|
16281
|
+
total: findings.length,
|
|
16282
|
+
counts: severityCounts,
|
|
16283
|
+
activeFilter: filter,
|
|
16284
|
+
onFilter: setFilter
|
|
16285
|
+
}),
|
|
16286
|
+
// ── Bottom: split view ───────────────────────────────────────────────
|
|
16287
|
+
import_react11.default.createElement(
|
|
16288
|
+
"div",
|
|
16289
|
+
{
|
|
16290
|
+
style: {
|
|
16291
|
+
flex: 1,
|
|
16292
|
+
minHeight: 0,
|
|
16293
|
+
display: "flex",
|
|
16294
|
+
overflow: "hidden"
|
|
16295
|
+
}
|
|
16296
|
+
},
|
|
16297
|
+
// ── Left: Navigator ───────────────────────────────────────────────
|
|
16298
|
+
import_react11.default.createElement(
|
|
16203
16299
|
"div",
|
|
16204
16300
|
{
|
|
16205
|
-
key: finding.id,
|
|
16206
16301
|
style: {
|
|
16302
|
+
flex: "0 0 340px",
|
|
16303
|
+
minWidth: "280px",
|
|
16304
|
+
maxWidth: "380px",
|
|
16305
|
+
minHeight: 0,
|
|
16207
16306
|
display: "flex",
|
|
16307
|
+
flexDirection: "column",
|
|
16308
|
+
overflow: "hidden",
|
|
16309
|
+
borderRight: "1px solid var(--dsw-alias-border-l2)"
|
|
16310
|
+
}
|
|
16311
|
+
},
|
|
16312
|
+
// Search + filter (fixed header)
|
|
16313
|
+
import_react11.default.createElement(
|
|
16314
|
+
"div",
|
|
16315
|
+
{
|
|
16316
|
+
style: {
|
|
16317
|
+
flex: "none",
|
|
16318
|
+
padding: "8px 12px 4px"
|
|
16319
|
+
}
|
|
16320
|
+
},
|
|
16321
|
+
import_react11.default.createElement("input", {
|
|
16322
|
+
type: "text",
|
|
16323
|
+
placeholder: "Search findings...",
|
|
16324
|
+
value: search,
|
|
16325
|
+
onChange: (e) => setSearch(e.target.value),
|
|
16326
|
+
style: {
|
|
16327
|
+
width: "100%",
|
|
16328
|
+
boxSizing: "border-box",
|
|
16329
|
+
padding: "6px 10px",
|
|
16330
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
16331
|
+
borderRadius: "6px",
|
|
16332
|
+
background: "var(--dsw-alias-bg-base)",
|
|
16333
|
+
color: "var(--dsw-alias-label-primary)",
|
|
16334
|
+
fontSize: "13px",
|
|
16335
|
+
outline: "none",
|
|
16336
|
+
marginBottom: "4px"
|
|
16337
|
+
}
|
|
16338
|
+
}),
|
|
16339
|
+
import_react11.default.createElement(PentesterTabBar, {
|
|
16340
|
+
items: FILTER_TABS,
|
|
16341
|
+
active: filter,
|
|
16342
|
+
onSelect: (id) => setFilter(id),
|
|
16343
|
+
variant: "compact"
|
|
16344
|
+
})
|
|
16345
|
+
),
|
|
16346
|
+
// FindingList (scrollable)
|
|
16347
|
+
import_react11.default.createElement(
|
|
16348
|
+
"div",
|
|
16349
|
+
{
|
|
16350
|
+
style: {
|
|
16351
|
+
flex: 1,
|
|
16352
|
+
minHeight: 0,
|
|
16353
|
+
overflowY: "auto",
|
|
16354
|
+
overflowX: "hidden",
|
|
16355
|
+
overscrollBehaviorY: "contain",
|
|
16356
|
+
scrollbarGutter: "stable"
|
|
16357
|
+
}
|
|
16358
|
+
},
|
|
16359
|
+
filtered.length === 0 ? import_react11.default.createElement("div", {
|
|
16360
|
+
style: {
|
|
16361
|
+
padding: "24px 12px",
|
|
16362
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
16363
|
+
fontSize: "13px",
|
|
16364
|
+
textAlign: "center"
|
|
16365
|
+
}
|
|
16366
|
+
}, findings.length === 0 ? "No findings yet" : "No matching findings") : filtered.map(
|
|
16367
|
+
(finding) => import_react11.default.createElement(FindingRow, {
|
|
16368
|
+
key: finding.id,
|
|
16369
|
+
finding,
|
|
16370
|
+
isSelected: finding.id === selectedId,
|
|
16371
|
+
onClick: () => loadDetail(finding)
|
|
16372
|
+
})
|
|
16373
|
+
)
|
|
16374
|
+
)
|
|
16375
|
+
),
|
|
16376
|
+
// ── Right: Detail ──────────────────────────────────────────────────
|
|
16377
|
+
import_react11.default.createElement(
|
|
16378
|
+
"div",
|
|
16379
|
+
{
|
|
16380
|
+
style: {
|
|
16381
|
+
flex: 1,
|
|
16382
|
+
minWidth: 0,
|
|
16383
|
+
minHeight: 0,
|
|
16384
|
+
display: "flex",
|
|
16385
|
+
flexDirection: "column",
|
|
16386
|
+
overflow: "hidden"
|
|
16387
|
+
}
|
|
16388
|
+
},
|
|
16389
|
+
selectedFinding === null ? import_react11.default.createElement(
|
|
16390
|
+
"div",
|
|
16391
|
+
{
|
|
16392
|
+
style: {
|
|
16393
|
+
flex: 1,
|
|
16394
|
+
display: "flex",
|
|
16395
|
+
alignItems: "center",
|
|
16396
|
+
justifyContent: "center",
|
|
16397
|
+
flexDirection: "column",
|
|
16398
|
+
gap: "8px",
|
|
16399
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
16400
|
+
fontSize: "13px"
|
|
16401
|
+
}
|
|
16402
|
+
},
|
|
16403
|
+
findings.length === 0 ? import_react11.default.createElement(
|
|
16404
|
+
import_react11.default.Fragment,
|
|
16405
|
+
null,
|
|
16406
|
+
import_react11.default.createElement("div", { style: { fontWeight: 500, color: "var(--dsw-alias-label-primary)" } }, "No findings yet"),
|
|
16407
|
+
import_react11.default.createElement("div", null, "Validated findings will appear here as the assessment progresses.")
|
|
16408
|
+
) : "Select a finding to inspect"
|
|
16409
|
+
) : import_react11.default.createElement(FindingDetail, {
|
|
16410
|
+
finding: selectedFinding,
|
|
16411
|
+
content: detailContent,
|
|
16412
|
+
loading: detailLoading,
|
|
16413
|
+
error: detailError,
|
|
16414
|
+
onNavigate
|
|
16415
|
+
})
|
|
16416
|
+
)
|
|
16417
|
+
)
|
|
16418
|
+
);
|
|
16419
|
+
}
|
|
16420
|
+
function SeveritySummary(props) {
|
|
16421
|
+
const { total, counts, activeFilter, onFilter } = props;
|
|
16422
|
+
const items = [
|
|
16423
|
+
{ key: "all", label: "Total", count: total },
|
|
16424
|
+
...SEVERITY_ORDER.map((s) => ({
|
|
16425
|
+
key: s,
|
|
16426
|
+
label: SEVERITY_LABELS[s],
|
|
16427
|
+
count: counts[s],
|
|
16428
|
+
color: SEVERITY_COLORS[s]
|
|
16429
|
+
}))
|
|
16430
|
+
];
|
|
16431
|
+
return import_react11.default.createElement(
|
|
16432
|
+
"div",
|
|
16433
|
+
{
|
|
16434
|
+
style: {
|
|
16435
|
+
flex: "none",
|
|
16436
|
+
display: "flex",
|
|
16437
|
+
alignItems: "center",
|
|
16438
|
+
gap: "4px",
|
|
16439
|
+
padding: "8px 12px",
|
|
16440
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
16441
|
+
flexWrap: "wrap",
|
|
16442
|
+
fontSize: "13px",
|
|
16443
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
16444
|
+
}
|
|
16445
|
+
},
|
|
16446
|
+
...items.map((item) => {
|
|
16447
|
+
const isActive = activeFilter === item.key;
|
|
16448
|
+
return import_react11.default.createElement(
|
|
16449
|
+
"button",
|
|
16450
|
+
{
|
|
16451
|
+
key: item.key,
|
|
16452
|
+
type: "button",
|
|
16453
|
+
onClick: () => onFilter(item.key),
|
|
16454
|
+
style: {
|
|
16455
|
+
display: "inline-flex",
|
|
16208
16456
|
alignItems: "center",
|
|
16209
|
-
gap: "
|
|
16210
|
-
padding: "
|
|
16457
|
+
gap: "5px",
|
|
16458
|
+
padding: "3px 10px",
|
|
16459
|
+
borderRadius: "12px",
|
|
16460
|
+
border: "none",
|
|
16461
|
+
background: isActive ? "var(--dsw-alias-interactive-bg-hover)" : "transparent",
|
|
16462
|
+
color: isActive ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-secondary)",
|
|
16211
16463
|
cursor: "pointer",
|
|
16212
|
-
borderRadius: "4px",
|
|
16213
16464
|
fontSize: "13px",
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
},
|
|
16218
|
-
onClick: () => openDetail(finding)
|
|
16465
|
+
fontWeight: isActive ? 500 : 400,
|
|
16466
|
+
whiteSpace: "nowrap"
|
|
16467
|
+
}
|
|
16219
16468
|
},
|
|
16220
|
-
|
|
16469
|
+
item.color !== void 0 && import_react11.default.createElement("span", {
|
|
16221
16470
|
style: {
|
|
16222
16471
|
width: "8px",
|
|
16223
16472
|
height: "8px",
|
|
16224
16473
|
borderRadius: "50%",
|
|
16225
|
-
background:
|
|
16474
|
+
background: item.color,
|
|
16226
16475
|
flexShrink: 0
|
|
16227
16476
|
}
|
|
16228
16477
|
}),
|
|
16229
|
-
|
|
16230
|
-
|
|
16231
|
-
style: {
|
|
16232
|
-
},
|
|
16233
|
-
)
|
|
16234
|
-
)
|
|
16235
|
-
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
const modalContent = selectedFinding !== null ? import_react10.default.createElement(
|
|
16243
|
-
import_dsh_client_ui_primitives3.Modal,
|
|
16478
|
+
import_react11.default.createElement("span", null, item.label),
|
|
16479
|
+
import_react11.default.createElement("span", {
|
|
16480
|
+
style: { fontWeight: 600, color: isActive ? "var(--dsw-alias-label-primary)" : "var(--dsw-alias-label-tertiary)" }
|
|
16481
|
+
}, String(item.count))
|
|
16482
|
+
);
|
|
16483
|
+
})
|
|
16484
|
+
);
|
|
16485
|
+
}
|
|
16486
|
+
function FindingRow(props) {
|
|
16487
|
+
const { finding, isSelected, onClick } = props;
|
|
16488
|
+
const color = SEVERITY_COLORS[finding.severity];
|
|
16489
|
+
return import_react11.default.createElement(
|
|
16490
|
+
"div",
|
|
16244
16491
|
{
|
|
16245
|
-
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16492
|
+
role: "button",
|
|
16493
|
+
tabIndex: 0,
|
|
16494
|
+
onClick,
|
|
16495
|
+
onKeyDown: (e) => {
|
|
16496
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
16497
|
+
e.preventDefault();
|
|
16498
|
+
onClick();
|
|
16499
|
+
}
|
|
16500
|
+
},
|
|
16501
|
+
style: {
|
|
16502
|
+
display: "flex",
|
|
16503
|
+
flexDirection: "column",
|
|
16504
|
+
gap: "2px",
|
|
16505
|
+
padding: "8px 12px",
|
|
16506
|
+
cursor: "pointer",
|
|
16507
|
+
borderLeft: `3px solid ${isSelected ? color : "transparent"}`,
|
|
16508
|
+
background: isSelected ? "var(--dsw-alias-state-business-primary)" : "transparent",
|
|
16509
|
+
color: isSelected ? "var(--dsw-alias-state-business-primary-fg, #fff)" : "var(--dsw-alias-label-primary)",
|
|
16510
|
+
fontSize: "13px",
|
|
16511
|
+
lineHeight: "18px",
|
|
16512
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
16513
|
+
transition: "background 0.1s"
|
|
16514
|
+
},
|
|
16515
|
+
onMouseEnter: (e) => {
|
|
16516
|
+
if (!isSelected) e.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover)";
|
|
16517
|
+
},
|
|
16518
|
+
onMouseLeave: (e) => {
|
|
16519
|
+
if (!isSelected) e.currentTarget.style.background = "transparent";
|
|
16520
|
+
}
|
|
16249
16521
|
},
|
|
16250
|
-
|
|
16522
|
+
// Row 1: title + severity
|
|
16523
|
+
import_react11.default.createElement(
|
|
16251
16524
|
"div",
|
|
16252
|
-
{
|
|
16253
|
-
import_react10.default.createElement("div", {
|
|
16525
|
+
{
|
|
16254
16526
|
style: {
|
|
16255
|
-
display: "
|
|
16256
|
-
|
|
16257
|
-
|
|
16258
|
-
|
|
16259
|
-
|
|
16260
|
-
|
|
16527
|
+
display: "flex",
|
|
16528
|
+
alignItems: "center",
|
|
16529
|
+
gap: "8px",
|
|
16530
|
+
minWidth: 0
|
|
16531
|
+
}
|
|
16532
|
+
},
|
|
16533
|
+
import_react11.default.createElement("span", {
|
|
16534
|
+
style: {
|
|
16535
|
+
width: "7px",
|
|
16536
|
+
height: "7px",
|
|
16537
|
+
borderRadius: "50%",
|
|
16538
|
+
background: color,
|
|
16539
|
+
flexShrink: 0
|
|
16540
|
+
}
|
|
16541
|
+
}),
|
|
16542
|
+
import_react11.default.createElement("span", {
|
|
16543
|
+
style: {
|
|
16544
|
+
overflow: "hidden",
|
|
16545
|
+
textOverflow: "ellipsis",
|
|
16546
|
+
whiteSpace: "nowrap",
|
|
16547
|
+
fontWeight: 500,
|
|
16548
|
+
flex: 1,
|
|
16549
|
+
minWidth: 0
|
|
16550
|
+
}
|
|
16551
|
+
}, finding.title),
|
|
16552
|
+
import_react11.default.createElement("span", {
|
|
16553
|
+
style: {
|
|
16554
|
+
fontSize: "11px",
|
|
16261
16555
|
fontWeight: 600,
|
|
16262
|
-
|
|
16556
|
+
color: isSelected ? "rgba(255,255,255,0.75)" : color,
|
|
16557
|
+
flexShrink: 0
|
|
16263
16558
|
}
|
|
16264
|
-
}, SEVERITY_LABELS[
|
|
16265
|
-
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16559
|
+
}, SEVERITY_LABELS[finding.severity].toUpperCase())
|
|
16560
|
+
),
|
|
16561
|
+
// Row 2: affected asset (if exists)
|
|
16562
|
+
finding.affectedAsset !== void 0 && import_react11.default.createElement("div", {
|
|
16563
|
+
style: {
|
|
16564
|
+
fontSize: "12px",
|
|
16565
|
+
color: isSelected ? "rgba(255,255,255,0.6)" : "var(--dsw-alias-label-tertiary)",
|
|
16566
|
+
overflow: "hidden",
|
|
16567
|
+
textOverflow: "ellipsis",
|
|
16568
|
+
whiteSpace: "nowrap",
|
|
16569
|
+
marginLeft: "15px"
|
|
16570
|
+
}
|
|
16571
|
+
}, finding.affectedAsset),
|
|
16572
|
+
// Row 3: source stage + delegation
|
|
16573
|
+
import_react11.default.createElement("div", {
|
|
16574
|
+
style: {
|
|
16575
|
+
fontSize: "11px",
|
|
16576
|
+
color: isSelected ? "rgba(255,255,255,0.5)" : "var(--dsw-alias-label-tertiary)",
|
|
16577
|
+
marginLeft: "15px",
|
|
16578
|
+
overflow: "hidden",
|
|
16579
|
+
textOverflow: "ellipsis",
|
|
16580
|
+
whiteSpace: "nowrap"
|
|
16581
|
+
}
|
|
16582
|
+
}, `${finding.sourceStage} \xB7 ${finding.sourceDelegationId}`)
|
|
16583
|
+
);
|
|
16584
|
+
}
|
|
16585
|
+
function FindingDetail(props) {
|
|
16586
|
+
const { finding, content, loading, error: error51, onNavigate } = props;
|
|
16587
|
+
const color = SEVERITY_COLORS[finding.severity];
|
|
16588
|
+
return import_react11.default.createElement(
|
|
16278
16589
|
"div",
|
|
16279
|
-
{
|
|
16280
|
-
|
|
16281
|
-
|
|
16590
|
+
{
|
|
16591
|
+
style: {
|
|
16592
|
+
flex: 1,
|
|
16593
|
+
minHeight: 0,
|
|
16594
|
+
display: "flex",
|
|
16595
|
+
flexDirection: "column",
|
|
16596
|
+
overflow: "hidden"
|
|
16597
|
+
}
|
|
16598
|
+
},
|
|
16599
|
+
// ── Metadata header (fixed) ─────────────────────────────────────────
|
|
16600
|
+
import_react11.default.createElement(
|
|
16601
|
+
"div",
|
|
16602
|
+
{
|
|
16603
|
+
style: {
|
|
16604
|
+
flex: "none",
|
|
16605
|
+
padding: "12px 16px",
|
|
16606
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2)"
|
|
16607
|
+
}
|
|
16608
|
+
},
|
|
16609
|
+
// Title + severity + copy
|
|
16610
|
+
import_react11.default.createElement(
|
|
16611
|
+
"div",
|
|
16612
|
+
{
|
|
16613
|
+
style: {
|
|
16614
|
+
display: "flex",
|
|
16615
|
+
alignItems: "center",
|
|
16616
|
+
gap: "10px",
|
|
16617
|
+
marginBottom: "8px"
|
|
16618
|
+
}
|
|
16619
|
+
},
|
|
16620
|
+
import_react11.default.createElement("span", {
|
|
16621
|
+
style: {
|
|
16622
|
+
fontSize: "15px",
|
|
16623
|
+
fontWeight: 600,
|
|
16624
|
+
color: "var(--dsw-alias-label-primary)",
|
|
16625
|
+
overflow: "hidden",
|
|
16626
|
+
textOverflow: "ellipsis",
|
|
16627
|
+
whiteSpace: "nowrap",
|
|
16628
|
+
flex: 1,
|
|
16629
|
+
minWidth: 0
|
|
16630
|
+
}
|
|
16631
|
+
}, finding.title),
|
|
16632
|
+
content !== null && import_react11.default.createElement(CopyAction, { text: content }),
|
|
16633
|
+
import_react11.default.createElement("span", {
|
|
16634
|
+
style: {
|
|
16635
|
+
display: "inline-block",
|
|
16636
|
+
padding: "2px 8px",
|
|
16637
|
+
borderRadius: "10px",
|
|
16638
|
+
background: color,
|
|
16639
|
+
color: "#fff",
|
|
16640
|
+
fontSize: "11px",
|
|
16641
|
+
fontWeight: 600,
|
|
16642
|
+
flexShrink: 0
|
|
16643
|
+
}
|
|
16644
|
+
}, SEVERITY_LABELS[finding.severity].toUpperCase())
|
|
16645
|
+
),
|
|
16646
|
+
// Affected asset
|
|
16647
|
+
finding.affectedAsset !== void 0 && import_react11.default.createElement(
|
|
16648
|
+
"div",
|
|
16649
|
+
{
|
|
16650
|
+
style: {
|
|
16651
|
+
fontSize: "13px",
|
|
16652
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
16653
|
+
marginBottom: "6px",
|
|
16654
|
+
display: "flex",
|
|
16655
|
+
gap: "6px"
|
|
16656
|
+
}
|
|
16657
|
+
},
|
|
16658
|
+
import_react11.default.createElement("span", { style: { color: "var(--dsw-alias-label-tertiary)", flexShrink: 0 } }, "Affected asset"),
|
|
16659
|
+
import_react11.default.createElement("code", {
|
|
16660
|
+
style: {
|
|
16661
|
+
fontSize: "12px",
|
|
16662
|
+
background: "var(--dsw-alias-bg-subtle)",
|
|
16663
|
+
padding: "1px 6px",
|
|
16664
|
+
borderRadius: "3px"
|
|
16665
|
+
}
|
|
16666
|
+
}, finding.affectedAsset)
|
|
16667
|
+
),
|
|
16668
|
+
// Stage + Delegation metadata
|
|
16669
|
+
import_react11.default.createElement(
|
|
16670
|
+
"div",
|
|
16671
|
+
{
|
|
16672
|
+
style: {
|
|
16673
|
+
display: "flex",
|
|
16674
|
+
gap: "20px",
|
|
16675
|
+
fontSize: "12px",
|
|
16676
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
16677
|
+
}
|
|
16678
|
+
},
|
|
16679
|
+
import_react11.default.createElement(
|
|
16680
|
+
"div",
|
|
16681
|
+
null,
|
|
16682
|
+
import_react11.default.createElement("span", { style: { fontWeight: 500, color: "var(--dsw-alias-label-secondary)" } }, "Stage"),
|
|
16683
|
+
" ",
|
|
16684
|
+
import_react11.default.createElement("span", null, finding.sourceStage)
|
|
16685
|
+
),
|
|
16686
|
+
import_react11.default.createElement(
|
|
16687
|
+
"div",
|
|
16688
|
+
null,
|
|
16689
|
+
import_react11.default.createElement("span", { style: { fontWeight: 500, color: "var(--dsw-alias-label-secondary)" } }, "Delegation"),
|
|
16690
|
+
" ",
|
|
16691
|
+
import_react11.default.createElement("span", null, finding.sourceDelegationId)
|
|
16692
|
+
)
|
|
16693
|
+
)
|
|
16694
|
+
),
|
|
16695
|
+
// ── DetailBody (scrollable) ────────────────────────────────────────
|
|
16696
|
+
import_react11.default.createElement(
|
|
16697
|
+
"div",
|
|
16698
|
+
{
|
|
16699
|
+
style: {
|
|
16700
|
+
flex: 1,
|
|
16701
|
+
minHeight: 0,
|
|
16702
|
+
overflowY: "auto",
|
|
16703
|
+
overflowX: "auto",
|
|
16704
|
+
overscrollBehaviorY: "contain",
|
|
16705
|
+
scrollbarGutter: "stable",
|
|
16706
|
+
padding: "16px",
|
|
16707
|
+
fontSize: "13px",
|
|
16708
|
+
lineHeight: "1.6",
|
|
16709
|
+
color: "var(--dsw-alias-label-primary)"
|
|
16710
|
+
}
|
|
16711
|
+
},
|
|
16712
|
+
loading && import_react11.default.createElement("div", {
|
|
16713
|
+
style: { color: "var(--dsw-alias-label-tertiary)", padding: "16px 0" }
|
|
16714
|
+
}, "Loading finding..."),
|
|
16715
|
+
error51 && import_react11.default.createElement("div", {
|
|
16716
|
+
style: { color: "var(--dsw-status-error)", padding: "16px 0" }
|
|
16717
|
+
}, "Unable to load finding detail"),
|
|
16718
|
+
content !== null && import_react11.default.createElement(import_dsh_client_ui_primitives4.MarkdownText, { text: content })
|
|
16719
|
+
),
|
|
16720
|
+
// ── Footer actions (fixed) ──────────────────────────────────────────
|
|
16721
|
+
import_react11.default.createElement(
|
|
16722
|
+
"div",
|
|
16723
|
+
{
|
|
16724
|
+
style: {
|
|
16725
|
+
flex: "none",
|
|
16726
|
+
padding: "8px 16px",
|
|
16727
|
+
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
16728
|
+
display: "flex",
|
|
16729
|
+
gap: "8px"
|
|
16730
|
+
}
|
|
16731
|
+
},
|
|
16732
|
+
import_react11.default.createElement(ActionButton, {
|
|
16733
|
+
label: "View Stage",
|
|
16734
|
+
onClick: () => onNavigate("stages", { stage: finding.sourceStage })
|
|
16735
|
+
}),
|
|
16736
|
+
import_react11.default.createElement(ActionButton, {
|
|
16737
|
+
label: "View in Output",
|
|
16738
|
+
onClick: () => onNavigate("output", { output: `findings/${finding.detailFile}` })
|
|
16739
|
+
})
|
|
16740
|
+
)
|
|
16282
16741
|
);
|
|
16283
16742
|
}
|
|
16743
|
+
function ActionButton(props) {
|
|
16744
|
+
return import_react11.default.createElement("button", {
|
|
16745
|
+
type: "button",
|
|
16746
|
+
onClick: props.onClick,
|
|
16747
|
+
style: {
|
|
16748
|
+
padding: "4px 12px",
|
|
16749
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
16750
|
+
borderRadius: "4px",
|
|
16751
|
+
background: "transparent",
|
|
16752
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
16753
|
+
cursor: "pointer",
|
|
16754
|
+
fontSize: "12px",
|
|
16755
|
+
lineHeight: "20px"
|
|
16756
|
+
},
|
|
16757
|
+
onMouseEnter: (e) => {
|
|
16758
|
+
e.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover)";
|
|
16759
|
+
},
|
|
16760
|
+
onMouseLeave: (e) => {
|
|
16761
|
+
e.currentTarget.style.background = "transparent";
|
|
16762
|
+
}
|
|
16763
|
+
}, props.label);
|
|
16764
|
+
}
|
|
16284
16765
|
|
|
16285
16766
|
// src/ui/client/pentester/TraceView.tsx
|
|
16286
|
-
var
|
|
16767
|
+
var import_react16 = __toESM(require("react"), 1);
|
|
16287
16768
|
|
|
16288
16769
|
// src/ui/client/pentester/trace/TraceTimeline.tsx
|
|
16289
|
-
var
|
|
16770
|
+
var import_react15 = __toESM(require("react"), 1);
|
|
16290
16771
|
|
|
16291
16772
|
// src/ui/client/pentester/trace/types.ts
|
|
16292
16773
|
var STAGE_NODE_H = 72;
|
|
@@ -16690,8 +17171,8 @@ function buildScaledTraceLayout(baseLayout, scale) {
|
|
|
16690
17171
|
}
|
|
16691
17172
|
|
|
16692
17173
|
// src/ui/client/pentester/trace/TraceNode.tsx
|
|
16693
|
-
var
|
|
16694
|
-
var
|
|
17174
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
17175
|
+
var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
16695
17176
|
var CARD = {
|
|
16696
17177
|
position: "absolute",
|
|
16697
17178
|
borderRadius: "7px",
|
|
@@ -16704,10 +17185,10 @@ var CARD = {
|
|
|
16704
17185
|
cursor: "pointer",
|
|
16705
17186
|
pointerEvents: "auto"
|
|
16706
17187
|
};
|
|
16707
|
-
var StartNode = (0,
|
|
17188
|
+
var StartNode = (0, import_react12.forwardRef)(
|
|
16708
17189
|
function StartNode2(props, ref) {
|
|
16709
17190
|
const { section, x } = props;
|
|
16710
|
-
return
|
|
17191
|
+
return import_react12.default.createElement(
|
|
16711
17192
|
"div",
|
|
16712
17193
|
{
|
|
16713
17194
|
ref,
|
|
@@ -16735,7 +17216,7 @@ var StartNode = (0, import_react11.forwardRef)(
|
|
|
16735
17216
|
pointerEvents: "auto"
|
|
16736
17217
|
}
|
|
16737
17218
|
},
|
|
16738
|
-
|
|
17219
|
+
import_react12.default.createElement("div", {
|
|
16739
17220
|
style: {
|
|
16740
17221
|
width: "6px",
|
|
16741
17222
|
height: "6px",
|
|
@@ -16748,13 +17229,13 @@ var StartNode = (0, import_react11.forwardRef)(
|
|
|
16748
17229
|
);
|
|
16749
17230
|
}
|
|
16750
17231
|
);
|
|
16751
|
-
var StageNode = (0,
|
|
17232
|
+
var StageNode = (0, import_react12.forwardRef)(
|
|
16752
17233
|
function StageNode2(props, ref) {
|
|
16753
17234
|
const { section, x, onClick } = props;
|
|
16754
17235
|
const status = section.status;
|
|
16755
17236
|
const borderColor = status === "completed" ? "var(--dsw-status-done, #22c55e)" : status === "active" ? "var(--dsw-alias-state-business-primary)" : "var(--dsw-alias-border-l2)";
|
|
16756
17237
|
const dotState = status === "completed" ? "done" : status === "active" ? "ongoing" : "ongoing";
|
|
16757
|
-
return
|
|
17238
|
+
return import_react12.default.createElement(
|
|
16758
17239
|
"div",
|
|
16759
17240
|
{
|
|
16760
17241
|
ref,
|
|
@@ -16782,26 +17263,26 @@ var StageNode = (0, import_react11.forwardRef)(
|
|
|
16782
17263
|
gap: "10px"
|
|
16783
17264
|
}
|
|
16784
17265
|
},
|
|
16785
|
-
|
|
16786
|
-
|
|
17266
|
+
import_react12.default.createElement(import_dsh_client_ui_primitives5.StateDot, { state: dotState, size: 8 }),
|
|
17267
|
+
import_react12.default.createElement(
|
|
16787
17268
|
"div",
|
|
16788
17269
|
{ style: { minWidth: 0 } },
|
|
16789
|
-
|
|
17270
|
+
import_react12.default.createElement("div", {
|
|
16790
17271
|
style: { fontWeight: 600, color: "var(--dsw-alias-label-primary)", fontSize: "14px", lineHeight: "20px" }
|
|
16791
17272
|
}, section.label),
|
|
16792
|
-
|
|
17273
|
+
import_react12.default.createElement("div", {
|
|
16793
17274
|
style: { fontSize: "12px", color: "var(--dsw-alias-label-secondary)", marginTop: "2px" }
|
|
16794
17275
|
}, section.sublabel)
|
|
16795
17276
|
)
|
|
16796
17277
|
);
|
|
16797
17278
|
}
|
|
16798
17279
|
);
|
|
16799
|
-
var AgentNode = (0,
|
|
17280
|
+
var AgentNode = (0, import_react12.forwardRef)(
|
|
16800
17281
|
function AgentNode2(props, ref) {
|
|
16801
17282
|
const { branch, x, liveActivity, onClick } = props;
|
|
16802
17283
|
const dotState = branch.status === "failed" ? "error" : branch.status === "closed" ? "done" : liveActivity === "running" ? "ongoing" : liveActivity === "inactive" ? "done" : branch.status === "starting" ? "ongoing" : "done";
|
|
16803
17284
|
const borderColor = dotState === "error" ? "var(--dsw-status-error, #ef4444)" : dotState === "ongoing" ? "var(--dsw-alias-state-business-primary)" : "var(--dsw-alias-border-l2)";
|
|
16804
|
-
return
|
|
17285
|
+
return import_react12.default.createElement(
|
|
16805
17286
|
"div",
|
|
16806
17287
|
{
|
|
16807
17288
|
ref,
|
|
@@ -16829,14 +17310,14 @@ var AgentNode = (0, import_react11.forwardRef)(
|
|
|
16829
17310
|
gap: "8px"
|
|
16830
17311
|
}
|
|
16831
17312
|
},
|
|
16832
|
-
|
|
16833
|
-
|
|
17313
|
+
import_react12.default.createElement(import_dsh_client_ui_primitives5.StateDot, { state: dotState, size: 8 }),
|
|
17314
|
+
import_react12.default.createElement(
|
|
16834
17315
|
"div",
|
|
16835
17316
|
{ style: { minWidth: 0 } },
|
|
16836
|
-
|
|
17317
|
+
import_react12.default.createElement("div", {
|
|
16837
17318
|
style: { fontWeight: 600, color: "var(--dsw-alias-label-primary)", fontSize: "13px", lineHeight: "18px" }
|
|
16838
17319
|
}, branch.label),
|
|
16839
|
-
|
|
17320
|
+
import_react12.default.createElement("div", {
|
|
16840
17321
|
style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary)", marginTop: "2px" }
|
|
16841
17322
|
}, branch.status === "starting" ? "Agent starting" : branch.status === "active" ? "Agent active" : "Agent completed")
|
|
16842
17323
|
)
|
|
@@ -16851,11 +17332,11 @@ var DELIVERY_ICON_COLORS = {
|
|
|
16851
17332
|
finding: "var(--dsw-status-error, #ef4444)",
|
|
16852
17333
|
asset: "#3b82f6"
|
|
16853
17334
|
};
|
|
16854
|
-
var DeliveryNode = (0,
|
|
17335
|
+
var DeliveryNode = (0, import_react12.forwardRef)(
|
|
16855
17336
|
function DeliveryNode2(props, ref) {
|
|
16856
17337
|
const { group, x, y, onClick } = props;
|
|
16857
17338
|
const iconColor = DELIVERY_ICON_COLORS[group.kind] ?? "var(--dsw-alias-label-tertiary)";
|
|
16858
|
-
return
|
|
17339
|
+
return import_react12.default.createElement(
|
|
16859
17340
|
"div",
|
|
16860
17341
|
{
|
|
16861
17342
|
ref,
|
|
@@ -16887,7 +17368,7 @@ var DeliveryNode = (0, import_react11.forwardRef)(
|
|
|
16887
17368
|
textAlign: "center"
|
|
16888
17369
|
}
|
|
16889
17370
|
},
|
|
16890
|
-
|
|
17371
|
+
import_react12.default.createElement("div", {
|
|
16891
17372
|
style: {
|
|
16892
17373
|
width: "8px",
|
|
16893
17374
|
height: "8px",
|
|
@@ -16896,10 +17377,10 @@ var DeliveryNode = (0, import_react11.forwardRef)(
|
|
|
16896
17377
|
flexShrink: 0
|
|
16897
17378
|
}
|
|
16898
17379
|
}),
|
|
16899
|
-
|
|
17380
|
+
import_react12.default.createElement("div", {
|
|
16900
17381
|
style: { fontWeight: 600, color: "var(--dsw-alias-label-primary)", fontSize: "12px", lineHeight: "16px" }
|
|
16901
17382
|
}, group.label),
|
|
16902
|
-
|
|
17383
|
+
import_react12.default.createElement("div", {
|
|
16903
17384
|
style: { fontSize: "10px", color: "var(--dsw-alias-label-tertiary)" }
|
|
16904
17385
|
}, `${group.count} ${group.count === 1 ? "file" : "files"}`)
|
|
16905
17386
|
);
|
|
@@ -16907,7 +17388,7 @@ var DeliveryNode = (0, import_react11.forwardRef)(
|
|
|
16907
17388
|
);
|
|
16908
17389
|
|
|
16909
17390
|
// src/ui/client/pentester/trace/TraceConnectors.tsx
|
|
16910
|
-
var
|
|
17391
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
16911
17392
|
function roundedOrthogonal(sx, sy, tx, ty, r = 6) {
|
|
16912
17393
|
if (Math.abs(sx - tx) < 2) {
|
|
16913
17394
|
return `M ${sx} ${sy} L ${tx} ${ty}`;
|
|
@@ -16932,7 +17413,7 @@ function branchJunction(cx, sy, targets) {
|
|
|
16932
17413
|
}
|
|
16933
17414
|
function TraceConnectors(props) {
|
|
16934
17415
|
const { layout } = props;
|
|
16935
|
-
const paths = (0,
|
|
17416
|
+
const paths = (0, import_react13.useMemo)(() => {
|
|
16936
17417
|
const result = [];
|
|
16937
17418
|
const cx = layout.spineX;
|
|
16938
17419
|
const solid = { stroke: "var(--dsw-alias-border-l2)", strokeWidth: 1.25 };
|
|
@@ -17013,7 +17494,7 @@ function TraceConnectors(props) {
|
|
|
17013
17494
|
}
|
|
17014
17495
|
return result;
|
|
17015
17496
|
}, [layout]);
|
|
17016
|
-
return
|
|
17497
|
+
return import_react13.default.createElement(
|
|
17017
17498
|
"svg",
|
|
17018
17499
|
{
|
|
17019
17500
|
width: layout.worldHalfWidth * 2,
|
|
@@ -17026,7 +17507,7 @@ function TraceConnectors(props) {
|
|
|
17026
17507
|
}
|
|
17027
17508
|
},
|
|
17028
17509
|
...paths.map(
|
|
17029
|
-
(p, i) =>
|
|
17510
|
+
(p, i) => import_react13.default.createElement("path", {
|
|
17030
17511
|
key: i,
|
|
17031
17512
|
d: p.d,
|
|
17032
17513
|
fill: "none",
|
|
@@ -17041,7 +17522,7 @@ function TraceConnectors(props) {
|
|
|
17041
17522
|
}
|
|
17042
17523
|
|
|
17043
17524
|
// src/ui/client/pentester/trace/TraceControls.tsx
|
|
17044
|
-
var
|
|
17525
|
+
var import_react14 = __toESM(require("react"), 1);
|
|
17045
17526
|
var BTN = {
|
|
17046
17527
|
height: "32px",
|
|
17047
17528
|
display: "flex",
|
|
@@ -17060,33 +17541,33 @@ var BTN = {
|
|
|
17060
17541
|
function TraceControls(props) {
|
|
17061
17542
|
const { scale, onZoomIn, onZoomOut, onReset, onFit } = props;
|
|
17062
17543
|
const pct = Math.round(scale * 100);
|
|
17063
|
-
return
|
|
17544
|
+
return import_react14.default.createElement(
|
|
17064
17545
|
"div",
|
|
17065
17546
|
{
|
|
17066
17547
|
style: { display: "flex", alignItems: "center", gap: "4px" }
|
|
17067
17548
|
},
|
|
17068
|
-
|
|
17549
|
+
import_react14.default.createElement("button", {
|
|
17069
17550
|
type: "button",
|
|
17070
17551
|
"aria-label": "Zoom out",
|
|
17071
17552
|
title: "Zoom out",
|
|
17072
17553
|
onClick: onZoomOut,
|
|
17073
17554
|
style: { ...BTN, width: "32px", padding: 0 }
|
|
17074
17555
|
}, "\u2212"),
|
|
17075
|
-
|
|
17556
|
+
import_react14.default.createElement("button", {
|
|
17076
17557
|
type: "button",
|
|
17077
17558
|
"aria-label": "Reset zoom",
|
|
17078
17559
|
title: "Reset to 100%",
|
|
17079
17560
|
onClick: onReset,
|
|
17080
17561
|
style: { ...BTN, fontWeight: 500, fontSize: "11px", color: "var(--dsw-alias-label-primary)" }
|
|
17081
17562
|
}, `${pct}%`),
|
|
17082
|
-
|
|
17563
|
+
import_react14.default.createElement("button", {
|
|
17083
17564
|
type: "button",
|
|
17084
17565
|
"aria-label": "Zoom in",
|
|
17085
17566
|
title: "Zoom in",
|
|
17086
17567
|
onClick: onZoomIn,
|
|
17087
17568
|
style: { ...BTN, width: "32px", padding: 0 }
|
|
17088
17569
|
}, "+"),
|
|
17089
|
-
|
|
17570
|
+
import_react14.default.createElement("button", {
|
|
17090
17571
|
type: "button",
|
|
17091
17572
|
"aria-label": "Fit to width",
|
|
17092
17573
|
title: "Fit topology width",
|
|
@@ -17115,12 +17596,12 @@ function checkSpineInvariant(graphEl, scale) {
|
|
|
17115
17596
|
}
|
|
17116
17597
|
function TraceTimeline(props) {
|
|
17117
17598
|
const { snapshot, liveActivity, onNavigate, onOpenSession } = props;
|
|
17118
|
-
const baseLayout = (0,
|
|
17119
|
-
const [scale, setScale] = (0,
|
|
17120
|
-
const graphRef = (0,
|
|
17121
|
-
const graphVpRef = (0,
|
|
17122
|
-
const autoFitDoneRef = (0,
|
|
17123
|
-
const scaledLayout = (0,
|
|
17599
|
+
const baseLayout = (0, import_react15.useMemo)(() => buildTraceLayout(snapshot), [snapshot]);
|
|
17600
|
+
const [scale, setScale] = (0, import_react15.useState)(DEFAULT_SCALE);
|
|
17601
|
+
const graphRef = (0, import_react15.useRef)(null);
|
|
17602
|
+
const graphVpRef = (0, import_react15.useRef)(null);
|
|
17603
|
+
const autoFitDoneRef = (0, import_react15.useRef)(false);
|
|
17604
|
+
const scaledLayout = (0, import_react15.useMemo)(
|
|
17124
17605
|
() => buildScaledTraceLayout(baseLayout, scale),
|
|
17125
17606
|
[baseLayout, scale]
|
|
17126
17607
|
);
|
|
@@ -17130,7 +17611,7 @@ function TraceTimeline(props) {
|
|
|
17130
17611
|
const spineX = scaledLayout.spineX;
|
|
17131
17612
|
const worldW = worldHalfWidth * 2;
|
|
17132
17613
|
const worldH = scaledLayout.totalHeight;
|
|
17133
|
-
const doAutoFit = (0,
|
|
17614
|
+
const doAutoFit = (0, import_react15.useCallback)(() => {
|
|
17134
17615
|
const vp = graphVpRef.current;
|
|
17135
17616
|
if (vp === null) return DEFAULT_SCALE;
|
|
17136
17617
|
const availableHalf = vp.clientWidth / 2 - GRAPH_PADDING;
|
|
@@ -17138,13 +17619,13 @@ function TraceTimeline(props) {
|
|
|
17138
17619
|
const fitScale = availableHalf / requiredHalf;
|
|
17139
17620
|
return Math.min(DEFAULT_SCALE, Math.max(MIN_SCALE, fitScale));
|
|
17140
17621
|
}, [baseLayout.worldHalfWidth]);
|
|
17141
|
-
(0,
|
|
17622
|
+
(0, import_react15.useEffect)(() => {
|
|
17142
17623
|
if (autoFitDoneRef.current) return;
|
|
17143
17624
|
const fitScale = doAutoFit();
|
|
17144
17625
|
if (fitScale !== DEFAULT_SCALE) setScale(fitScale);
|
|
17145
17626
|
autoFitDoneRef.current = true;
|
|
17146
17627
|
}, [doAutoFit]);
|
|
17147
|
-
const zoomTo = (0,
|
|
17628
|
+
const zoomTo = (0, import_react15.useCallback)((newScale) => {
|
|
17148
17629
|
const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, newScale));
|
|
17149
17630
|
const owner = getScrollOwner();
|
|
17150
17631
|
const oldScale = scale;
|
|
@@ -17157,26 +17638,26 @@ function TraceTimeline(props) {
|
|
|
17157
17638
|
owner.scrollTop = Math.max(0, nextScrollTop);
|
|
17158
17639
|
});
|
|
17159
17640
|
}, [scale]);
|
|
17160
|
-
const zoomIn = (0,
|
|
17161
|
-
const zoomOut = (0,
|
|
17162
|
-
const resetZoom = (0,
|
|
17163
|
-
const fitWidth = (0,
|
|
17164
|
-
const handleWheel = (0,
|
|
17641
|
+
const zoomIn = (0, import_react15.useCallback)(() => zoomTo(scale * 1.15), [zoomTo, scale]);
|
|
17642
|
+
const zoomOut = (0, import_react15.useCallback)(() => zoomTo(scale / 1.15), [zoomTo, scale]);
|
|
17643
|
+
const resetZoom = (0, import_react15.useCallback)(() => zoomTo(DEFAULT_SCALE), [zoomTo]);
|
|
17644
|
+
const fitWidth = (0, import_react15.useCallback)(() => zoomTo(doAutoFit()), [zoomTo, doAutoFit]);
|
|
17645
|
+
const handleWheel = (0, import_react15.useCallback)((e) => {
|
|
17165
17646
|
if (!e.ctrlKey && !e.metaKey) return;
|
|
17166
17647
|
e.preventDefault();
|
|
17167
17648
|
const factor = e.deltaY < 0 ? 1.12 : 1 / 1.12;
|
|
17168
17649
|
zoomTo(scale * factor);
|
|
17169
17650
|
}, [zoomTo, scale]);
|
|
17170
|
-
(0,
|
|
17651
|
+
(0, import_react15.useEffect)(() => {
|
|
17171
17652
|
checkSpineInvariant(graphRef.current, scale);
|
|
17172
17653
|
}, [scale, adjustedSections]);
|
|
17173
|
-
const handleStageClick = (0,
|
|
17654
|
+
const handleStageClick = (0, import_react15.useCallback)((stageId) => {
|
|
17174
17655
|
onNavigate("stages", { stage: stageId });
|
|
17175
17656
|
}, [onNavigate]);
|
|
17176
|
-
const handleAgentClick = (0,
|
|
17657
|
+
const handleAgentClick = (0, import_react15.useCallback)((sessionId) => {
|
|
17177
17658
|
if (sessionId !== void 0) onOpenSession(sessionId);
|
|
17178
17659
|
}, [onOpenSession]);
|
|
17179
|
-
const handleDeliveryClick = (0,
|
|
17660
|
+
const handleDeliveryClick = (0, import_react15.useCallback)((group) => {
|
|
17180
17661
|
if (group.navTab === "findings") {
|
|
17181
17662
|
onNavigate("findings", { finding: group.navPath });
|
|
17182
17663
|
} else {
|
|
@@ -17185,7 +17666,7 @@ function TraceTimeline(props) {
|
|
|
17185
17666
|
}, [onNavigate]);
|
|
17186
17667
|
const gridCols = `${TIME_PANEL_W}px minmax(0, 1fr)`;
|
|
17187
17668
|
const timelineEventGrid = `${TIMELINE_DOT_W}px ${TIMELINE_TIME_W}px minmax(0, 1fr)`;
|
|
17188
|
-
return
|
|
17669
|
+
return import_react15.default.createElement(
|
|
17189
17670
|
"div",
|
|
17190
17671
|
{
|
|
17191
17672
|
style: {
|
|
@@ -17198,7 +17679,7 @@ function TraceTimeline(props) {
|
|
|
17198
17679
|
}
|
|
17199
17680
|
},
|
|
17200
17681
|
// ── TraceHeader ─────────────────────────────────────────────────────────
|
|
17201
|
-
|
|
17682
|
+
import_react15.default.createElement(
|
|
17202
17683
|
"div",
|
|
17203
17684
|
{
|
|
17204
17685
|
"data-testid": "trace-header",
|
|
@@ -17210,16 +17691,16 @@ function TraceTimeline(props) {
|
|
|
17210
17691
|
background: "var(--dsw-alias-bg-base)"
|
|
17211
17692
|
}
|
|
17212
17693
|
},
|
|
17213
|
-
|
|
17694
|
+
import_react15.default.createElement(
|
|
17214
17695
|
"div",
|
|
17215
17696
|
{
|
|
17216
17697
|
style: { padding: "12px 18px", borderRight: "1px solid var(--dsw-alias-border-l1)" }
|
|
17217
17698
|
},
|
|
17218
|
-
|
|
17699
|
+
import_react15.default.createElement("div", {
|
|
17219
17700
|
style: { fontSize: "13px", fontWeight: 600, color: "var(--dsw-alias-label-primary)" }
|
|
17220
17701
|
}, "Timeline")
|
|
17221
17702
|
),
|
|
17222
|
-
|
|
17703
|
+
import_react15.default.createElement(
|
|
17223
17704
|
"div",
|
|
17224
17705
|
{
|
|
17225
17706
|
style: {
|
|
@@ -17229,10 +17710,10 @@ function TraceTimeline(props) {
|
|
|
17229
17710
|
justifyContent: "space-between"
|
|
17230
17711
|
}
|
|
17231
17712
|
},
|
|
17232
|
-
|
|
17713
|
+
import_react15.default.createElement("div", {
|
|
17233
17714
|
style: { fontSize: "13px", fontWeight: 600, color: "var(--dsw-alias-label-primary)" }
|
|
17234
17715
|
}, "Topology"),
|
|
17235
|
-
|
|
17716
|
+
import_react15.default.createElement(TraceControls, {
|
|
17236
17717
|
scale,
|
|
17237
17718
|
onZoomIn: zoomIn,
|
|
17238
17719
|
onZoomOut: zoomOut,
|
|
@@ -17242,7 +17723,7 @@ function TraceTimeline(props) {
|
|
|
17242
17723
|
)
|
|
17243
17724
|
),
|
|
17244
17725
|
// ── Content (no scroll — flows into Harness scroll owner) ───────────────
|
|
17245
|
-
|
|
17726
|
+
import_react15.default.createElement(
|
|
17246
17727
|
"div",
|
|
17247
17728
|
{
|
|
17248
17729
|
onWheel: handleWheel,
|
|
@@ -17252,7 +17733,7 @@ function TraceTimeline(props) {
|
|
|
17252
17733
|
}
|
|
17253
17734
|
},
|
|
17254
17735
|
// ── Timeline rail ────────────────────────────────────────────────────
|
|
17255
|
-
|
|
17736
|
+
import_react15.default.createElement(
|
|
17256
17737
|
"div",
|
|
17257
17738
|
{
|
|
17258
17739
|
style: {
|
|
@@ -17263,7 +17744,7 @@ function TraceTimeline(props) {
|
|
|
17263
17744
|
}
|
|
17264
17745
|
},
|
|
17265
17746
|
// Vertical timeline spine line
|
|
17266
|
-
|
|
17747
|
+
import_react15.default.createElement("div", {
|
|
17267
17748
|
"aria-hidden": true,
|
|
17268
17749
|
style: {
|
|
17269
17750
|
position: "absolute",
|
|
@@ -17278,7 +17759,7 @@ function TraceTimeline(props) {
|
|
|
17278
17759
|
...scaledBands.map((band) => {
|
|
17279
17760
|
const isStart = band.bandId === "band:start";
|
|
17280
17761
|
if (band.timelineItems.length === 0) return null;
|
|
17281
|
-
return
|
|
17762
|
+
return import_react15.default.createElement(
|
|
17282
17763
|
"div",
|
|
17283
17764
|
{
|
|
17284
17765
|
key: band.bandId,
|
|
@@ -17295,7 +17776,7 @@ function TraceTimeline(props) {
|
|
|
17295
17776
|
},
|
|
17296
17777
|
// Start band
|
|
17297
17778
|
isStart && band.timelineItems.map(
|
|
17298
|
-
(item, ii) =>
|
|
17779
|
+
(item, ii) => import_react15.default.createElement(
|
|
17299
17780
|
"div",
|
|
17300
17781
|
{
|
|
17301
17782
|
key: ii,
|
|
@@ -17307,12 +17788,12 @@ function TraceTimeline(props) {
|
|
|
17307
17788
|
minHeight: `${TIMELINE_ROW_H}px`
|
|
17308
17789
|
}
|
|
17309
17790
|
},
|
|
17310
|
-
|
|
17791
|
+
import_react15.default.createElement(
|
|
17311
17792
|
"div",
|
|
17312
17793
|
{
|
|
17313
17794
|
style: { display: "flex", justifyContent: "center", paddingTop: "4px" }
|
|
17314
17795
|
},
|
|
17315
|
-
|
|
17796
|
+
import_react15.default.createElement("div", {
|
|
17316
17797
|
style: {
|
|
17317
17798
|
width: "6px",
|
|
17318
17799
|
height: "6px",
|
|
@@ -17321,7 +17802,7 @@ function TraceTimeline(props) {
|
|
|
17321
17802
|
}
|
|
17322
17803
|
})
|
|
17323
17804
|
),
|
|
17324
|
-
|
|
17805
|
+
import_react15.default.createElement("span", {
|
|
17325
17806
|
style: {
|
|
17326
17807
|
fontSize: "11px",
|
|
17327
17808
|
fontFamily: "monospace",
|
|
@@ -17330,13 +17811,13 @@ function TraceTimeline(props) {
|
|
|
17330
17811
|
paddingTop: "2px"
|
|
17331
17812
|
}
|
|
17332
17813
|
}, item.timeLabel),
|
|
17333
|
-
|
|
17814
|
+
import_react15.default.createElement(
|
|
17334
17815
|
"div",
|
|
17335
17816
|
{ style: { minWidth: 0, paddingTop: "2px" } },
|
|
17336
|
-
|
|
17817
|
+
import_react15.default.createElement("div", {
|
|
17337
17818
|
style: { fontSize: "13px", fontWeight: 500, color: "var(--dsw-alias-label-primary)", lineHeight: "18px" }
|
|
17338
17819
|
}, item.title),
|
|
17339
|
-
item.subtitle !== "" &&
|
|
17820
|
+
item.subtitle !== "" && import_react15.default.createElement("div", {
|
|
17340
17821
|
style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary)", lineHeight: "16px" }
|
|
17341
17822
|
}, item.subtitle)
|
|
17342
17823
|
)
|
|
@@ -17344,7 +17825,7 @@ function TraceTimeline(props) {
|
|
|
17344
17825
|
),
|
|
17345
17826
|
// Regular stage/agent items
|
|
17346
17827
|
!isStart && band.timelineItems.map(
|
|
17347
|
-
(item, ii) =>
|
|
17828
|
+
(item, ii) => import_react15.default.createElement(
|
|
17348
17829
|
"div",
|
|
17349
17830
|
{
|
|
17350
17831
|
key: ii,
|
|
@@ -17356,12 +17837,12 @@ function TraceTimeline(props) {
|
|
|
17356
17837
|
minHeight: `${TIMELINE_ROW_H}px`
|
|
17357
17838
|
}
|
|
17358
17839
|
},
|
|
17359
|
-
|
|
17840
|
+
import_react15.default.createElement(
|
|
17360
17841
|
"div",
|
|
17361
17842
|
{
|
|
17362
17843
|
style: { display: "flex", justifyContent: "center", paddingTop: "4px" }
|
|
17363
17844
|
},
|
|
17364
|
-
|
|
17845
|
+
import_react15.default.createElement("div", {
|
|
17365
17846
|
style: {
|
|
17366
17847
|
width: "8px",
|
|
17367
17848
|
height: "8px",
|
|
@@ -17370,7 +17851,7 @@ function TraceTimeline(props) {
|
|
|
17370
17851
|
}
|
|
17371
17852
|
})
|
|
17372
17853
|
),
|
|
17373
|
-
|
|
17854
|
+
import_react15.default.createElement("span", {
|
|
17374
17855
|
style: {
|
|
17375
17856
|
fontSize: "11px",
|
|
17376
17857
|
fontFamily: "monospace",
|
|
@@ -17379,13 +17860,13 @@ function TraceTimeline(props) {
|
|
|
17379
17860
|
paddingTop: "2px"
|
|
17380
17861
|
}
|
|
17381
17862
|
}, item.timeLabel),
|
|
17382
|
-
|
|
17863
|
+
import_react15.default.createElement(
|
|
17383
17864
|
"div",
|
|
17384
17865
|
{ style: { minWidth: 0, paddingTop: "2px" } },
|
|
17385
|
-
|
|
17866
|
+
import_react15.default.createElement("div", {
|
|
17386
17867
|
style: { fontSize: "13px", fontWeight: 500, color: "var(--dsw-alias-label-primary)", lineHeight: "18px" }
|
|
17387
17868
|
}, item.title),
|
|
17388
|
-
item.subtitle !== "" &&
|
|
17869
|
+
item.subtitle !== "" && import_react15.default.createElement("div", {
|
|
17389
17870
|
style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary)", lineHeight: "16px" }
|
|
17390
17871
|
}, item.subtitle)
|
|
17391
17872
|
)
|
|
@@ -17395,7 +17876,7 @@ function TraceTimeline(props) {
|
|
|
17395
17876
|
})
|
|
17396
17877
|
),
|
|
17397
17878
|
// ── Graph viewport ────────────────────────────────────────────────────
|
|
17398
|
-
|
|
17879
|
+
import_react15.default.createElement(
|
|
17399
17880
|
"div",
|
|
17400
17881
|
{
|
|
17401
17882
|
ref: graphVpRef,
|
|
@@ -17407,7 +17888,7 @@ function TraceTimeline(props) {
|
|
|
17407
17888
|
}
|
|
17408
17889
|
},
|
|
17409
17890
|
// SpineAnchor: CSS left:50%, always at viewport center
|
|
17410
|
-
|
|
17891
|
+
import_react15.default.createElement(
|
|
17411
17892
|
"div",
|
|
17412
17893
|
{
|
|
17413
17894
|
style: {
|
|
@@ -17420,7 +17901,7 @@ function TraceTimeline(props) {
|
|
|
17420
17901
|
}
|
|
17421
17902
|
},
|
|
17422
17903
|
// TopologyWorld: symmetric around spine
|
|
17423
|
-
|
|
17904
|
+
import_react15.default.createElement(
|
|
17424
17905
|
"div",
|
|
17425
17906
|
{
|
|
17426
17907
|
ref: graphRef,
|
|
@@ -17434,24 +17915,24 @@ function TraceTimeline(props) {
|
|
|
17434
17915
|
transformOrigin: `${spineX}px 0px`
|
|
17435
17916
|
}
|
|
17436
17917
|
},
|
|
17437
|
-
|
|
17918
|
+
import_react15.default.createElement(TraceConnectors, {
|
|
17438
17919
|
layout: { ...baseLayout, sections: adjustedSections, worldHeight: worldH, spineX },
|
|
17439
17920
|
rects: /* @__PURE__ */ new Map()
|
|
17440
17921
|
}),
|
|
17441
|
-
|
|
17922
|
+
import_react15.default.createElement(
|
|
17442
17923
|
"div",
|
|
17443
17924
|
{
|
|
17444
17925
|
style: { position: "absolute", inset: 0, zIndex: 1 }
|
|
17445
17926
|
},
|
|
17446
17927
|
...adjustedSections.filter((s) => s.stageId === "start").map(
|
|
17447
|
-
(section) =>
|
|
17928
|
+
(section) => import_react15.default.createElement(StartNode, {
|
|
17448
17929
|
key: "stage:start",
|
|
17449
17930
|
section,
|
|
17450
17931
|
x: spineX
|
|
17451
17932
|
})
|
|
17452
17933
|
),
|
|
17453
17934
|
...adjustedSections.filter((s) => s.stageId !== "start").map(
|
|
17454
|
-
(section) =>
|
|
17935
|
+
(section) => import_react15.default.createElement(StageNode, {
|
|
17455
17936
|
key: `stage:${section.stageId}`,
|
|
17456
17937
|
section,
|
|
17457
17938
|
x: spineX,
|
|
@@ -17460,7 +17941,7 @@ function TraceTimeline(props) {
|
|
|
17460
17941
|
),
|
|
17461
17942
|
...adjustedSections.flatMap(
|
|
17462
17943
|
(section) => section.agentBranches.map(
|
|
17463
|
-
(branch) =>
|
|
17944
|
+
(branch) => import_react15.default.createElement(AgentNode, {
|
|
17464
17945
|
key: `agent:${branch.delegationId}`,
|
|
17465
17946
|
branch,
|
|
17466
17947
|
x: spineX + branch.x,
|
|
@@ -17475,7 +17956,7 @@ function TraceTimeline(props) {
|
|
|
17475
17956
|
(row3, ri) => row3.map((dx, gi) => {
|
|
17476
17957
|
const group = branch.deliveryGroups[ri * 3 + gi];
|
|
17477
17958
|
if (group === void 0) return null;
|
|
17478
|
-
return
|
|
17959
|
+
return import_react15.default.createElement(DeliveryNode, {
|
|
17479
17960
|
key: `delivery:${branch.delegationId}:${group.kind}`,
|
|
17480
17961
|
group,
|
|
17481
17962
|
x: spineX + dx,
|
|
@@ -17498,11 +17979,11 @@ function TraceTimeline(props) {
|
|
|
17498
17979
|
function TraceView(props) {
|
|
17499
17980
|
const { snapshot, liveActivity, onNavigate, onOpenSession, activeTargetId } = props;
|
|
17500
17981
|
if (snapshot === null || snapshot.run === null) {
|
|
17501
|
-
return
|
|
17982
|
+
return import_react16.default.createElement("div", {
|
|
17502
17983
|
style: { padding: "24px", color: "var(--dsw-alias-label-tertiary)", fontSize: "14px" }
|
|
17503
17984
|
}, "No execution trace yet");
|
|
17504
17985
|
}
|
|
17505
|
-
return
|
|
17986
|
+
return import_react16.default.createElement(TraceTimeline, {
|
|
17506
17987
|
snapshot,
|
|
17507
17988
|
liveActivity,
|
|
17508
17989
|
onNavigate,
|
|
@@ -17512,21 +17993,21 @@ function TraceView(props) {
|
|
|
17512
17993
|
}
|
|
17513
17994
|
|
|
17514
17995
|
// src/ui/client/pentester/OutputView.tsx
|
|
17515
|
-
var
|
|
17516
|
-
var
|
|
17996
|
+
var import_react18 = __toESM(require("react"), 1);
|
|
17997
|
+
var import_dsh_client_ui_primitives7 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
17517
17998
|
|
|
17518
17999
|
// src/ui/client/pentester/FolderTreeRow.tsx
|
|
17519
|
-
var
|
|
17520
|
-
var
|
|
18000
|
+
var import_react17 = __toESM(require("react"), 1);
|
|
18001
|
+
var import_dsh_client_ui_primitives6 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
17521
18002
|
function FolderTreeRow(props) {
|
|
17522
18003
|
const { name, depth, defaultOpen = true, children, containsSelected = false } = props;
|
|
17523
|
-
const [open, setOpen] = (0,
|
|
17524
|
-
const hasChildren = children !== void 0 &&
|
|
18004
|
+
const [open, setOpen] = (0, import_react17.useState)(defaultOpen);
|
|
18005
|
+
const hasChildren = children !== void 0 && import_react17.default.Children.count(children) > 0;
|
|
17525
18006
|
const folderColor = containsSelected ? "var(--dsw-alias-state-business-primary)" : "var(--dsw-alias-label-secondary)";
|
|
17526
|
-
return
|
|
18007
|
+
return import_react17.default.createElement(
|
|
17527
18008
|
"div",
|
|
17528
18009
|
null,
|
|
17529
|
-
|
|
18010
|
+
import_react17.default.createElement(
|
|
17530
18011
|
"div",
|
|
17531
18012
|
{
|
|
17532
18013
|
role: "button",
|
|
@@ -17562,19 +18043,19 @@ function FolderTreeRow(props) {
|
|
|
17562
18043
|
}
|
|
17563
18044
|
},
|
|
17564
18045
|
// Chevron
|
|
17565
|
-
hasChildren ?
|
|
18046
|
+
hasChildren ? import_react17.default.createElement(
|
|
17566
18047
|
"span",
|
|
17567
18048
|
{ style: { flexShrink: 0, color: "var(--dsw-alias-label-tertiary)" } },
|
|
17568
|
-
|
|
17569
|
-
) :
|
|
18049
|
+
import_react17.default.createElement(open ? import_dsh_client_ui_primitives6.IconChevronDownOutline14 : import_dsh_client_ui_primitives6.IconChevronRightOutline14, { size: 14 })
|
|
18050
|
+
) : import_react17.default.createElement("span", { style: { width: "14px", flexShrink: 0 } }),
|
|
17570
18051
|
// Folder icon — color reflects selected ancestry
|
|
17571
|
-
|
|
18052
|
+
import_react17.default.createElement(
|
|
17572
18053
|
"span",
|
|
17573
18054
|
{ style: { flexShrink: 0, color: folderColor } },
|
|
17574
|
-
|
|
18055
|
+
import_react17.default.createElement(open ? import_dsh_client_ui_primitives6.IconFolderOpen16 : import_dsh_client_ui_primitives6.IconFolderClose16, { size: 16 })
|
|
17575
18056
|
),
|
|
17576
18057
|
// Name
|
|
17577
|
-
|
|
18058
|
+
import_react17.default.createElement("span", {
|
|
17578
18059
|
style: {
|
|
17579
18060
|
overflow: "hidden",
|
|
17580
18061
|
textOverflow: "ellipsis",
|
|
@@ -17582,12 +18063,12 @@ function FolderTreeRow(props) {
|
|
|
17582
18063
|
}
|
|
17583
18064
|
}, name)
|
|
17584
18065
|
),
|
|
17585
|
-
open && hasChildren &&
|
|
18066
|
+
open && hasChildren && import_react17.default.createElement("div", null, children)
|
|
17586
18067
|
);
|
|
17587
18068
|
}
|
|
17588
18069
|
function FileRow(props) {
|
|
17589
18070
|
const { name, depth, size, isSelected = false, onClick } = props;
|
|
17590
|
-
return
|
|
18071
|
+
return import_react17.default.createElement(
|
|
17591
18072
|
"div",
|
|
17592
18073
|
{
|
|
17593
18074
|
role: "button",
|
|
@@ -17622,10 +18103,10 @@ function FileRow(props) {
|
|
|
17622
18103
|
}
|
|
17623
18104
|
},
|
|
17624
18105
|
// File icon placeholder (Harness doesn't have a specific file icon; use chevron space)
|
|
17625
|
-
|
|
18106
|
+
import_react17.default.createElement("span", {
|
|
17626
18107
|
style: { width: "14px", flexShrink: 0 }
|
|
17627
18108
|
}),
|
|
17628
|
-
|
|
18109
|
+
import_react17.default.createElement("span", {
|
|
17629
18110
|
style: {
|
|
17630
18111
|
overflow: "hidden",
|
|
17631
18112
|
textOverflow: "ellipsis",
|
|
@@ -17634,7 +18115,7 @@ function FileRow(props) {
|
|
|
17634
18115
|
minWidth: 0
|
|
17635
18116
|
}
|
|
17636
18117
|
}, name),
|
|
17637
|
-
size !== void 0 &&
|
|
18118
|
+
size !== void 0 && import_react17.default.createElement("span", {
|
|
17638
18119
|
style: {
|
|
17639
18120
|
fontSize: "11px",
|
|
17640
18121
|
color: "var(--dsw-alias-label-tertiary)",
|
|
@@ -17653,7 +18134,7 @@ var OUTPUT_FILTER_TABS = [
|
|
|
17653
18134
|
];
|
|
17654
18135
|
function TargetIcon(props) {
|
|
17655
18136
|
const s = props.size ?? 16;
|
|
17656
|
-
return
|
|
18137
|
+
return import_react18.default.createElement(
|
|
17657
18138
|
"svg",
|
|
17658
18139
|
{
|
|
17659
18140
|
width: s,
|
|
@@ -17667,13 +18148,13 @@ function TargetIcon(props) {
|
|
|
17667
18148
|
"aria-hidden": true,
|
|
17668
18149
|
style: { flexShrink: 0 }
|
|
17669
18150
|
},
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
18151
|
+
import_react18.default.createElement("circle", { cx: "8", cy: "8", r: "6.5" }),
|
|
18152
|
+
import_react18.default.createElement("circle", { cx: "8", cy: "8", r: "3.5" }),
|
|
18153
|
+
import_react18.default.createElement("circle", { cx: "8", cy: "8", r: "1", fill: "currentColor", stroke: "none" }),
|
|
18154
|
+
import_react18.default.createElement("line", { x1: "8", y1: "1", x2: "8", y2: "3" }),
|
|
18155
|
+
import_react18.default.createElement("line", { x1: "8", y1: "13", x2: "8", y2: "15" }),
|
|
18156
|
+
import_react18.default.createElement("line", { x1: "1", y1: "8", x2: "3", y2: "8" }),
|
|
18157
|
+
import_react18.default.createElement("line", { x1: "13", y1: "8", x2: "15", y2: "8" })
|
|
17677
18158
|
);
|
|
17678
18159
|
}
|
|
17679
18160
|
function entryContainsSelected(entry, selectedPath) {
|
|
@@ -17684,12 +18165,12 @@ function entryContainsSelected(entry, selectedPath) {
|
|
|
17684
18165
|
}
|
|
17685
18166
|
function TargetRow(props) {
|
|
17686
18167
|
const { targetId, target, current, defaultOpen, containsSelected, children } = props;
|
|
17687
|
-
const [open, setOpen] = (0,
|
|
18168
|
+
const [open, setOpen] = (0, import_react18.useState)(defaultOpen);
|
|
17688
18169
|
const iconColor = containsSelected ? "var(--dsw-alias-state-business-primary)" : current ? "var(--dsw-alias-state-business-primary)" : "var(--dsw-alias-label-secondary)";
|
|
17689
|
-
return
|
|
18170
|
+
return import_react18.default.createElement(
|
|
17690
18171
|
"div",
|
|
17691
18172
|
null,
|
|
17692
|
-
|
|
18173
|
+
import_react18.default.createElement(
|
|
17693
18174
|
"div",
|
|
17694
18175
|
{
|
|
17695
18176
|
role: "button",
|
|
@@ -17725,7 +18206,7 @@ function TargetRow(props) {
|
|
|
17725
18206
|
e.currentTarget.style.background = "transparent";
|
|
17726
18207
|
}
|
|
17727
18208
|
},
|
|
17728
|
-
|
|
18209
|
+
import_react18.default.createElement("span", {
|
|
17729
18210
|
style: {
|
|
17730
18211
|
color: "var(--dsw-alias-label-tertiary)",
|
|
17731
18212
|
flexShrink: 0,
|
|
@@ -17735,22 +18216,22 @@ function TargetRow(props) {
|
|
|
17735
18216
|
width: "12px"
|
|
17736
18217
|
}
|
|
17737
18218
|
}, open ? "\u25BE" : "\u25B8"),
|
|
17738
|
-
|
|
18219
|
+
import_react18.default.createElement("span", {
|
|
17739
18220
|
style: {
|
|
17740
18221
|
color: iconColor,
|
|
17741
18222
|
flexShrink: 0,
|
|
17742
18223
|
display: "flex",
|
|
17743
18224
|
alignItems: "center"
|
|
17744
18225
|
}
|
|
17745
|
-
},
|
|
17746
|
-
|
|
18226
|
+
}, import_react18.default.createElement(TargetIcon, { size: 16 })),
|
|
18227
|
+
import_react18.default.createElement("span", {
|
|
17747
18228
|
style: {
|
|
17748
18229
|
overflow: "hidden",
|
|
17749
18230
|
textOverflow: "ellipsis",
|
|
17750
18231
|
whiteSpace: "nowrap"
|
|
17751
18232
|
}
|
|
17752
18233
|
}, target),
|
|
17753
|
-
current &&
|
|
18234
|
+
current && import_react18.default.createElement("span", {
|
|
17754
18235
|
style: {
|
|
17755
18236
|
fontSize: "10px",
|
|
17756
18237
|
color: "var(--dsw-alias-state-business-primary)",
|
|
@@ -17763,19 +18244,19 @@ function TargetRow(props) {
|
|
|
17763
18244
|
}
|
|
17764
18245
|
}, "active")
|
|
17765
18246
|
),
|
|
17766
|
-
open &&
|
|
18247
|
+
open && import_react18.default.createElement("div", { style: { marginLeft: "20px" } }, children)
|
|
17767
18248
|
);
|
|
17768
18249
|
}
|
|
17769
18250
|
function OutputView(props) {
|
|
17770
|
-
const { snapshot, command, sessionId } = props;
|
|
17771
|
-
const [filter, setFilter] = (0,
|
|
17772
|
-
const [preview, setPreview] = (0,
|
|
17773
|
-
const [previewContent, setPreviewContent] = (0,
|
|
17774
|
-
const [previewLoading, setPreviewLoading] = (0,
|
|
17775
|
-
const [outputTree, setOutputTree] = (0,
|
|
17776
|
-
const [outputLoading, setOutputLoading] = (0,
|
|
17777
|
-
const [outputError, setOutputError] = (0,
|
|
17778
|
-
(0,
|
|
18251
|
+
const { snapshot, command, sessionId, focusOutput } = props;
|
|
18252
|
+
const [filter, setFilter] = (0, import_react18.useState)("all");
|
|
18253
|
+
const [preview, setPreview] = (0, import_react18.useState)(null);
|
|
18254
|
+
const [previewContent, setPreviewContent] = (0, import_react18.useState)(null);
|
|
18255
|
+
const [previewLoading, setPreviewLoading] = (0, import_react18.useState)(false);
|
|
18256
|
+
const [outputTree, setOutputTree] = (0, import_react18.useState)(null);
|
|
18257
|
+
const [outputLoading, setOutputLoading] = (0, import_react18.useState)(false);
|
|
18258
|
+
const [outputError, setOutputError] = (0, import_react18.useState)(null);
|
|
18259
|
+
(0, import_react18.useEffect)(() => {
|
|
17779
18260
|
if (snapshot === null) return;
|
|
17780
18261
|
let cancelled = false;
|
|
17781
18262
|
setOutputLoading(true);
|
|
@@ -17801,7 +18282,7 @@ function OutputView(props) {
|
|
|
17801
18282
|
const targetTrees = outputTree !== null ? [outputTree] : [];
|
|
17802
18283
|
const selectedPath = preview?.entry.path ?? null;
|
|
17803
18284
|
const selectedTargetId = preview?.targetId ?? null;
|
|
17804
|
-
const filteredTargets = (0,
|
|
18285
|
+
const filteredTargets = (0, import_react18.useMemo)(() => {
|
|
17805
18286
|
const base = filter === "all" ? targetTrees : (() => {
|
|
17806
18287
|
const categoryMap = {
|
|
17807
18288
|
all: [],
|
|
@@ -17822,7 +18303,7 @@ function OutputView(props) {
|
|
|
17822
18303
|
)
|
|
17823
18304
|
}));
|
|
17824
18305
|
}, [targetTrees, filter, selectedPath, selectedTargetId]);
|
|
17825
|
-
const openPreview = (0,
|
|
18306
|
+
const openPreview = (0, import_react18.useCallback)(async (entry, targetId) => {
|
|
17826
18307
|
if (entry.kind === "directory") return;
|
|
17827
18308
|
setPreview({ entry, targetId });
|
|
17828
18309
|
setPreviewContent(null);
|
|
@@ -17845,27 +18326,37 @@ function OutputView(props) {
|
|
|
17845
18326
|
setPreviewLoading(false);
|
|
17846
18327
|
}
|
|
17847
18328
|
}, [command, sessionId]);
|
|
17848
|
-
const closePreview = (0,
|
|
18329
|
+
const closePreview = (0, import_react18.useCallback)(() => {
|
|
17849
18330
|
setPreview(null);
|
|
17850
18331
|
setPreviewContent(null);
|
|
17851
18332
|
}, []);
|
|
18333
|
+
const focusAppliedRef = (0, import_react18.useRef)(void 0);
|
|
18334
|
+
(0, import_react18.useEffect)(() => {
|
|
18335
|
+
if (focusOutput === void 0 || focusOutput === focusAppliedRef.current) return;
|
|
18336
|
+
if (outputTree === null) return;
|
|
18337
|
+
focusAppliedRef.current = focusOutput;
|
|
18338
|
+
const entry = findEntryByPath(outputTree.children, focusOutput);
|
|
18339
|
+
if (entry !== void 0) {
|
|
18340
|
+
openPreview(entry, outputTree.targetId);
|
|
18341
|
+
}
|
|
18342
|
+
}, [focusOutput, outputTree, openPreview]);
|
|
17852
18343
|
const initialLoading = outputTree === null && outputLoading;
|
|
17853
18344
|
if (initialLoading) {
|
|
17854
|
-
return
|
|
18345
|
+
return import_react18.default.createElement("div", {
|
|
17855
18346
|
style: { padding: "24px", color: "var(--dsw-alias-label-tertiary)", fontSize: "14px" }
|
|
17856
18347
|
}, "Loading output tree...");
|
|
17857
18348
|
}
|
|
17858
18349
|
if (outputError !== null) {
|
|
17859
|
-
return
|
|
18350
|
+
return import_react18.default.createElement(
|
|
17860
18351
|
"div",
|
|
17861
18352
|
{ style: { padding: "24px" } },
|
|
17862
|
-
|
|
18353
|
+
import_react18.default.createElement("div", {
|
|
17863
18354
|
style: { color: "var(--dsw-status-error)", marginBottom: "12px", fontSize: "14px" }
|
|
17864
18355
|
}, "Unable to load output tree"),
|
|
17865
|
-
|
|
18356
|
+
import_react18.default.createElement("div", {
|
|
17866
18357
|
style: { color: "var(--dsw-alias-label-tertiary)", fontSize: "12px", marginBottom: "12px" }
|
|
17867
18358
|
}, outputError),
|
|
17868
|
-
|
|
18359
|
+
import_react18.default.createElement("button", {
|
|
17869
18360
|
onClick: () => {
|
|
17870
18361
|
setOutputError(null);
|
|
17871
18362
|
setOutputTree(null);
|
|
@@ -17895,48 +18386,66 @@ function OutputView(props) {
|
|
|
17895
18386
|
);
|
|
17896
18387
|
}
|
|
17897
18388
|
if (snapshot === null) {
|
|
17898
|
-
return
|
|
18389
|
+
return import_react18.default.createElement("div", {
|
|
17899
18390
|
style: { padding: "24px", color: "var(--dsw-alias-label-tertiary)", fontSize: "14px" }
|
|
17900
18391
|
}, "No output data");
|
|
17901
18392
|
}
|
|
17902
18393
|
if (targetTrees.length === 0) {
|
|
17903
|
-
return
|
|
18394
|
+
return import_react18.default.createElement("div", {
|
|
17904
18395
|
style: { padding: "24px", color: "var(--dsw-alias-label-tertiary)", fontSize: "14px" }
|
|
17905
18396
|
}, "No output files");
|
|
17906
18397
|
}
|
|
17907
|
-
return
|
|
18398
|
+
return import_react18.default.createElement(
|
|
17908
18399
|
"div",
|
|
17909
18400
|
{
|
|
17910
|
-
style: { display: "flex", gap: "16px",
|
|
18401
|
+
style: { display: "flex", gap: "16px", flex: 1, height: "100%", minHeight: 0, minWidth: 0, overflow: "hidden" }
|
|
17911
18402
|
},
|
|
17912
18403
|
// Left: file tree
|
|
17913
|
-
|
|
18404
|
+
import_react18.default.createElement(
|
|
17914
18405
|
"div",
|
|
17915
18406
|
{
|
|
17916
18407
|
style: {
|
|
17917
18408
|
flex: "0 0 320px",
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
paddingRight: "12px",
|
|
18409
|
+
minHeight: 0,
|
|
18410
|
+
overflow: "hidden",
|
|
17921
18411
|
display: "flex",
|
|
17922
|
-
flexDirection: "column"
|
|
18412
|
+
flexDirection: "column",
|
|
18413
|
+
borderRight: "1px solid var(--dsw-alias-border-l2)",
|
|
18414
|
+
paddingRight: "12px"
|
|
17923
18415
|
}
|
|
17924
18416
|
},
|
|
17925
|
-
|
|
18417
|
+
// Filter tabs (fixed)
|
|
18418
|
+
import_react18.default.createElement(
|
|
17926
18419
|
"div",
|
|
17927
|
-
{
|
|
17928
|
-
|
|
18420
|
+
{
|
|
18421
|
+
style: {
|
|
18422
|
+
flex: "none",
|
|
18423
|
+
marginBottom: "12px",
|
|
18424
|
+
paddingTop: "2px"
|
|
18425
|
+
}
|
|
18426
|
+
},
|
|
18427
|
+
import_react18.default.createElement(PentesterTabBar, {
|
|
17929
18428
|
items: OUTPUT_FILTER_TABS,
|
|
17930
18429
|
active: filter,
|
|
17931
18430
|
onSelect: (id) => setFilter(id),
|
|
17932
18431
|
variant: "compact"
|
|
17933
18432
|
})
|
|
17934
18433
|
),
|
|
17935
|
-
// ──
|
|
17936
|
-
|
|
18434
|
+
// ── TreeViewport (scrollable) ──────────────────────────────────
|
|
18435
|
+
import_react18.default.createElement(
|
|
17937
18436
|
"div",
|
|
17938
|
-
{
|
|
17939
|
-
|
|
18437
|
+
{
|
|
18438
|
+
style: {
|
|
18439
|
+
flex: 1,
|
|
18440
|
+
minHeight: 0,
|
|
18441
|
+
minWidth: 0,
|
|
18442
|
+
overflowY: "auto",
|
|
18443
|
+
overflowX: "hidden",
|
|
18444
|
+
overscrollBehaviorY: "contain",
|
|
18445
|
+
scrollbarGutter: "stable"
|
|
18446
|
+
}
|
|
18447
|
+
},
|
|
18448
|
+
import_react18.default.createElement("div", {
|
|
17940
18449
|
style: {
|
|
17941
18450
|
fontSize: "11px",
|
|
17942
18451
|
fontWeight: 600,
|
|
@@ -17948,7 +18457,7 @@ function OutputView(props) {
|
|
|
17948
18457
|
}
|
|
17949
18458
|
}, "Targets"),
|
|
17950
18459
|
...filteredTargets.map(
|
|
17951
|
-
(t) =>
|
|
18460
|
+
(t) => import_react18.default.createElement(TargetRow, {
|
|
17952
18461
|
key: t.targetId,
|
|
17953
18462
|
targetId: t.targetId,
|
|
17954
18463
|
target: t.target,
|
|
@@ -17963,23 +18472,22 @@ function OutputView(props) {
|
|
|
17963
18472
|
)
|
|
17964
18473
|
),
|
|
17965
18474
|
// Right: preview frame
|
|
17966
|
-
|
|
18475
|
+
import_react18.default.createElement(
|
|
17967
18476
|
"div",
|
|
17968
18477
|
{
|
|
17969
18478
|
style: {
|
|
17970
18479
|
flex: 1,
|
|
17971
18480
|
minWidth: 0,
|
|
18481
|
+
minHeight: 0,
|
|
17972
18482
|
display: "flex",
|
|
17973
18483
|
flexDirection: "column",
|
|
17974
18484
|
overflow: "hidden",
|
|
17975
18485
|
border: "1px solid var(--dsw-alias-border-l2)",
|
|
17976
18486
|
borderRadius: "8px",
|
|
17977
|
-
background: "var(--dsw-alias-bg-base)"
|
|
17978
|
-
minHeight: "320px",
|
|
17979
|
-
maxHeight: "clamp(320px, 65vh, 680px)"
|
|
18487
|
+
background: "var(--dsw-alias-bg-base)"
|
|
17980
18488
|
}
|
|
17981
18489
|
},
|
|
17982
|
-
preview === null ?
|
|
18490
|
+
preview === null ? import_react18.default.createElement("div", {
|
|
17983
18491
|
style: {
|
|
17984
18492
|
flex: 1,
|
|
17985
18493
|
display: "flex",
|
|
@@ -17988,43 +18496,77 @@ function OutputView(props) {
|
|
|
17988
18496
|
color: "var(--dsw-alias-label-tertiary)",
|
|
17989
18497
|
fontSize: "13px"
|
|
17990
18498
|
}
|
|
17991
|
-
}, "Select a file to preview") :
|
|
17992
|
-
|
|
18499
|
+
}, "Select a file to preview") : import_react18.default.createElement(
|
|
18500
|
+
import_react18.default.Fragment,
|
|
17993
18501
|
null,
|
|
17994
|
-
|
|
18502
|
+
// PreviewHeader (fixed)
|
|
18503
|
+
import_react18.default.createElement(
|
|
17995
18504
|
"div",
|
|
17996
18505
|
{
|
|
17997
18506
|
style: {
|
|
17998
18507
|
flex: "none",
|
|
17999
18508
|
display: "flex",
|
|
18000
18509
|
alignItems: "center",
|
|
18001
|
-
justifyContent: "space-between",
|
|
18002
18510
|
padding: "8px 12px",
|
|
18003
18511
|
borderBottom: "1px solid var(--dsw-alias-border-l2)"
|
|
18004
18512
|
}
|
|
18005
18513
|
},
|
|
18006
|
-
|
|
18007
|
-
|
|
18008
|
-
}, preview.entry.name),
|
|
18009
|
-
import_react17.default.createElement("button", {
|
|
18010
|
-
onClick: closePreview,
|
|
18514
|
+
// Filename
|
|
18515
|
+
import_react18.default.createElement("div", {
|
|
18011
18516
|
style: {
|
|
18012
|
-
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
|
|
18517
|
+
flex: 1,
|
|
18518
|
+
minWidth: 0,
|
|
18519
|
+
fontSize: "13px",
|
|
18520
|
+
fontWeight: 600,
|
|
18521
|
+
color: "var(--dsw-alias-label-primary)",
|
|
18522
|
+
overflow: "hidden",
|
|
18523
|
+
textOverflow: "ellipsis",
|
|
18524
|
+
whiteSpace: "nowrap"
|
|
18525
|
+
}
|
|
18526
|
+
}, preview.entry.name),
|
|
18527
|
+
// Actions
|
|
18528
|
+
import_react18.default.createElement(
|
|
18529
|
+
"div",
|
|
18530
|
+
{
|
|
18531
|
+
style: {
|
|
18532
|
+
flex: "none",
|
|
18533
|
+
display: "flex",
|
|
18534
|
+
alignItems: "center",
|
|
18535
|
+
gap: "4px",
|
|
18536
|
+
marginLeft: "8px"
|
|
18537
|
+
}
|
|
18018
18538
|
},
|
|
18019
|
-
"
|
|
18020
|
-
|
|
18539
|
+
previewContent !== null && previewContent.content !== void 0 && previewContent.mime !== "binary" && import_react18.default.createElement(CopyAction, { text: previewContent.content }),
|
|
18540
|
+
import_react18.default.createElement("button", {
|
|
18541
|
+
onClick: closePreview,
|
|
18542
|
+
style: {
|
|
18543
|
+
background: "none",
|
|
18544
|
+
border: "none",
|
|
18545
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
18546
|
+
cursor: "pointer",
|
|
18547
|
+
fontSize: "18px",
|
|
18548
|
+
padding: "0 4px"
|
|
18549
|
+
},
|
|
18550
|
+
"aria-label": "Close preview"
|
|
18551
|
+
}, "\xD7")
|
|
18552
|
+
)
|
|
18021
18553
|
),
|
|
18022
|
-
|
|
18554
|
+
// PreviewBody (scrollable)
|
|
18555
|
+
import_react18.default.createElement(
|
|
18023
18556
|
"div",
|
|
18024
18557
|
{
|
|
18025
|
-
style: {
|
|
18558
|
+
style: {
|
|
18559
|
+
flex: 1,
|
|
18560
|
+
minHeight: 0,
|
|
18561
|
+
minWidth: 0,
|
|
18562
|
+
overflowY: "auto",
|
|
18563
|
+
overflowX: "auto",
|
|
18564
|
+
overscrollBehaviorY: "contain",
|
|
18565
|
+
scrollbarGutter: "stable",
|
|
18566
|
+
padding: "12px"
|
|
18567
|
+
}
|
|
18026
18568
|
},
|
|
18027
|
-
previewLoading &&
|
|
18569
|
+
previewLoading && import_react18.default.createElement("div", {
|
|
18028
18570
|
style: { color: "var(--dsw-alias-label-tertiary)", padding: "16px 0" }
|
|
18029
18571
|
}, "Loading..."),
|
|
18030
18572
|
previewContent !== null && renderPreview(previewContent)
|
|
@@ -18037,7 +18579,7 @@ function renderOutputTree(entry, depth, targetId, onSelect, selected, selectedPa
|
|
|
18037
18579
|
if (entry.kind === "directory" && entry.children !== void 0 && entry.children.length > 0) {
|
|
18038
18580
|
const isSelectedTarget = selectedTargetId === targetId;
|
|
18039
18581
|
const containsSelected = isSelectedTarget && entryContainsSelected(entry, selectedPath);
|
|
18040
|
-
return
|
|
18582
|
+
return import_react18.default.createElement(FolderTreeRow, {
|
|
18041
18583
|
key: `${targetId}:${entry.path}`,
|
|
18042
18584
|
name: entry.name,
|
|
18043
18585
|
depth,
|
|
@@ -18049,7 +18591,7 @@ function renderOutputTree(entry, depth, targetId, onSelect, selected, selectedPa
|
|
|
18049
18591
|
});
|
|
18050
18592
|
}
|
|
18051
18593
|
const isSelected = selected?.entry.path === entry.path && selected?.targetId === targetId;
|
|
18052
|
-
return
|
|
18594
|
+
return import_react18.default.createElement(FileRow, {
|
|
18053
18595
|
key: `${targetId}:${entry.path}`,
|
|
18054
18596
|
name: entry.name,
|
|
18055
18597
|
depth,
|
|
@@ -18060,33 +18602,33 @@ function renderOutputTree(entry, depth, targetId, onSelect, selected, selectedPa
|
|
|
18060
18602
|
}
|
|
18061
18603
|
function renderPreview(result) {
|
|
18062
18604
|
if (result.mime === "binary") {
|
|
18063
|
-
return
|
|
18605
|
+
return import_react18.default.createElement(
|
|
18064
18606
|
"div",
|
|
18065
18607
|
{
|
|
18066
18608
|
style: { color: "var(--dsw-alias-label-tertiary)", fontSize: "13px", padding: "16px" }
|
|
18067
18609
|
},
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18610
|
+
import_react18.default.createElement("div", { style: { marginBottom: "8px" } }, "Preview unavailable"),
|
|
18611
|
+
import_react18.default.createElement("div", { style: { fontSize: "12px" } }, `Binary file \xB7 ${formatSize(result.size)}`),
|
|
18612
|
+
import_react18.default.createElement("div", { style: { fontSize: "12px" } }, result.path)
|
|
18071
18613
|
);
|
|
18072
18614
|
}
|
|
18073
18615
|
if (result.content === void 0) {
|
|
18074
|
-
return
|
|
18616
|
+
return import_react18.default.createElement("div", {
|
|
18075
18617
|
style: { color: "var(--dsw-alias-label-tertiary)", fontSize: "13px" }
|
|
18076
18618
|
}, "No content available");
|
|
18077
18619
|
}
|
|
18078
18620
|
if (result.mime === "markdown") {
|
|
18079
|
-
return
|
|
18621
|
+
return import_react18.default.createElement(import_dsh_client_ui_primitives7.MarkdownText, { text: result.content });
|
|
18080
18622
|
}
|
|
18081
18623
|
if (result.mime === "json") {
|
|
18082
18624
|
try {
|
|
18083
18625
|
const parsed = JSON.parse(result.content);
|
|
18084
|
-
return
|
|
18626
|
+
return import_react18.default.createElement(import_dsh_client_ui_primitives7.JsonTree, { data: parsed, label: result.name });
|
|
18085
18627
|
} catch {
|
|
18086
18628
|
}
|
|
18087
18629
|
}
|
|
18088
18630
|
const lines = result.content.split("\n");
|
|
18089
|
-
return
|
|
18631
|
+
return import_react18.default.createElement(import_dsh_client_ui_primitives7.ReadBlock, {
|
|
18090
18632
|
lines: lines.map((text, i) => ({ number: i + 1, text })),
|
|
18091
18633
|
totalLines: lines.length,
|
|
18092
18634
|
maxLines: 500
|
|
@@ -18109,6 +18651,16 @@ function formatSize(bytes) {
|
|
|
18109
18651
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
18110
18652
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
18111
18653
|
}
|
|
18654
|
+
function findEntryByPath(entries, targetPath) {
|
|
18655
|
+
for (const entry of entries) {
|
|
18656
|
+
if (entry.path === targetPath) return entry;
|
|
18657
|
+
if (entry.kind === "directory" && entry.children !== void 0) {
|
|
18658
|
+
const found = findEntryByPath(entry.children, targetPath);
|
|
18659
|
+
if (found !== void 0) return found;
|
|
18660
|
+
}
|
|
18661
|
+
}
|
|
18662
|
+
return void 0;
|
|
18663
|
+
}
|
|
18112
18664
|
|
|
18113
18665
|
// src/ui/client/pentester-view.tsx
|
|
18114
18666
|
var CORE_REFRESH_MS = 1e4;
|
|
@@ -18151,13 +18703,13 @@ function resolveDelegationPresentationState(delegation, sessionList, rootSession
|
|
|
18151
18703
|
return "unknown";
|
|
18152
18704
|
}
|
|
18153
18705
|
function useDelegationActivity(sessions, rootSessionId, delegations) {
|
|
18154
|
-
const delegationSessionIds = (0,
|
|
18706
|
+
const delegationSessionIds = (0, import_react19.useMemo)(
|
|
18155
18707
|
() => new Set(delegations.filter((d) => d.sessionId !== void 0).map((d) => d.sessionId)),
|
|
18156
18708
|
[delegations]
|
|
18157
18709
|
);
|
|
18158
|
-
const prevSigRef = (0,
|
|
18159
|
-
const cachedMapRef = (0,
|
|
18160
|
-
const getSnapshot = (0,
|
|
18710
|
+
const prevSigRef = (0, import_react19.useRef)("");
|
|
18711
|
+
const cachedMapRef = (0, import_react19.useRef)(/* @__PURE__ */ new Map());
|
|
18712
|
+
const getSnapshot = (0, import_react19.useCallback)(() => {
|
|
18161
18713
|
const raw = sessions?.list.getSnapshot();
|
|
18162
18714
|
if (raw === void 0) return cachedMapRef.current;
|
|
18163
18715
|
const sig = computeActivitySignature(raw, rootSessionId, delegationSessionIds);
|
|
@@ -18171,7 +18723,7 @@ function useDelegationActivity(sessions, rootSessionId, delegations) {
|
|
|
18171
18723
|
cachedMapRef.current = map2;
|
|
18172
18724
|
return map2;
|
|
18173
18725
|
}, [sessions, rootSessionId, delegationSessionIds, delegations]);
|
|
18174
|
-
return (0,
|
|
18726
|
+
return (0, import_react19.useSyncExternalStore)(
|
|
18175
18727
|
sessions?.list.subscribe ?? (() => () => {
|
|
18176
18728
|
}),
|
|
18177
18729
|
getSnapshot
|
|
@@ -18183,7 +18735,7 @@ var RPC_PREFIX = "[PENTESTER_RPC]";
|
|
|
18183
18735
|
var isPerf = typeof window !== "undefined" && window.__DSH_PENTESTER_PERF === true;
|
|
18184
18736
|
function PentesterView(props) {
|
|
18185
18737
|
const { sessionId, reflect, sessions, useSession, sessionSwitchTimes: sessionSwitchTimes2, sessionPerf } = props;
|
|
18186
|
-
const mountTime = (0,
|
|
18738
|
+
const mountTime = (0, import_react19.useRef)(performance.now());
|
|
18187
18739
|
const switchTime = sessionSwitchTimes2?.get(sessionId);
|
|
18188
18740
|
if (isPerf) {
|
|
18189
18741
|
console.log(`${PERF_PREFIX} mount=0ms`);
|
|
@@ -18192,8 +18744,8 @@ function PentesterView(props) {
|
|
|
18192
18744
|
}
|
|
18193
18745
|
}
|
|
18194
18746
|
const openState = useSession?.((s) => s.openState);
|
|
18195
|
-
const prevOpenState = (0,
|
|
18196
|
-
(0,
|
|
18747
|
+
const prevOpenState = (0, import_react19.useRef)(void 0);
|
|
18748
|
+
(0, import_react19.useEffect)(() => {
|
|
18197
18749
|
if (!sessionPerf || openState === void 0) return;
|
|
18198
18750
|
if (openState !== prevOpenState.current) {
|
|
18199
18751
|
const elapsed = (performance.now() - mountTime.current).toFixed(0);
|
|
@@ -18219,27 +18771,27 @@ function PentesterView(props) {
|
|
|
18219
18771
|
prevOpenState.current = openState;
|
|
18220
18772
|
}
|
|
18221
18773
|
}, [openState, sessionPerf, switchTime]);
|
|
18222
|
-
const [tab, setTab] = (0,
|
|
18223
|
-
const [dataState, setDataState] = (0,
|
|
18224
|
-
const [requestState, setRequestState] = (0,
|
|
18225
|
-
const [navFocus, setNavFocus] = (0,
|
|
18226
|
-
const [activeTargetId, setActiveTargetId] = (0,
|
|
18227
|
-
const requestSeqRef = (0,
|
|
18228
|
-
const pendingRef = (0,
|
|
18229
|
-
const mountedRef = (0,
|
|
18230
|
-
const firstLoadDone = (0,
|
|
18231
|
-
const pollingPausedRef = (0,
|
|
18232
|
-
const backoffRef = (0,
|
|
18233
|
-
const timerRef = (0,
|
|
18234
|
-
const snapshotRef = (0,
|
|
18235
|
-
const pentesterCommand = (0,
|
|
18774
|
+
const [tab, setTab] = (0, import_react19.useState)("overview");
|
|
18775
|
+
const [dataState, setDataState] = (0, import_react19.useState)({ kind: "initial" });
|
|
18776
|
+
const [requestState, setRequestState] = (0, import_react19.useState)("idle");
|
|
18777
|
+
const [navFocus, setNavFocus] = (0, import_react19.useState)({});
|
|
18778
|
+
const [activeTargetId, setActiveTargetId] = (0, import_react19.useState)(null);
|
|
18779
|
+
const requestSeqRef = (0, import_react19.useRef)(0);
|
|
18780
|
+
const pendingRef = (0, import_react19.useRef)(null);
|
|
18781
|
+
const mountedRef = (0, import_react19.useRef)(true);
|
|
18782
|
+
const firstLoadDone = (0, import_react19.useRef)(false);
|
|
18783
|
+
const pollingPausedRef = (0, import_react19.useRef)(false);
|
|
18784
|
+
const backoffRef = (0, import_react19.useRef)(0);
|
|
18785
|
+
const timerRef = (0, import_react19.useRef)(null);
|
|
18786
|
+
const snapshotRef = (0, import_react19.useRef)(null);
|
|
18787
|
+
const pentesterCommand = (0, import_react19.useCallback)((input2, timeoutMs) => {
|
|
18236
18788
|
const currentFace = reflect?.get("remote.pentesterView");
|
|
18237
18789
|
return pentesterViewCommand(currentFace, input2, timeoutMs);
|
|
18238
18790
|
}, [reflect]);
|
|
18239
18791
|
const snapshot = dataState.kind === "bound" ? dataState.snapshot : null;
|
|
18240
18792
|
const delegations = snapshot?.delegations ?? [];
|
|
18241
18793
|
const liveActivity = useDelegationActivity(sessions, sessionId, delegations);
|
|
18242
|
-
const loadSnapshot = (0,
|
|
18794
|
+
const loadSnapshot = (0, import_react19.useCallback)(async (reason) => {
|
|
18243
18795
|
if (reason !== "retry" && reason !== "refresh" && getPentesterEndpointState() === "missing") {
|
|
18244
18796
|
if (isPerf) console.log(`${RPC_PREFIX} circuit-open endpoint=missing reason=${reason}`);
|
|
18245
18797
|
return;
|
|
@@ -18357,7 +18909,7 @@ Client: ${mismatch.client}`,
|
|
|
18357
18909
|
}
|
|
18358
18910
|
}
|
|
18359
18911
|
}, [pentesterCommand, sessionId, switchTime]);
|
|
18360
|
-
(0,
|
|
18912
|
+
(0, import_react19.useEffect)(() => {
|
|
18361
18913
|
mountedRef.current = true;
|
|
18362
18914
|
pollingPausedRef.current = false;
|
|
18363
18915
|
backoffRef.current = 0;
|
|
@@ -18385,7 +18937,7 @@ Client: ${mismatch.client}`,
|
|
|
18385
18937
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
18386
18938
|
};
|
|
18387
18939
|
}, [loadSnapshot]);
|
|
18388
|
-
(0,
|
|
18940
|
+
(0, import_react19.useEffect)(() => {
|
|
18389
18941
|
const onVisible = () => {
|
|
18390
18942
|
if (document.visibilityState === "visible" && mountedRef.current && firstLoadDone.current && !pollingPausedRef.current) {
|
|
18391
18943
|
loadSnapshot("visible");
|
|
@@ -18394,11 +18946,11 @@ Client: ${mismatch.client}`,
|
|
|
18394
18946
|
document.addEventListener("visibilitychange", onVisible);
|
|
18395
18947
|
return () => document.removeEventListener("visibilitychange", onVisible);
|
|
18396
18948
|
}, [loadSnapshot]);
|
|
18397
|
-
const navigate = (0,
|
|
18949
|
+
const navigate = (0, import_react19.useCallback)((targetTab, focus) => {
|
|
18398
18950
|
setTab(targetTab);
|
|
18399
18951
|
if (focus !== void 0) setNavFocus(focus);
|
|
18400
18952
|
}, []);
|
|
18401
|
-
const openSession = (0,
|
|
18953
|
+
const openSession = (0, import_react19.useCallback)((id) => {
|
|
18402
18954
|
sessions?.open(id);
|
|
18403
18955
|
}, [sessions]);
|
|
18404
18956
|
const isInitialLoading = dataState.kind === "initial" && requestState === "pending";
|
|
@@ -18406,28 +18958,28 @@ Client: ${mismatch.client}`,
|
|
|
18406
18958
|
const errorMsg = dataState.kind === "error" ? dataState.error : null;
|
|
18407
18959
|
const errorCode = dataState.kind === "error" ? dataState.code : null;
|
|
18408
18960
|
const hasSnapshot = snapshot !== null;
|
|
18409
|
-
return
|
|
18961
|
+
return import_react19.default.createElement(
|
|
18410
18962
|
"div",
|
|
18411
18963
|
{
|
|
18412
18964
|
"data-testid": "pentester-view",
|
|
18413
18965
|
"data-pentester-view": "",
|
|
18966
|
+
"data-conversation-composer-overlay": "",
|
|
18414
18967
|
style: {
|
|
18415
18968
|
display: "flex",
|
|
18416
18969
|
flexDirection: "column",
|
|
18417
18970
|
width: "100%",
|
|
18418
|
-
|
|
18419
|
-
|
|
18971
|
+
height: "100%",
|
|
18972
|
+
minHeight: 0,
|
|
18973
|
+
overflow: "hidden"
|
|
18420
18974
|
}
|
|
18421
18975
|
},
|
|
18422
18976
|
// ── Layer 1: TabsBar (sticky) ────────────────────────────────────────
|
|
18423
|
-
|
|
18977
|
+
import_react19.default.createElement(
|
|
18424
18978
|
"div",
|
|
18425
18979
|
{
|
|
18426
18980
|
"data-testid": "pentester-tabs-bar",
|
|
18427
18981
|
style: {
|
|
18428
18982
|
flex: "none",
|
|
18429
|
-
position: "sticky",
|
|
18430
|
-
top: 0,
|
|
18431
18983
|
zIndex: 29,
|
|
18432
18984
|
background: "var(--dsw-alias-bg-base)",
|
|
18433
18985
|
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
@@ -18436,7 +18988,7 @@ Client: ${mismatch.client}`,
|
|
|
18436
18988
|
boxSizing: "border-box"
|
|
18437
18989
|
}
|
|
18438
18990
|
},
|
|
18439
|
-
|
|
18991
|
+
import_react19.default.createElement(PentesterTabBar, {
|
|
18440
18992
|
items: PENTESTER_TABS.map((t) => ({
|
|
18441
18993
|
id: t.id,
|
|
18442
18994
|
label: t.id.charAt(0).toUpperCase() + t.id.slice(1)
|
|
@@ -18447,7 +18999,7 @@ Client: ${mismatch.client}`,
|
|
|
18447
18999
|
),
|
|
18448
19000
|
// ── Refresh error banner ──────────────────────────────────────────────
|
|
18449
19001
|
// Stale-while-revalidate: error + last good snapshot → show banner
|
|
18450
|
-
errorMsg !== null && hasSnapshot &&
|
|
19002
|
+
errorMsg !== null && hasSnapshot && import_react19.default.createElement(
|
|
18451
19003
|
"div",
|
|
18452
19004
|
{
|
|
18453
19005
|
style: {
|
|
@@ -18461,8 +19013,8 @@ Client: ${mismatch.client}`,
|
|
|
18461
19013
|
alignItems: "center"
|
|
18462
19014
|
}
|
|
18463
19015
|
},
|
|
18464
|
-
|
|
18465
|
-
|
|
19016
|
+
import_react19.default.createElement("span", null, errorMsg),
|
|
19017
|
+
import_react19.default.createElement("button", {
|
|
18466
19018
|
onClick: () => {
|
|
18467
19019
|
if (pendingRef.current === null) {
|
|
18468
19020
|
void loadSnapshot("retry");
|
|
@@ -18482,29 +19034,32 @@ Client: ${mismatch.client}`,
|
|
|
18482
19034
|
}
|
|
18483
19035
|
}, isRetrying ? "Retrying\u2026" : "Retry")
|
|
18484
19036
|
),
|
|
18485
|
-
// ── Body: flex
|
|
18486
|
-
|
|
19037
|
+
// ── Body: bounded flex viewport ────────────────────────────────────
|
|
19038
|
+
import_react19.default.createElement(
|
|
18487
19039
|
"div",
|
|
18488
19040
|
{
|
|
18489
19041
|
style: {
|
|
18490
19042
|
flex: 1,
|
|
18491
19043
|
minHeight: 0,
|
|
18492
|
-
overflow: "
|
|
18493
|
-
|
|
19044
|
+
overflow: "hidden",
|
|
19045
|
+
display: "flex",
|
|
19046
|
+
flexDirection: "column",
|
|
19047
|
+
padding: "16px",
|
|
19048
|
+
boxSizing: "border-box"
|
|
18494
19049
|
}
|
|
18495
19050
|
},
|
|
18496
19051
|
// Initial loading: shell is already visible, show skeleton
|
|
18497
|
-
isInitialLoading &&
|
|
19052
|
+
isInitialLoading && import_react19.default.createElement("div", {
|
|
18498
19053
|
style: { padding: "24px", color: "var(--dsw-alias-label-tertiary)", fontSize: "14px" }
|
|
18499
19054
|
}, "Loading..."),
|
|
18500
19055
|
// Error state (no last good snapshot)
|
|
18501
|
-
dataState.kind === "error" && !hasSnapshot &&
|
|
19056
|
+
dataState.kind === "error" && !hasSnapshot && import_react19.default.createElement(
|
|
18502
19057
|
"div",
|
|
18503
19058
|
{ style: { padding: "24px" } },
|
|
18504
|
-
|
|
19059
|
+
import_react19.default.createElement("div", {
|
|
18505
19060
|
style: { color: "var(--dsw-status-error)", marginBottom: "12px", fontSize: "14px" }
|
|
18506
19061
|
}, errorMsg ?? "Unknown error"),
|
|
18507
|
-
|
|
19062
|
+
import_react19.default.createElement("button", {
|
|
18508
19063
|
onClick: () => {
|
|
18509
19064
|
if (pendingRef.current === null) {
|
|
18510
19065
|
void loadSnapshot("retry");
|
|
@@ -18524,20 +19079,20 @@ Client: ${mismatch.client}`,
|
|
|
18524
19079
|
}, isRetrying ? "Retrying\u2026" : "Retry")
|
|
18525
19080
|
),
|
|
18526
19081
|
// Unbound state
|
|
18527
|
-
dataState.kind === "unbound" &&
|
|
19082
|
+
dataState.kind === "unbound" && import_react19.default.createElement(
|
|
18528
19083
|
"div",
|
|
18529
19084
|
{ style: { padding: "24px" } },
|
|
18530
|
-
|
|
19085
|
+
import_react19.default.createElement("div", {
|
|
18531
19086
|
style: { fontSize: "14px", color: "var(--dsw-alias-label-tertiary)", marginBottom: "16px" }
|
|
18532
19087
|
}, "This session is not bound to a pentest target."),
|
|
18533
|
-
dataState.targets.length > 0 &&
|
|
19088
|
+
dataState.targets.length > 0 && import_react19.default.createElement(
|
|
18534
19089
|
"div",
|
|
18535
19090
|
{ style: { marginBottom: "12px" } },
|
|
18536
|
-
|
|
19091
|
+
import_react19.default.createElement("div", {
|
|
18537
19092
|
style: { fontSize: "13px", fontWeight: 600, marginBottom: "8px", color: "var(--dsw-alias-label-primary)" }
|
|
18538
19093
|
}, "Existing targets"),
|
|
18539
19094
|
...dataState.targets.map(
|
|
18540
|
-
(t) =>
|
|
19095
|
+
(t) => import_react19.default.createElement(
|
|
18541
19096
|
"div",
|
|
18542
19097
|
{
|
|
18543
19098
|
key: t.id,
|
|
@@ -18552,17 +19107,17 @@ Client: ${mismatch.client}`,
|
|
|
18552
19107
|
fontSize: "13px"
|
|
18553
19108
|
}
|
|
18554
19109
|
},
|
|
18555
|
-
|
|
19110
|
+
import_react19.default.createElement(
|
|
18556
19111
|
"div",
|
|
18557
19112
|
null,
|
|
18558
|
-
|
|
18559
|
-
|
|
19113
|
+
import_react19.default.createElement("div", { style: { fontWeight: 500 } }, t.target),
|
|
19114
|
+
import_react19.default.createElement(
|
|
18560
19115
|
"div",
|
|
18561
19116
|
{ style: { color: "var(--dsw-alias-label-tertiary)", fontSize: "12px" } },
|
|
18562
19117
|
`${t.currentStage ?? "unknown"} \xB7 ${t.status}`
|
|
18563
19118
|
)
|
|
18564
19119
|
),
|
|
18565
|
-
t.rootSessionId !== null &&
|
|
19120
|
+
t.rootSessionId !== null && import_react19.default.createElement("button", {
|
|
18566
19121
|
onClick: () => sessions?.open(t.rootSessionId),
|
|
18567
19122
|
style: {
|
|
18568
19123
|
padding: "4px 12px",
|
|
@@ -18577,7 +19132,7 @@ Client: ${mismatch.client}`,
|
|
|
18577
19132
|
)
|
|
18578
19133
|
)
|
|
18579
19134
|
),
|
|
18580
|
-
|
|
19135
|
+
import_react19.default.createElement("button", {
|
|
18581
19136
|
onClick: () => {
|
|
18582
19137
|
if (pendingRef.current === null) {
|
|
18583
19138
|
void loadSnapshot("refresh");
|
|
@@ -18597,38 +19152,59 @@ Client: ${mismatch.client}`,
|
|
|
18597
19152
|
}
|
|
18598
19153
|
}, "Refresh")
|
|
18599
19154
|
),
|
|
18600
|
-
// Bound content
|
|
18601
|
-
dataState.kind === "bound" &&
|
|
18602
|
-
|
|
18603
|
-
|
|
18604
|
-
|
|
18605
|
-
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
19155
|
+
// Bound content — wrapped in a bounded viewport
|
|
19156
|
+
dataState.kind === "bound" && import_react19.default.createElement(
|
|
19157
|
+
"div",
|
|
19158
|
+
{
|
|
19159
|
+
style: {
|
|
19160
|
+
flex: 1,
|
|
19161
|
+
minHeight: 0,
|
|
19162
|
+
minWidth: 0,
|
|
19163
|
+
overflow: "hidden",
|
|
19164
|
+
display: "flex",
|
|
19165
|
+
flexDirection: "column"
|
|
19166
|
+
}
|
|
19167
|
+
},
|
|
19168
|
+
tab === "overview" && import_react19.default.createElement(
|
|
19169
|
+
ScrollablePage,
|
|
19170
|
+
null,
|
|
19171
|
+
import_react19.default.createElement(OverviewView, {
|
|
19172
|
+
snapshot,
|
|
19173
|
+
liveActivity,
|
|
19174
|
+
onNavigate: navigate,
|
|
19175
|
+
onOpenSession: openSession
|
|
19176
|
+
})
|
|
19177
|
+
),
|
|
19178
|
+
tab === "stages" && import_react19.default.createElement(
|
|
19179
|
+
ScrollablePage,
|
|
19180
|
+
null,
|
|
19181
|
+
import_react19.default.createElement(StagesView, {
|
|
19182
|
+
snapshot,
|
|
19183
|
+
liveActivity,
|
|
19184
|
+
onNavigate: navigate,
|
|
19185
|
+
onOpenSession: openSession,
|
|
19186
|
+
focusStage: navFocus.stage
|
|
19187
|
+
})
|
|
19188
|
+
),
|
|
19189
|
+
tab === "findings" && import_react19.default.createElement(FindingsView, {
|
|
18618
19190
|
snapshot,
|
|
18619
19191
|
command: pentesterCommand,
|
|
18620
19192
|
sessionId,
|
|
18621
19193
|
onNavigate: navigate,
|
|
18622
19194
|
focusFinding: navFocus.finding
|
|
18623
19195
|
}),
|
|
18624
|
-
tab === "trace" &&
|
|
18625
|
-
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
19196
|
+
tab === "trace" && import_react19.default.createElement(
|
|
19197
|
+
ScrollablePage,
|
|
19198
|
+
null,
|
|
19199
|
+
import_react19.default.createElement(TraceView, {
|
|
19200
|
+
snapshot,
|
|
19201
|
+
liveActivity,
|
|
19202
|
+
onNavigate: navigate,
|
|
19203
|
+
onOpenSession: openSession,
|
|
19204
|
+
activeTargetId
|
|
19205
|
+
})
|
|
19206
|
+
),
|
|
19207
|
+
tab === "output" && import_react19.default.createElement(OutputView, {
|
|
18632
19208
|
snapshot,
|
|
18633
19209
|
command: pentesterCommand,
|
|
18634
19210
|
sessionId,
|
|
@@ -18638,6 +19214,17 @@ Client: ${mismatch.client}`,
|
|
|
18638
19214
|
)
|
|
18639
19215
|
);
|
|
18640
19216
|
}
|
|
19217
|
+
function ScrollablePage(props) {
|
|
19218
|
+
return import_react19.default.createElement("div", {
|
|
19219
|
+
style: {
|
|
19220
|
+
flex: 1,
|
|
19221
|
+
minHeight: 0,
|
|
19222
|
+
overflowY: "auto",
|
|
19223
|
+
overflowX: "hidden",
|
|
19224
|
+
overscrollBehavior: "contain"
|
|
19225
|
+
}
|
|
19226
|
+
}, props.children);
|
|
19227
|
+
}
|
|
18641
19228
|
|
|
18642
19229
|
// src/ui/client/pentester/locales.ts
|
|
18643
19230
|
var NS = "dsh-pentester-view";
|
|
@@ -18719,7 +19306,7 @@ var en = {
|
|
|
18719
19306
|
};
|
|
18720
19307
|
|
|
18721
19308
|
// src/build-id.ts
|
|
18722
|
-
var BUILD_ID = "2.
|
|
19309
|
+
var BUILD_ID = "2.4.0+3a85fc6";
|
|
18723
19310
|
|
|
18724
19311
|
// src/ui/client/plugin.tsx
|
|
18725
19312
|
var SESSION_SWITCH_PERF = "[SESSION_SWITCH_PERF]";
|
|
@@ -18747,7 +19334,7 @@ function getRemoteMountError() {
|
|
|
18747
19334
|
}
|
|
18748
19335
|
var inject = ["slots", "remote", "sessions", "locale"];
|
|
18749
19336
|
function apply(ctx) {
|
|
18750
|
-
console.log(`[dsh-pentester]
|
|
19337
|
+
console.log(`[dsh-pentester/client] build=${BUILD_ID}`);
|
|
18751
19338
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "pentester: locale");
|
|
18752
19339
|
ctx.effect(() => {
|
|
18753
19340
|
let disposeMount;
|
|
@@ -18780,17 +19367,20 @@ function apply(ctx) {
|
|
|
18780
19367
|
if (result.ok && result.value !== null && typeof result.value === "object" && "ok" in result.value) {
|
|
18781
19368
|
const inner = result.value.value;
|
|
18782
19369
|
if (inner?.ready === true && typeof inner.buildId === "string") {
|
|
19370
|
+
console.log(`[dsh-pentester/client] health host=${inner.buildId} client=${BUILD_ID}`);
|
|
18783
19371
|
if (inner.buildId === BUILD_ID) {
|
|
19372
|
+
if (buildMismatch !== null) {
|
|
19373
|
+
console.log(`[dsh-pentester/client] build mismatch cleared (was host=${buildMismatch.host} client=${buildMismatch.client})`);
|
|
19374
|
+
}
|
|
18784
19375
|
buildMismatch = null;
|
|
18785
|
-
console.log(`[dsh-pentester] health check passed host=${inner.buildId} client=${BUILD_ID}`);
|
|
18786
19376
|
} else {
|
|
18787
19377
|
buildMismatch = { host: inner.buildId, client: BUILD_ID };
|
|
18788
|
-
console.error(`[dsh-pentester]
|
|
19378
|
+
console.error(`[dsh-pentester/client] build mismatch set host=${inner.buildId} client=${BUILD_ID}`);
|
|
18789
19379
|
}
|
|
18790
19380
|
}
|
|
18791
19381
|
}
|
|
18792
19382
|
} catch (error51) {
|
|
18793
|
-
console.warn("[dsh-pentester] build health check unavailable", error51);
|
|
19383
|
+
console.warn("[dsh-pentester/client] build health check unavailable", error51);
|
|
18794
19384
|
}
|
|
18795
19385
|
})();
|
|
18796
19386
|
}).catch((error51) => {
|
|
@@ -18816,7 +19406,7 @@ function apply(ctx) {
|
|
|
18816
19406
|
return { command: (input2) => dockerCommand(face, input2) };
|
|
18817
19407
|
}
|
|
18818
19408
|
},
|
|
18819
|
-
(props) =>
|
|
19409
|
+
(props) => import_react20.default.createElement(PentesterConfigSection, { ...props })
|
|
18820
19410
|
)
|
|
18821
19411
|
);
|
|
18822
19412
|
ctx.slots.inject("conversation.view", () => {
|
|
@@ -18863,7 +19453,7 @@ function apply(ctx) {
|
|
|
18863
19453
|
}
|
|
18864
19454
|
},
|
|
18865
19455
|
(props) => {
|
|
18866
|
-
return
|
|
19456
|
+
return import_react20.default.createElement(PentesterView, {
|
|
18867
19457
|
sessionId: props.sessionId,
|
|
18868
19458
|
reflect: props.reflect,
|
|
18869
19459
|
sessions: props.sessions,
|