theokit 0.65.0-next.3 → 0.65.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js
CHANGED
|
@@ -90,7 +90,7 @@ cli.command(
|
|
|
90
90
|
});
|
|
91
91
|
cli.command("agent sessions gc", "Collect old transcripts for this project (dry run unless --apply)").option("--apply", "Actually delete. Without it the command prints the plan and changes nothing.").option("--keep-last <n>", "Newest N sessions always survive (floor 1)", { default: 10 }).option("--max-age-days <n>", "Only sessions older than this may go (floor 1)", { default: 30 }).action(async (options) => {
|
|
92
92
|
try {
|
|
93
|
-
const { sessionsGcCommand } = await import("../sessions-gc-
|
|
93
|
+
const { sessionsGcCommand } = await import("../sessions-gc-P4HYEUBR.js");
|
|
94
94
|
const { lines, failed } = await sessionsGcCommand({
|
|
95
95
|
apply: options.apply,
|
|
96
96
|
keepLast: Number(options.keepLast),
|
|
@@ -6,19 +6,28 @@ import { planTranscriptGC, runTranscriptGC } from "@theokit/agents/session";
|
|
|
6
6
|
var DEFAULTS = { keepLast: 10, maxAgeDays: 30 };
|
|
7
7
|
function formatGcPlan(plan, result) {
|
|
8
8
|
const lines = [result.dryRun ? " Dry run \u2014 nothing was deleted." : " Applied.", ""];
|
|
9
|
-
if (result.removed.length === 0) {
|
|
9
|
+
if (result.removed.length === 0 && result.orphaned.length === 0) {
|
|
10
10
|
lines.push(" Nothing to collect.");
|
|
11
|
-
}
|
|
11
|
+
}
|
|
12
|
+
if (result.removed.length > 0) {
|
|
12
13
|
lines.push(` ${result.dryRun ? "Would remove" : "Removed"} ${String(result.removed.length)}:`);
|
|
13
14
|
for (const id of result.removed) lines.push(` - ${id}`);
|
|
14
15
|
}
|
|
16
|
+
if (result.orphaned.length > 0) {
|
|
17
|
+
lines.push(
|
|
18
|
+
` ${result.dryRun ? "Would remove" : "Removed"} ${String(result.orphaned.length)} with no readable session id:`
|
|
19
|
+
);
|
|
20
|
+
for (const path of result.orphaned) lines.push(` - ${path}`);
|
|
21
|
+
}
|
|
15
22
|
if (plan.kept.length > 0) {
|
|
16
23
|
lines.push("", ` Kept ${String(plan.kept.length)}:`);
|
|
17
|
-
for (const keep of plan.kept)
|
|
24
|
+
for (const keep of plan.kept)
|
|
25
|
+
lines.push(` - ${keep.id ?? "(id unreadable)"} \u2014 ${keep.reason}`);
|
|
18
26
|
}
|
|
19
27
|
if (result.errors.length > 0) {
|
|
20
28
|
lines.push("", ` ${String(result.errors.length)} failed (the rest still ran):`);
|
|
21
|
-
for (const error of result.errors)
|
|
29
|
+
for (const error of result.errors)
|
|
30
|
+
lines.push(` \u2717 ${error.id ?? "(id unreadable)"} \u2014 ${error.message}`);
|
|
22
31
|
}
|
|
23
32
|
return lines;
|
|
24
33
|
}
|
|
@@ -35,4 +44,4 @@ export {
|
|
|
35
44
|
formatGcPlan,
|
|
36
45
|
sessionsGcCommand
|
|
37
46
|
};
|
|
38
|
-
//# sourceMappingURL=sessions-gc-
|
|
47
|
+
//# sourceMappingURL=sessions-gc-P4HYEUBR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/sessions-gc.ts"],"sourcesContent":["import { planTranscriptGC, runTranscriptGC } from '@theokit/agents/session'\nimport type { TranscriptGCPlan } from '@theokit/agents/session'\n\n/**\n * M72 — `theokit agent sessions gc`: bound the disk state the framework creates.\n *\n * ## Why the default is a dry run\n *\n * This deletes conversation history. Without `--apply` the command PRINTS the plan and changes\n * nothing, because a destructive retention policy an operator has never seen the output of is a\n * policy nobody reviewed. Making `--apply` the default would save one flag and cost the review.\n *\n * The plan is printed in both modes, not just the dry one: an operator applying a policy still needs\n * to see what it decided, and \"removed 12 sessions\" without which ones is a report nobody can act\n * on.\n */\n\n/**\n * Not exported: its only consumer is the signature below, in this same file.\n *\n * Publishing it would put a name in the package surface that nobody imports — the G7 shape knip\n * caught in M76. When a caller needs to hold these options in a typed variable, exporting it then is\n * one line; exporting it now is a promise to keep a name stable for an audience that does not exist.\n */\ninterface SessionsGcOptions {\n /** Actually delete. Absent ⇒ dry run. */\n readonly apply?: boolean\n /** Newest N sessions always survive (floor 1). */\n readonly keepLast?: number\n /** Only sessions older than this may go (floor 1). */\n readonly maxAgeDays?: number\n /** Where to collect. Defaults to the process cwd — the project the operator is standing in. */\n readonly cwd?: string\n}\n\n/** Defaults chosen to be boring: a month of history, never fewer than ten sessions. */\nconst DEFAULTS = { keepLast: 10, maxAgeDays: 30 } as const\n\n/** Render the plan for a human. Returns lines so the command is testable without capturing stdout. */\nexport function formatGcPlan(\n plan: TranscriptGCPlan,\n // `Awaited<>` because `runTranscriptGC` is async (T2.2). Without it the parameter type IS the\n // Promise, and every field read below type-checks against a thenable that has none of them.\n result: Awaited<ReturnType<typeof runTranscriptGC>>,\n): string[] {\n const lines: string[] = [result.dryRun ? ' Dry run — nothing was deleted.' : ' Applied.', '']\n\n if (result.removed.length === 0 && result.orphaned.length === 0) {\n lines.push(' Nothing to collect.')\n }\n if (result.removed.length > 0) {\n lines.push(` ${result.dryRun ? 'Would remove' : 'Removed'} ${String(result.removed.length)}:`)\n for (const id of result.removed) lines.push(` - ${id}`)\n }\n // Reported separately and by PATH, because these have no session id to print — the transcript\n // could not be read. Folding them into the count above would say a number of sessions were\n // collected while naming fewer, and printing a filename in the id column would put back the\n // fabricated identity #668 removed. An operator who sees one of these knows a registry entry may\n // have outlived its transcript, which is the fact worth acting on.\n if (result.orphaned.length > 0) {\n lines.push(\n ` ${result.dryRun ? 'Would remove' : 'Removed'} ${String(result.orphaned.length)} with no readable session id:`,\n )\n for (const path of result.orphaned) lines.push(` - ${path}`)\n }\n\n // The kept list carries the REASON per session. \"Skipped 4\" tells an operator nothing; \"kept\n // because it holds an active writer lease\" tells them whether to go stop something.\n if (plan.kept.length > 0) {\n lines.push('', ` Kept ${String(plan.kept.length)}:`)\n for (const keep of plan.kept)\n lines.push(` - ${keep.id ?? '(id unreadable)'} — ${keep.reason}`)\n }\n\n if (result.errors.length > 0) {\n lines.push('', ` ${String(result.errors.length)} failed (the rest still ran):`)\n for (const error of result.errors)\n lines.push(` ✗ ${error.id ?? '(id unreadable)'} — ${error.message}`)\n }\n\n return lines\n}\n\n/**\n * Plan and (optionally) apply transcript retention for one project.\n *\n * Returns the result so a caller can decide the exit code: a partial failure is reported, never\n * swallowed into a zero exit.\n */\nexport async function sessionsGcCommand(options: SessionsGcOptions = {}): Promise<{\n readonly lines: readonly string[]\n readonly failed: number\n}> {\n const plan = planTranscriptGC({\n cwd: options.cwd ?? process.cwd(),\n keepLast: options.keepLast ?? DEFAULTS.keepLast,\n maxAgeDays: options.maxAgeDays ?? DEFAULTS.maxAgeDays,\n })\n // AWAITED. T2.2 made this async and this caller was not updated; `result.removed` was then\n // `undefined` on a Promise and the command threw before printing anything. The workspace\n // typecheck missed it because `packages/agents/dist/session.d.ts` was a day older than the source\n // and still declared the synchronous return.\n const result = await runTranscriptGC(plan, { apply: options.apply === true })\n return { lines: formatGcPlan(plan, result), failed: result.errors.length }\n}\n"],"mappings":";;;;AAAA,SAAS,kBAAkB,uBAAuB;AAoClD,IAAM,WAAW,EAAE,UAAU,IAAI,YAAY,GAAG;AAGzC,SAAS,aACd,MAGA,QACU;AACV,QAAM,QAAkB,CAAC,OAAO,SAAS,0CAAqC,cAAc,EAAE;AAE9F,MAAI,OAAO,QAAQ,WAAW,KAAK,OAAO,SAAS,WAAW,GAAG;AAC/D,UAAM,KAAK,uBAAuB;AAAA,EACpC;AACA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,UAAM,KAAK,KAAK,OAAO,SAAS,iBAAiB,SAAS,IAAI,OAAO,OAAO,QAAQ,MAAM,CAAC,GAAG;AAC9F,eAAW,MAAM,OAAO,QAAS,OAAM,KAAK,SAAS,EAAE,EAAE;AAAA,EAC3D;AAMA,MAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,UAAM;AAAA,MACJ,KAAK,OAAO,SAAS,iBAAiB,SAAS,IAAI,OAAO,OAAO,SAAS,MAAM,CAAC;AAAA,IACnF;AACA,eAAW,QAAQ,OAAO,SAAU,OAAM,KAAK,SAAS,IAAI,EAAE;AAAA,EAChE;AAIA,MAAI,KAAK,KAAK,SAAS,GAAG;AACxB,UAAM,KAAK,IAAI,UAAU,OAAO,KAAK,KAAK,MAAM,CAAC,GAAG;AACpD,eAAW,QAAQ,KAAK;AACtB,YAAM,KAAK,SAAS,KAAK,MAAM,iBAAiB,WAAM,KAAK,MAAM,EAAE;AAAA,EACvE;AAEA,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,UAAM,KAAK,IAAI,KAAK,OAAO,OAAO,OAAO,MAAM,CAAC,+BAA+B;AAC/E,eAAW,SAAS,OAAO;AACzB,YAAM,KAAK,cAAS,MAAM,MAAM,iBAAiB,WAAM,MAAM,OAAO,EAAE;AAAA,EAC1E;AAEA,SAAO;AACT;AAQA,eAAsB,kBAAkB,UAA6B,CAAC,GAGnE;AACD,QAAM,OAAO,iBAAiB;AAAA,IAC5B,KAAK,QAAQ,OAAO,QAAQ,IAAI;AAAA,IAChC,UAAU,QAAQ,YAAY,SAAS;AAAA,IACvC,YAAY,QAAQ,cAAc,SAAS;AAAA,EAC7C,CAAC;AAKD,QAAM,SAAS,MAAM,gBAAgB,MAAM,EAAE,OAAO,QAAQ,UAAU,KAAK,CAAC;AAC5E,SAAO,EAAE,OAAO,aAAa,MAAM,MAAM,GAAG,QAAQ,OAAO,OAAO,OAAO;AAC3E;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theokit",
|
|
3
|
-
"version": "0.65.0-next.
|
|
3
|
+
"version": "0.65.0-next.4",
|
|
4
4
|
"description": "The TheoKit web framework — file-based routing, typed server surfaces, the Vite plugin, the CLI and the deploy adapters, around agents served from agents/*.ts.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -150,8 +150,8 @@
|
|
|
150
150
|
"tsx": "^4.22.4",
|
|
151
151
|
"typescript": "^5.9.3",
|
|
152
152
|
"vite": "^7.0.0",
|
|
153
|
-
"@theokit/agents": "^13.0.0-next.2",
|
|
154
153
|
"@theokit/http": "^2.1.0-next.0",
|
|
154
|
+
"@theokit/agents": "^13.0.0-next.3",
|
|
155
155
|
"@theokit/presenter": "^0.9.0-next.0"
|
|
156
156
|
},
|
|
157
157
|
"peerDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/sessions-gc.ts"],"sourcesContent":["import { planTranscriptGC, runTranscriptGC } from '@theokit/agents/session'\nimport type { TranscriptGCPlan } from '@theokit/agents/session'\n\n/**\n * M72 — `theokit agent sessions gc`: bound the disk state the framework creates.\n *\n * ## Why the default is a dry run\n *\n * This deletes conversation history. Without `--apply` the command PRINTS the plan and changes\n * nothing, because a destructive retention policy an operator has never seen the output of is a\n * policy nobody reviewed. Making `--apply` the default would save one flag and cost the review.\n *\n * The plan is printed in both modes, not just the dry one: an operator applying a policy still needs\n * to see what it decided, and \"removed 12 sessions\" without which ones is a report nobody can act\n * on.\n */\n\n/**\n * Not exported: its only consumer is the signature below, in this same file.\n *\n * Publishing it would put a name in the package surface that nobody imports — the G7 shape knip\n * caught in M76. When a caller needs to hold these options in a typed variable, exporting it then is\n * one line; exporting it now is a promise to keep a name stable for an audience that does not exist.\n */\ninterface SessionsGcOptions {\n /** Actually delete. Absent ⇒ dry run. */\n readonly apply?: boolean\n /** Newest N sessions always survive (floor 1). */\n readonly keepLast?: number\n /** Only sessions older than this may go (floor 1). */\n readonly maxAgeDays?: number\n /** Where to collect. Defaults to the process cwd — the project the operator is standing in. */\n readonly cwd?: string\n}\n\n/** Defaults chosen to be boring: a month of history, never fewer than ten sessions. */\nconst DEFAULTS = { keepLast: 10, maxAgeDays: 30 } as const\n\n/** Render the plan for a human. Returns lines so the command is testable without capturing stdout. */\nexport function formatGcPlan(\n plan: TranscriptGCPlan,\n // `Awaited<>` because `runTranscriptGC` is async (T2.2). Without it the parameter type IS the\n // Promise, and every field read below type-checks against a thenable that has none of them.\n result: Awaited<ReturnType<typeof runTranscriptGC>>,\n): string[] {\n const lines: string[] = [result.dryRun ? ' Dry run — nothing was deleted.' : ' Applied.', '']\n\n if (result.removed.length === 0) {\n lines.push(' Nothing to collect.')\n } else {\n lines.push(` ${result.dryRun ? 'Would remove' : 'Removed'} ${String(result.removed.length)}:`)\n for (const id of result.removed) lines.push(` - ${id}`)\n }\n\n // The kept list carries the REASON per session. \"Skipped 4\" tells an operator nothing; \"kept\n // because it holds an active writer lease\" tells them whether to go stop something.\n if (plan.kept.length > 0) {\n lines.push('', ` Kept ${String(plan.kept.length)}:`)\n for (const keep of plan.kept) lines.push(` - ${keep.id} — ${keep.reason}`)\n }\n\n if (result.errors.length > 0) {\n lines.push('', ` ${String(result.errors.length)} failed (the rest still ran):`)\n for (const error of result.errors) lines.push(` ✗ ${error.id} — ${error.message}`)\n }\n\n return lines\n}\n\n/**\n * Plan and (optionally) apply transcript retention for one project.\n *\n * Returns the result so a caller can decide the exit code: a partial failure is reported, never\n * swallowed into a zero exit.\n */\nexport async function sessionsGcCommand(options: SessionsGcOptions = {}): Promise<{\n readonly lines: readonly string[]\n readonly failed: number\n}> {\n const plan = planTranscriptGC({\n cwd: options.cwd ?? process.cwd(),\n keepLast: options.keepLast ?? DEFAULTS.keepLast,\n maxAgeDays: options.maxAgeDays ?? DEFAULTS.maxAgeDays,\n })\n // AWAITED. T2.2 made this async and this caller was not updated; `result.removed` was then\n // `undefined` on a Promise and the command threw before printing anything. The workspace\n // typecheck missed it because `packages/agents/dist/session.d.ts` was a day older than the source\n // and still declared the synchronous return.\n const result = await runTranscriptGC(plan, { apply: options.apply === true })\n return { lines: formatGcPlan(plan, result), failed: result.errors.length }\n}\n"],"mappings":";;;;AAAA,SAAS,kBAAkB,uBAAuB;AAoClD,IAAM,WAAW,EAAE,UAAU,IAAI,YAAY,GAAG;AAGzC,SAAS,aACd,MAGA,QACU;AACV,QAAM,QAAkB,CAAC,OAAO,SAAS,0CAAqC,cAAc,EAAE;AAE9F,MAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B,UAAM,KAAK,uBAAuB;AAAA,EACpC,OAAO;AACL,UAAM,KAAK,KAAK,OAAO,SAAS,iBAAiB,SAAS,IAAI,OAAO,OAAO,QAAQ,MAAM,CAAC,GAAG;AAC9F,eAAW,MAAM,OAAO,QAAS,OAAM,KAAK,SAAS,EAAE,EAAE;AAAA,EAC3D;AAIA,MAAI,KAAK,KAAK,SAAS,GAAG;AACxB,UAAM,KAAK,IAAI,UAAU,OAAO,KAAK,KAAK,MAAM,CAAC,GAAG;AACpD,eAAW,QAAQ,KAAK,KAAM,OAAM,KAAK,SAAS,KAAK,EAAE,WAAM,KAAK,MAAM,EAAE;AAAA,EAC9E;AAEA,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,UAAM,KAAK,IAAI,KAAK,OAAO,OAAO,OAAO,MAAM,CAAC,+BAA+B;AAC/E,eAAW,SAAS,OAAO,OAAQ,OAAM,KAAK,cAAS,MAAM,EAAE,WAAM,MAAM,OAAO,EAAE;AAAA,EACtF;AAEA,SAAO;AACT;AAQA,eAAsB,kBAAkB,UAA6B,CAAC,GAGnE;AACD,QAAM,OAAO,iBAAiB;AAAA,IAC5B,KAAK,QAAQ,OAAO,QAAQ,IAAI;AAAA,IAChC,UAAU,QAAQ,YAAY,SAAS;AAAA,IACvC,YAAY,QAAQ,cAAc,SAAS;AAAA,EAC7C,CAAC;AAKD,QAAM,SAAS,MAAM,gBAAgB,MAAM,EAAE,OAAO,QAAQ,UAAU,KAAK,CAAC;AAC5E,SAAO,EAAE,OAAO,aAAa,MAAM,MAAM,GAAG,QAAQ,OAAO,OAAO,OAAO;AAC3E;","names":[]}
|