0sec-cli 0.15.0 → 0.18.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/0sec.js +327 -0
- package/README.md +68 -48
- package/attacks/data-exfiltration/pii-leakage.yaml +27 -0
- package/attacks/encoding-bypass/base64-encoding.yaml +24 -0
- package/attacks/jailbreak/dan-roleplay.yaml +27 -0
- package/attacks/jailbreak/hypothetical-scenario.yaml +25 -0
- package/attacks/jailbreak/multilingual-bypass.yaml +22 -0
- package/attacks/output-manipulation/harmful-content.yaml +25 -0
- package/attacks/prompt-injection/context-manipulation.yaml +32 -0
- package/attacks/prompt-injection/direct-injection.yaml +28 -0
- package/attacks/prompt-injection/indirect-injection.yaml +33 -0
- package/attacks/system-prompt-extraction/direct-ask.yaml +30 -0
- package/attacks/system-prompt-extraction/markdown-exfil.yaml +26 -0
- package/attacks/tool-misuse/ssrf-via-tools.yaml +27 -0
- package/chunks/adapt-loop-SMH6V4PD.js +18 -0
- package/chunks/adgraph-JLGA6RYI.js +54 -0
- package/chunks/agent/skills/frameworks/entra-id.yaml +63 -0
- package/chunks/agent/skills/frameworks/graphql-introspection.yaml +116 -0
- package/chunks/agent/skills/frameworks/nextjs.yaml +82 -0
- package/chunks/agent/skills/frameworks/python-web.yaml +85 -0
- package/chunks/agent/skills/frameworks/supabase.yaml +83 -0
- package/chunks/agent/skills/frameworks/wordpress-deep.yaml +122 -0
- package/chunks/agent/skills/techniques/ad-attack-paths.yaml +57 -0
- package/chunks/agent/skills/techniques/advisory-disclosure.yaml +59 -0
- package/chunks/agent/skills/techniques/assumption-mining.yaml +53 -0
- package/chunks/agent/skills/techniques/blind-exploitation.yaml +143 -0
- package/chunks/agent/skills/techniques/crypto-misuse.yaml +88 -0
- package/chunks/agent/skills/techniques/cve-poc-adaptation.yaml +82 -0
- package/chunks/agent/skills/techniques/entra-attack-paths.yaml +55 -0
- package/chunks/agent/skills/techniques/http-conformance-diff.yaml +48 -0
- package/chunks/agent/skills/techniques/jwt-attacks.yaml +137 -0
- package/chunks/agent/skills/techniques/kernel-weaponization.yaml +53 -0
- package/chunks/agent/skills/techniques/llm-excessive-agency.yaml +55 -0
- package/chunks/agent/skills/techniques/llm-insecure-output-handling.yaml +56 -0
- package/chunks/agent/skills/techniques/llm-prompt-injection.yaml +54 -0
- package/chunks/agent/skills/techniques/llm-prompt-layer-write.yaml +68 -0
- package/chunks/agent/skills/techniques/llm-rag-poisoning.yaml +57 -0
- package/chunks/agent/skills/techniques/llm-safety-eval.yaml +51 -0
- package/chunks/agent/skills/techniques/npm-ecosystem.yaml +51 -0
- package/chunks/agent/skills/techniques/poc-verification.yaml +55 -0
- package/chunks/agent/skills/techniques/race-condition.yaml +122 -0
- package/chunks/agent/skills/techniques/scoped-fix.yaml +49 -0
- package/chunks/agent/skills/techniques/seedless-depth-review.yaml +59 -0
- package/chunks/agent/skills/techniques/spec-differential.yaml +48 -0
- package/chunks/agent/skills/techniques/variant-hunting.yaml +55 -0
- package/chunks/agent/skills/vulnerabilities/cardano-eutxo-validators.yaml +72 -0
- package/chunks/agent/skills/vulnerabilities/command-injection.yaml +99 -0
- package/chunks/agent/skills/vulnerabilities/deserialization-chains.yaml +106 -0
- package/chunks/agent/skills/vulnerabilities/native-memory-safety.yaml +93 -0
- package/chunks/agent/skills/vulnerabilities/path-traversal.yaml +78 -0
- package/chunks/agent/skills/vulnerabilities/prototype-pollution.yaml +132 -0
- package/chunks/agent/skills/vulnerabilities/request-smuggling.yaml +129 -0
- package/chunks/agent/skills/vulnerabilities/sqli-advanced.yaml +102 -0
- package/chunks/agent/skills/vulnerabilities/ssrf-bypass.yaml +84 -0
- package/chunks/agent/skills/vulnerabilities/ssti-exploitation.yaml +112 -0
- package/chunks/agent/skills/vulnerabilities/structural-sqli.yaml +91 -0
- package/chunks/appsec-catalog-CBWHGTEL.js +24 -0
- package/chunks/artifact-scraper-HQ7HLP6V.js +34 -0
- package/chunks/assumption-mining-5SNIVVDN.js +79 -0
- package/chunks/chunk-242TMK6G.js +110 -0
- package/chunks/chunk-2JCCA2JL.js +381 -0
- package/chunks/chunk-2RMLOJVB.js +47 -0
- package/chunks/chunk-3KPWWJCI.js +1422 -0
- package/chunks/chunk-3MOLBTLS.js +953 -0
- package/chunks/chunk-53G27VPS.js +136 -0
- package/chunks/chunk-57ZENEX2.js +169 -0
- package/chunks/chunk-5G3ZXFBW.js +182 -0
- package/chunks/chunk-5JI7L7KV.js +74240 -0
- package/chunks/chunk-6L26OBWI.js +1094 -0
- package/chunks/chunk-6LKRLK2R.js +542 -0
- package/chunks/chunk-72CISA2D.js +2597 -0
- package/chunks/chunk-7DQEV5QI.js +287 -0
- package/chunks/chunk-AD7WXDH6.js +3250 -0
- package/chunks/chunk-ADOLI6DT.js +102 -0
- package/chunks/chunk-AHTBZC3E.js +596 -0
- package/chunks/chunk-ASUR522M.js +518 -0
- package/chunks/chunk-ATATQACO.js +471 -0
- package/chunks/chunk-BATRQBOR.js +1732 -0
- package/chunks/chunk-BFR2CDV5.js +5735 -0
- package/chunks/chunk-BFRB6HB2.js +235 -0
- package/chunks/chunk-BKZFDZ23.js +361 -0
- package/chunks/chunk-BVAZO4WA.js +193 -0
- package/chunks/chunk-BZNEY2ZS.js +33225 -0
- package/chunks/chunk-C2WXWFBB.js +1070 -0
- package/chunks/chunk-CMKXP5RR.js +917 -0
- package/chunks/chunk-DW5UWPFY.js +275 -0
- package/chunks/chunk-F3WBKITT.js +687 -0
- package/chunks/chunk-GMT2AZKM.js +2439 -0
- package/chunks/chunk-H2FFLZNK.js +3 -0
- package/chunks/chunk-IOL7D5YV.js +515 -0
- package/chunks/chunk-IR537GON.js +49 -0
- package/chunks/chunk-JQHOLLTD.js +3729 -0
- package/chunks/chunk-KLTNTE2Z.js +121 -0
- package/chunks/chunk-LP3HHYQU.js +245 -0
- package/chunks/chunk-MYVT64FN.js +16 -0
- package/chunks/chunk-N7BOUYEV.js +852 -0
- package/chunks/chunk-OEFNRYI2.js +150 -0
- package/chunks/chunk-P6WKNFWX.js +1968 -0
- package/chunks/chunk-QI233I24.js +333 -0
- package/chunks/chunk-RJWOYEOG.js +271 -0
- package/chunks/chunk-RRMJC3ZE.js +105 -0
- package/chunks/chunk-RWONANDA.js +973 -0
- package/chunks/chunk-SAFFWQW4.js +5921 -0
- package/chunks/chunk-SF4KZ4O3.js +502 -0
- package/chunks/chunk-SVJEDVYK.js +808 -0
- package/chunks/chunk-TSK2AG6J.js +5108 -0
- package/chunks/chunk-U5FLXGHT.js +2010 -0
- package/chunks/chunk-UCYRA73C.js +662 -0
- package/chunks/chunk-UR4ELX2Y.js +4784 -0
- package/chunks/chunk-VQG4FT5D.js +685 -0
- package/chunks/chunk-WEBMRWEG.js +9337 -0
- package/chunks/chunk-WU6AFRAZ.js +1167 -0
- package/chunks/chunk-WVTBZEQO.js +1531 -0
- package/chunks/chunk-WXQ6BJ6A.js +596 -0
- package/chunks/chunk-XM5NLHYU.js +600 -0
- package/chunks/chunk-YLMN3N25.js +4054 -0
- package/chunks/chunk-YYRBQVFE.js +2572 -0
- package/chunks/chunk-Z5FA2XOX.js +2798 -0
- package/chunks/commands-TBC2F5CE.js +16999 -0
- package/chunks/corpus-v1.json +403 -0
- package/chunks/cost-ledger-NU63MYZM.js +13 -0
- package/chunks/data/appsec-archetypes.json +102 -0
- package/chunks/data/chromium-archetypes.json +204 -0
- package/chunks/data/freebsd-archetypes.json +171 -0
- package/chunks/data/kernel-archetypes.json +611 -0
- package/chunks/db-KFWOAUUB.js +16 -0
- package/chunks/disclose-EKTWSCGW.js +132 -0
- package/chunks/dist-4MAW5X6L.js +74 -0
- package/chunks/dist-4YICS2J2.js +2776 -0
- package/chunks/dist-FMGSR3DW.js +159 -0
- package/chunks/eval-runner-7ZF472KV.js +27 -0
- package/chunks/example-manifest.json +95 -0
- package/chunks/exploit-agent-45YQOHPJ.js +98 -0
- package/chunks/exploit-autoclimb-UZGEMGYT.js +81 -0
- package/chunks/exploit-climb-SG23KB2G.js +358 -0
- package/chunks/fix-IG7LYXH3.js +12 -0
- package/chunks/github-issues-MJ6OYOOU.js +157 -0
- package/chunks/harness-7ODOLOWU.js +22 -0
- package/chunks/http-conformance-DU66MZIU.js +11 -0
- package/chunks/http-sender-GWH2IYEA.js +10 -0
- package/chunks/hunt-scan-MMKUOETU.js +38 -0
- package/chunks/identity-6ZAIIWOR.js +191 -0
- package/chunks/kernel-primitive-7U6CWHXD.js +44 -0
- package/chunks/kernel-vm-runner-3JAU4O6J.js +62 -0
- package/chunks/memsafety-scan-J7SECV5W.js +16 -0
- package/chunks/native-loop-RJCJPOUS.js +54 -0
- package/chunks/npm-detectors-KB5Y5ZFX.js +69 -0
- package/chunks/npm-dynamic-discovery-AHROOZDB.js +13 -0
- package/chunks/orchestrate-OC2VZN2X.js +62 -0
- package/chunks/pipeline-BZK5BLJR.js +14 -0
- package/chunks/pre-recon-cve-66EB6G4M.js +351 -0
- package/chunks/prepare-MYY743TK.js +13 -0
- package/chunks/process-LQRCS5OY.js +13 -0
- package/chunks/replay-runner-45G3VU7X.js +39 -0
- package/chunks/run-D56MPDKY.js +32716 -0
- package/chunks/runtime-G7YWIO3B.js +43 -0
- package/chunks/runtime-J7PLXZNM.js +12 -0
- package/chunks/scan-stream-FHI2FYZE.js +96 -0
- package/chunks/scope-BI7BF4ZY.js +18 -0
- package/chunks/session-store-GZ4A4KYT.js +28 -0
- package/chunks/source-files-PWRQR6LY.js +12 -0
- package/chunks/specdrift-WCLH6TTQ.js +19 -0
- package/chunks/variant-candidates-YERCYMPD.js +13 -0
- package/chunks/web-recon-prepass-JJGPEOLE.js +1148 -0
- package/dashboard/assets/0sec-icon-66SreztZ.gif +0 -0
- package/dashboard/assets/bot-yILPnRgD.js +1 -0
- package/dashboard/assets/chevron-down-BeDJ-Vka.js +1 -0
- package/dashboard/assets/circle-alert-BEnMBMT-.js +1 -0
- package/dashboard/assets/client-DRYsuOGl.js +9 -0
- package/dashboard/assets/copy-Bi5vzoF9.js +1 -0
- package/dashboard/assets/desktop-CXTQonNm.js +32 -0
- package/dashboard/assets/desktop-NOekk4QS.css +1 -0
- package/dashboard/assets/dist-CmX-h7a4.js +1 -0
- package/dashboard/assets/dist-DAwYQmf_.js +45 -0
- package/dashboard/assets/findings-page-CACW9nw2.js +5 -0
- package/dashboard/assets/format-PoISqsES.js +1 -0
- package/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
- package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
- package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
- package/dashboard/assets/jsx-runtime-C7oxC63R.js +1 -0
- package/dashboard/assets/live-page-DrgQqQK5.js +1 -0
- package/dashboard/assets/meta-tile-CcskIV_o.js +1 -0
- package/dashboard/assets/operations-BKE8T-vY.css +2 -0
- package/dashboard/assets/operations-D8nUP5_m.js +4 -0
- package/dashboard/assets/operations-app-CQQhG54n.js +2 -0
- package/dashboard/assets/overview-page-DTGS8dPo.js +1 -0
- package/dashboard/assets/page-header-MFVvEtZW.js +1 -0
- package/dashboard/assets/play-Dwo-9xt6.js +1 -0
- package/dashboard/assets/scans-page-ChVtq8Us.js +1 -0
- package/dashboard/assets/search-CiooTLck.js +1 -0
- package/dashboard/assets/siren-CCBwTSuk.js +1 -0
- package/dashboard/assets/table-BYS-nIVA.js +1 -0
- package/dashboard/assets/tabs-DivxbhQy.js +1 -0
- package/dashboard/desktop.html +21 -0
- package/dashboard/index.html +15 -0
- package/package.json +30 -18
- package/bin/0sec.cjs +0 -361
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __0secCreateRequire } from "node:module";
|
|
3
|
+
const require = __0secCreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
homeStateDir
|
|
6
|
+
} from "./chunk-6L26OBWI.js";
|
|
7
|
+
|
|
8
|
+
// packages/cli/src/tui/session-store.ts
|
|
9
|
+
import { chmodSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
var SESSIONS_DIRNAME = "console-sessions";
|
|
12
|
+
var FILE_MODE = 384;
|
|
13
|
+
var DIR_MODE = 448;
|
|
14
|
+
var DEFAULT_PRUNE_KEEP = 20;
|
|
15
|
+
var PREVIEW_MAX_LENGTH = 120;
|
|
16
|
+
var SUMMARY_MAX_LENGTH = 120;
|
|
17
|
+
var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
18
|
+
var FILE_SUFFIX = ".json";
|
|
19
|
+
function sessionsDir(homeDir) {
|
|
20
|
+
return join(homeStateDir(homeDir), SESSIONS_DIRNAME);
|
|
21
|
+
}
|
|
22
|
+
function isValidSessionId(id) {
|
|
23
|
+
return typeof id === "string" && SESSION_ID_PATTERN.test(id);
|
|
24
|
+
}
|
|
25
|
+
function sessionFilePath(id, homeDir) {
|
|
26
|
+
if (!isValidSessionId(id)) return null;
|
|
27
|
+
return join(sessionsDir(homeDir), `${id}${FILE_SUFFIX}`);
|
|
28
|
+
}
|
|
29
|
+
function rawValue(raw, key) {
|
|
30
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
31
|
+
return raw[key];
|
|
32
|
+
}
|
|
33
|
+
function optionalString(raw, key) {
|
|
34
|
+
const value = rawValue(raw, key);
|
|
35
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
36
|
+
}
|
|
37
|
+
var CONTROL_CHARS = /[\u0000-\u001F\u007F-\u009F]+/g;
|
|
38
|
+
function sanitizeLine(value, maxLength) {
|
|
39
|
+
if (typeof value !== "string") return "";
|
|
40
|
+
const flattened = value.replace(CONTROL_CHARS, " ").replace(/\s+/g, " ").trim();
|
|
41
|
+
return flattened.length > maxLength ? `${flattened.slice(0, maxLength - 1)}\u2026` : flattened;
|
|
42
|
+
}
|
|
43
|
+
function sanitizePreview(value) {
|
|
44
|
+
return sanitizeLine(value, PREVIEW_MAX_LENGTH);
|
|
45
|
+
}
|
|
46
|
+
function sanitizeSummary(value) {
|
|
47
|
+
const flattened = sanitizeLine(value, SUMMARY_MAX_LENGTH);
|
|
48
|
+
return flattened.length > 0 ? flattened : void 0;
|
|
49
|
+
}
|
|
50
|
+
function toMeta(id, raw, messageCount) {
|
|
51
|
+
const savedAt = rawValue(raw, "savedAt");
|
|
52
|
+
const cwd = rawValue(raw, "cwd");
|
|
53
|
+
const target = optionalString(raw, "target");
|
|
54
|
+
const model = optionalString(raw, "model");
|
|
55
|
+
const mode = optionalString(raw, "mode");
|
|
56
|
+
const summary = sanitizeSummary(rawValue(raw, "summary"));
|
|
57
|
+
return {
|
|
58
|
+
id,
|
|
59
|
+
savedAt: typeof savedAt === "number" && Number.isFinite(savedAt) ? savedAt : 0,
|
|
60
|
+
...target !== void 0 ? { target } : {},
|
|
61
|
+
...model !== void 0 ? { model } : {},
|
|
62
|
+
...mode !== void 0 ? { mode } : {},
|
|
63
|
+
cwd: typeof cwd === "string" ? cwd : "",
|
|
64
|
+
messageCount,
|
|
65
|
+
preview: sanitizePreview(rawValue(raw, "preview")),
|
|
66
|
+
...summary !== void 0 ? { summary } : {}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function parseSession(id, text) {
|
|
70
|
+
let raw;
|
|
71
|
+
try {
|
|
72
|
+
raw = JSON.parse(text);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const messages = rawValue(raw, "messages");
|
|
77
|
+
if (!Array.isArray(messages)) return null;
|
|
78
|
+
return { ...toMeta(id, raw, messages.length), messages };
|
|
79
|
+
}
|
|
80
|
+
function saveSession(session, homeDir) {
|
|
81
|
+
try {
|
|
82
|
+
if (!Array.isArray(session?.messages)) return false;
|
|
83
|
+
const path = sessionFilePath(session.id, homeDir);
|
|
84
|
+
if (path === null) return false;
|
|
85
|
+
const dir = sessionsDir(homeDir);
|
|
86
|
+
mkdirSync(dir, { recursive: true, mode: DIR_MODE });
|
|
87
|
+
chmodSync(dir, DIR_MODE);
|
|
88
|
+
const payload = {
|
|
89
|
+
...toMeta(session.id, session, session.messages.length),
|
|
90
|
+
messages: session.messages
|
|
91
|
+
};
|
|
92
|
+
writeFileSync(path, `${JSON.stringify(payload)}
|
|
93
|
+
`, { encoding: "utf8", mode: FILE_MODE });
|
|
94
|
+
chmodSync(path, FILE_MODE);
|
|
95
|
+
return true;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function listSessions(homeDir, opts) {
|
|
101
|
+
const dir = sessionsDir(homeDir);
|
|
102
|
+
let entries;
|
|
103
|
+
try {
|
|
104
|
+
entries = readdirSync(dir);
|
|
105
|
+
} catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
const out = [];
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (!entry.endsWith(FILE_SUFFIX)) continue;
|
|
111
|
+
const id = entry.slice(0, -FILE_SUFFIX.length);
|
|
112
|
+
if (!isValidSessionId(id)) continue;
|
|
113
|
+
let text;
|
|
114
|
+
try {
|
|
115
|
+
text = readFileSync(join(dir, entry), "utf8");
|
|
116
|
+
} catch {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const parsed = parseSession(id, text);
|
|
120
|
+
if (parsed === null) continue;
|
|
121
|
+
if (opts?.cwd !== void 0 && parsed.cwd !== opts.cwd) continue;
|
|
122
|
+
const { messages: _messages, ...meta } = parsed;
|
|
123
|
+
out.push(meta);
|
|
124
|
+
}
|
|
125
|
+
out.sort((a, b) => b.savedAt - a.savedAt || a.id.localeCompare(b.id));
|
|
126
|
+
const limit = opts?.limit;
|
|
127
|
+
if (typeof limit === "number" && Number.isFinite(limit)) {
|
|
128
|
+
return out.slice(0, Math.max(0, Math.floor(limit)));
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
var SECONDS_PER_MINUTE = 60;
|
|
133
|
+
var MINUTES_PER_HOUR = 60;
|
|
134
|
+
var HOURS_PER_DAY = 24;
|
|
135
|
+
var DAYS_PER_WEEK = 7;
|
|
136
|
+
var FUTURE_SKEW_MS = 6e4;
|
|
137
|
+
function relativeAge(savedAt, now) {
|
|
138
|
+
if (!Number.isFinite(savedAt) || savedAt <= 0) return "";
|
|
139
|
+
if (savedAt > now + FUTURE_SKEW_MS) return "";
|
|
140
|
+
const seconds = Math.max(0, Math.floor((now - savedAt) / 1e3));
|
|
141
|
+
if (seconds < SECONDS_PER_MINUTE) return `${seconds}s`;
|
|
142
|
+
const minutes = Math.floor(seconds / SECONDS_PER_MINUTE);
|
|
143
|
+
if (minutes < MINUTES_PER_HOUR) return `${minutes}m`;
|
|
144
|
+
const hours = Math.floor(minutes / MINUTES_PER_HOUR);
|
|
145
|
+
if (hours < HOURS_PER_DAY) return `${hours}h`;
|
|
146
|
+
const days = Math.floor(hours / HOURS_PER_DAY);
|
|
147
|
+
if (days < DAYS_PER_WEEK) return `${days}d`;
|
|
148
|
+
return `${Math.floor(days / DAYS_PER_WEEK)}w`;
|
|
149
|
+
}
|
|
150
|
+
function loadSession(id, homeDir) {
|
|
151
|
+
const path = sessionFilePath(id, homeDir);
|
|
152
|
+
if (path === null) return null;
|
|
153
|
+
try {
|
|
154
|
+
return parseSession(id, readFileSync(path, "utf8"));
|
|
155
|
+
} catch {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function deleteSession(id, homeDir, opts) {
|
|
160
|
+
if (opts?.protectedIds?.has(id)) return false;
|
|
161
|
+
const path = sessionFilePath(id, homeDir);
|
|
162
|
+
if (path === null) return false;
|
|
163
|
+
try {
|
|
164
|
+
rmSync(path, { force: false });
|
|
165
|
+
return true;
|
|
166
|
+
} catch {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function pruneSessions(homeDir, opts) {
|
|
171
|
+
const requested = opts?.keep;
|
|
172
|
+
const keep = typeof requested === "number" && Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_PRUNE_KEEP;
|
|
173
|
+
let removed = 0;
|
|
174
|
+
let archived = 0;
|
|
175
|
+
for (const meta of listSessions(homeDir)) {
|
|
176
|
+
if (opts?.protectedIds?.has(meta.id)) continue;
|
|
177
|
+
if (archived++ < keep) continue;
|
|
178
|
+
if (deleteSession(meta.id, homeDir, opts)) removed += 1;
|
|
179
|
+
}
|
|
180
|
+
return removed;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export {
|
|
184
|
+
DEFAULT_PRUNE_KEEP,
|
|
185
|
+
sessionsDir,
|
|
186
|
+
isValidSessionId,
|
|
187
|
+
saveSession,
|
|
188
|
+
listSessions,
|
|
189
|
+
relativeAge,
|
|
190
|
+
loadSession,
|
|
191
|
+
deleteSession,
|
|
192
|
+
pruneSessions
|
|
193
|
+
};
|