@phamvuhoang/otto-core 0.31.0 → 0.33.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/dist/compression-survival.d.ts +46 -0
- package/dist/compression-survival.d.ts.map +1 -0
- package/dist/compression-survival.js +81 -0
- package/dist/compression-survival.js.map +1 -0
- package/dist/context-compressor.d.ts +13 -2
- package/dist/context-compressor.d.ts.map +1 -1
- package/dist/context-compressor.js +43 -1
- package/dist/context-compressor.js.map +1 -1
- package/dist/extension-profiles.js +2 -2
- package/dist/extension-profiles.js.map +1 -1
- package/dist/headroom-adapter.d.ts +138 -27
- package/dist/headroom-adapter.d.ts.map +1 -1
- package/dist/headroom-adapter.js +335 -49
- package/dist/headroom-adapter.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +1 -1
- package/dist/inspect.js.map +1 -1
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +45 -7
- package/dist/loop.js.map +1 -1
- package/dist/plan-rubric.d.ts +1 -1
- package/dist/plan-rubric.d.ts.map +1 -1
- package/dist/plan-rubric.js +19 -0
- package/dist/plan-rubric.js.map +1 -1
- package/dist/report-finalize.d.ts.map +1 -1
- package/dist/report-finalize.js +4 -3
- package/dist/report-finalize.js.map +1 -1
- package/dist/run-bin.d.ts.map +1 -1
- package/dist/run-bin.js +5 -0
- package/dist/run-bin.js.map +1 -1
- package/dist/run-report.d.ts +4 -1
- package/dist/run-report.d.ts.map +1 -1
- package/dist/run-report.js.map +1 -1
- package/dist/stage-exec.d.ts.map +1 -1
- package/dist/stage-exec.js +5 -1
- package/dist/stage-exec.js.map +1 -1
- package/dist/verification-evidence.d.ts +4 -0
- package/dist/verification-evidence.d.ts.map +1 -1
- package/dist/verification-evidence.js +33 -4
- package/dist/verification-evidence.js.map +1 -1
- package/dist/verification-matrix.d.ts +31 -4
- package/dist/verification-matrix.d.ts.map +1 -1
- package/dist/verification-matrix.js +44 -5
- package/dist/verification-matrix.js.map +1 -1
- package/package.json +1 -1
- package/templates/plan.md +5 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fact-survival measurement for context compression (issue #179 P22).
|
|
3
|
+
*
|
|
4
|
+
* The roadmap gates trusting (and later expanding) Headroom compression on one
|
|
5
|
+
* condition: *"use Headroom selectively for `retrievable` categories where **eval
|
|
6
|
+
* proves buried facts survive compression**."* Compression (`context-compressor.ts`,
|
|
7
|
+
* `headroom-adapter.ts`) already shrinks retrievable content and measures the
|
|
8
|
+
* token savings — but token savings alone cannot tell you whether a specific
|
|
9
|
+
* load-bearing fact (an error code, a version, a file path) *survived* the
|
|
10
|
+
* summarization. This module answers that orthogonal question.
|
|
11
|
+
*
|
|
12
|
+
* Pure: it takes a known set of "buried facts" and the compressed text and
|
|
13
|
+
* reports which facts still appear. Evals score survival against facts they
|
|
14
|
+
* supply; the runtime keep-decision (`context-compressor.ts`, issue #200)
|
|
15
|
+
* scores it against anchors mechanically extracted from the original via
|
|
16
|
+
* {@link extractAnchors}, so a compression that drops a load-bearing
|
|
17
|
+
* identifier is rejected instead of used.
|
|
18
|
+
*/
|
|
19
|
+
/** The outcome of scoring a fact set against one piece of compressed text. */
|
|
20
|
+
export type FactSurvival = {
|
|
21
|
+
/** How many facts were checked. */
|
|
22
|
+
total: number;
|
|
23
|
+
/** How many facts still appear in the compressed text. */
|
|
24
|
+
survived: number;
|
|
25
|
+
/** `survived / total`, or `1` for an empty fact set (vacuously all survive). */
|
|
26
|
+
survivalRate: number;
|
|
27
|
+
/** The facts that did not appear, in input order. */
|
|
28
|
+
missing: string[];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Score how many `facts` survive in `compressedText`. A fact "survives" when it
|
|
32
|
+
* appears as a normalized (case-insensitive, whitespace-collapsed) substring —
|
|
33
|
+
* robust to a summarizer rephrasing *around* a distinctive identifier while still
|
|
34
|
+
* catching a token that is dropped entirely. Pure.
|
|
35
|
+
*/
|
|
36
|
+
export declare function assessFactSurvival(facts: string[], compressedText: string): FactSurvival;
|
|
37
|
+
/**
|
|
38
|
+
* Extract up to `limit` distinctive anchors from original text, deduplicated,
|
|
39
|
+
* in order of first appearance. The runtime survival floor checks these against
|
|
40
|
+
* the compressed text; an empty result means the text has no mechanically
|
|
41
|
+
* recognizable load-bearing tokens (survival is then vacuous). Pure.
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractAnchors(text: string, limit?: number): string[];
|
|
44
|
+
/** One-line human summary of a survival assessment for eval output. Pure. */
|
|
45
|
+
export declare function formatFactSurvival(s: FactSurvival): string;
|
|
46
|
+
//# sourceMappingURL=compression-survival.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression-survival.d.ts","sourceRoot":"","sources":["../src/compression-survival.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG;IACzB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,MAAM,GACrB,YAAY,CAUd;AAeD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,EAAE,CAcjE;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAG1D"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fact-survival measurement for context compression (issue #179 P22).
|
|
3
|
+
*
|
|
4
|
+
* The roadmap gates trusting (and later expanding) Headroom compression on one
|
|
5
|
+
* condition: *"use Headroom selectively for `retrievable` categories where **eval
|
|
6
|
+
* proves buried facts survive compression**."* Compression (`context-compressor.ts`,
|
|
7
|
+
* `headroom-adapter.ts`) already shrinks retrievable content and measures the
|
|
8
|
+
* token savings — but token savings alone cannot tell you whether a specific
|
|
9
|
+
* load-bearing fact (an error code, a version, a file path) *survived* the
|
|
10
|
+
* summarization. This module answers that orthogonal question.
|
|
11
|
+
*
|
|
12
|
+
* Pure: it takes a known set of "buried facts" and the compressed text and
|
|
13
|
+
* reports which facts still appear. Evals score survival against facts they
|
|
14
|
+
* supply; the runtime keep-decision (`context-compressor.ts`, issue #200)
|
|
15
|
+
* scores it against anchors mechanically extracted from the original via
|
|
16
|
+
* {@link extractAnchors}, so a compression that drops a load-bearing
|
|
17
|
+
* identifier is rejected instead of used.
|
|
18
|
+
*/
|
|
19
|
+
/** Lowercase + collapse internal whitespace + trim, so a summarizer that changes
|
|
20
|
+
* spacing/case around a salient token does not read as a dropped fact. */
|
|
21
|
+
function normalize(s) {
|
|
22
|
+
return s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Score how many `facts` survive in `compressedText`. A fact "survives" when it
|
|
26
|
+
* appears as a normalized (case-insensitive, whitespace-collapsed) substring —
|
|
27
|
+
* robust to a summarizer rephrasing *around* a distinctive identifier while still
|
|
28
|
+
* catching a token that is dropped entirely. Pure.
|
|
29
|
+
*/
|
|
30
|
+
export function assessFactSurvival(facts, compressedText) {
|
|
31
|
+
const haystack = normalize(compressedText);
|
|
32
|
+
const missing = facts.filter((f) => !haystack.includes(normalize(f)));
|
|
33
|
+
const survived = facts.length - missing.length;
|
|
34
|
+
return {
|
|
35
|
+
total: facts.length,
|
|
36
|
+
survived,
|
|
37
|
+
survivalRate: facts.length === 0 ? 1 : survived / facts.length,
|
|
38
|
+
missing,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The load-bearing token shapes a summarizer must not drop: slash file paths
|
|
43
|
+
* with an extension, uppercase identifier codes containing a digit or
|
|
44
|
+
* underscore (error codes, env keys — bare acronyms like `API` don't count),
|
|
45
|
+
* and version strings. Ordered by appearance so a capped list keeps the
|
|
46
|
+
* earliest (usually headline) anchors.
|
|
47
|
+
*/
|
|
48
|
+
const ANCHOR_PATTERNS = [
|
|
49
|
+
/\bv?\d+\.\d+(?:\.\d+)+\b/g,
|
|
50
|
+
/\b[\w-]+(?:\/[\w.-]+)*\/[\w-]+\.\w{1,8}\b/g,
|
|
51
|
+
/\b[A-Z][A-Z0-9]*[_0-9][A-Z0-9_]*\b/g,
|
|
52
|
+
];
|
|
53
|
+
/**
|
|
54
|
+
* Extract up to `limit` distinctive anchors from original text, deduplicated,
|
|
55
|
+
* in order of first appearance. The runtime survival floor checks these against
|
|
56
|
+
* the compressed text; an empty result means the text has no mechanically
|
|
57
|
+
* recognizable load-bearing tokens (survival is then vacuous). Pure.
|
|
58
|
+
*/
|
|
59
|
+
export function extractAnchors(text, limit = 12) {
|
|
60
|
+
const found = [];
|
|
61
|
+
for (const pattern of ANCHOR_PATTERNS) {
|
|
62
|
+
for (const m of text.matchAll(pattern)) {
|
|
63
|
+
found.push({ index: m.index ?? 0, value: m[0] });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
found.sort((a, b) => a.index - b.index);
|
|
67
|
+
const anchors = [];
|
|
68
|
+
for (const f of found) {
|
|
69
|
+
if (anchors.length >= limit)
|
|
70
|
+
break;
|
|
71
|
+
if (!anchors.includes(f.value))
|
|
72
|
+
anchors.push(f.value);
|
|
73
|
+
}
|
|
74
|
+
return anchors;
|
|
75
|
+
}
|
|
76
|
+
/** One-line human summary of a survival assessment for eval output. Pure. */
|
|
77
|
+
export function formatFactSurvival(s) {
|
|
78
|
+
const pct = Math.round(s.survivalRate * 100);
|
|
79
|
+
return `fact survival: ${s.survived}/${s.total} buried facts survived (${pct}%)`;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=compression-survival.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression-survival.js","sourceRoot":"","sources":["../src/compression-survival.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH;2EAC2E;AAC3E,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAe,EACf,cAAsB;IAEtB,MAAM,QAAQ,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/C,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,QAAQ;QACR,YAAY,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM;QAC9D,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,eAAe,GAAG;IACtB,2BAA2B;IAC3B,4CAA4C;IAC5C,qCAAqC;CACtC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAK,GAAG,EAAE;IACrD,MAAM,KAAK,GAAuC,EAAE,CAAC;IACrD,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;QACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC;IAC7C,OAAO,kBAAkB,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,2BAA2B,GAAG,IAAI,CAAC;AACnF,CAAC"}
|
|
@@ -32,7 +32,17 @@ export type CompressorMode = "off" | "headroom";
|
|
|
32
32
|
* The token-heavy content categories P7 already flags — the targets the roadmap
|
|
33
33
|
* names. Carried on each compression so a report can attribute savings by source.
|
|
34
34
|
*/
|
|
35
|
-
export
|
|
35
|
+
export declare const COMPRESSION_CATEGORIES: readonly ["issue-body", "command-log", "prior-iteration", "read-artifact", "memory-projection"];
|
|
36
|
+
export type CompressionCategory = (typeof COMPRESSION_CATEGORIES)[number];
|
|
37
|
+
/**
|
|
38
|
+
* Whether a category is authorized for live compression (issue #200). The
|
|
39
|
+
* roadmap scopes Headroom to the `retrievable` lifecycle class — today only
|
|
40
|
+
* `issue-body` (re-fetchable from the tracker). `command-log` diffs/patches
|
|
41
|
+
* feed the *current* decision (the reviewer reads `head.diff` line by line),
|
|
42
|
+
* and `read-artifact` is the unknown default bucket, so both stay verbatim.
|
|
43
|
+
* Pure.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isCompressibleCategory(category: CompressionCategory): boolean;
|
|
36
46
|
/** Content handed to the compressor, tagged by source category + a stable key. */
|
|
37
47
|
export type CompressInput = {
|
|
38
48
|
/** A run-unique key (used to name the retrieval artifact). */
|
|
@@ -133,7 +143,8 @@ export declare function compressContent(compressor: ContextCompressor | null, in
|
|
|
133
143
|
* Synchronous compression for the sync render/`@spill` path, where `renderTemplate`
|
|
134
144
|
* cannot await. Same reversible measurement and degrade rules as
|
|
135
145
|
* {@link compressContent}; backed by a {@link SyncContextCompressor} (the Headroom
|
|
136
|
-
*
|
|
146
|
+
* runner is synchronous — it drives `compress()` via a blocking subprocess).
|
|
147
|
+
* `compressor === null` → original verbatim.
|
|
137
148
|
*/
|
|
138
149
|
export declare function compressContentSync(compressor: SyncContextCompressor | null, input: CompressInput, store: RetrievalStore | null, now?: () => number): CompressOutput;
|
|
139
150
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-compressor.d.ts","sourceRoot":"","sources":["../src/context-compressor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context-compressor.d.ts","sourceRoot":"","sources":["../src/context-compressor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { assessFactSurvival, extractAnchors } from "./compression-survival.js";
|
|
3
4
|
import { estimateTokens } from "./context-report.js";
|
|
4
5
|
import { runReportDir } from "./run-report.js";
|
|
5
6
|
const MODES = new Set(["off", "headroom"]);
|
|
7
|
+
/**
|
|
8
|
+
* The token-heavy content categories P7 already flags — the targets the roadmap
|
|
9
|
+
* names. Carried on each compression so a report can attribute savings by source.
|
|
10
|
+
*/
|
|
11
|
+
export const COMPRESSION_CATEGORIES = [
|
|
12
|
+
"issue-body",
|
|
13
|
+
"command-log",
|
|
14
|
+
"prior-iteration",
|
|
15
|
+
"read-artifact",
|
|
16
|
+
"memory-projection",
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Whether a category is authorized for live compression (issue #200). The
|
|
20
|
+
* roadmap scopes Headroom to the `retrievable` lifecycle class — today only
|
|
21
|
+
* `issue-body` (re-fetchable from the tracker). `command-log` diffs/patches
|
|
22
|
+
* feed the *current* decision (the reviewer reads `head.diff` line by line),
|
|
23
|
+
* and `read-artifact` is the unknown default bucket, so both stay verbatim.
|
|
24
|
+
* Pure.
|
|
25
|
+
*/
|
|
26
|
+
export function isCompressibleCategory(category) {
|
|
27
|
+
return category === "issue-body";
|
|
28
|
+
}
|
|
6
29
|
/**
|
|
7
30
|
* Resolve the compressor mode from the flag/env/config precedence chain (flag >
|
|
8
31
|
* env > config > off). An unrecognized value resolves to `off`, so a typo never
|
|
@@ -52,6 +75,13 @@ export function runRetrievalStore(workspaceDir, runId) {
|
|
|
52
75
|
return join(".otto", "runs", runId, "compressed", `${safe}.orig`);
|
|
53
76
|
};
|
|
54
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Minimum share of extracted anchors that must survive for a compression to be
|
|
80
|
+
* kept. At the default 12-anchor cap this tolerates one dropped anchor —
|
|
81
|
+
* summarizers legitimately trim repetition, but losing more than that means
|
|
82
|
+
* load-bearing identifiers are being destroyed.
|
|
83
|
+
*/
|
|
84
|
+
const SURVIVAL_FLOOR = 0.9;
|
|
55
85
|
/**
|
|
56
86
|
* Turn a raw compression attempt into a measured {@link CompressOutput}, shared
|
|
57
87
|
* by the async ({@link compressContent}) and sync ({@link compressContentSync})
|
|
@@ -80,6 +110,17 @@ function assembleOutput(input, version, result, store, latencyMs) {
|
|
|
80
110
|
return passthrough(!result.ok, result.note ??
|
|
81
111
|
(result.ok ? "no token reduction — kept original" : undefined));
|
|
82
112
|
}
|
|
113
|
+
// Runtime fact-survival floor (issue #200): a compression that blanks the
|
|
114
|
+
// content or drops mechanically extracted load-bearing anchors (paths,
|
|
115
|
+
// identifier codes, versions) is rejected in favor of the original.
|
|
116
|
+
if (result.text.trim().length === 0) {
|
|
117
|
+
return passthrough(true, "blank compression result — kept original");
|
|
118
|
+
}
|
|
119
|
+
const survival = assessFactSurvival(extractAnchors(input.text), result.text);
|
|
120
|
+
if (survival.survivalRate < SURVIVAL_FLOOR) {
|
|
121
|
+
return passthrough(true, `survival floor: only ${survival.survived}/${survival.total} anchors ` +
|
|
122
|
+
`survived (missing: ${survival.missing.slice(0, 3).join(", ")}) — kept original`);
|
|
123
|
+
}
|
|
83
124
|
const retrievalHandle = store ? store(input.key, input.text) : undefined;
|
|
84
125
|
return {
|
|
85
126
|
text: result.text,
|
|
@@ -136,7 +177,8 @@ export async function compressContent(compressor, input, store, deps = {}) {
|
|
|
136
177
|
* Synchronous compression for the sync render/`@spill` path, where `renderTemplate`
|
|
137
178
|
* cannot await. Same reversible measurement and degrade rules as
|
|
138
179
|
* {@link compressContent}; backed by a {@link SyncContextCompressor} (the Headroom
|
|
139
|
-
*
|
|
180
|
+
* runner is synchronous — it drives `compress()` via a blocking subprocess).
|
|
181
|
+
* `compressor === null` → original verbatim.
|
|
140
182
|
*/
|
|
141
183
|
export function compressContentSync(compressor, input, store, now = Date.now) {
|
|
142
184
|
if (!compressor)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-compressor.js","sourceRoot":"","sources":["../src/context-compressor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAkC/C,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"context-compressor.js","sourceRoot":"","sources":["../src/context-compressor.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,8 +47,8 @@ const PROFILES = [
|
|
|
47
47
|
sources: [],
|
|
48
48
|
tools: [headroomToolDefinition()],
|
|
49
49
|
config: { contextCompressor: "headroom" },
|
|
50
|
-
requires: ["headroom"],
|
|
51
|
-
followUp: "Next: install the
|
|
50
|
+
requires: ["python3", "headroom-ai[ml]"],
|
|
51
|
+
followUp: "Next: pip install 'headroom-ai[ml]' (local Python lib — base is passthrough; no API key), pre-warm the model once, then otto-tools health.",
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
name: "security-review",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-profiles.js","sourceRoot":"","sources":["../src/extension-profiles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAsC/D;;;;GAIG;AACH,MAAM,eAAe,GAAG,QAAQ,CAAC;AACjC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAE/B,MAAM,QAAQ,GAAuB;IACnC;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,iFAAiF;QACnF,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,qCAAqC;gBAC/C,GAAG,EAAE,eAAe;aACrB;SACF;QACD,KAAK,EAAE,EAAE;QACT,4EAA4E;QAC5E,+EAA+E;QAC/E,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACpE,QAAQ,EAAE,CAAC,KAAK,CAAC;QACjB,QAAQ,EACN,wGAAwG;KAC3G;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,yFAAyF;QAC3F,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,sDAAsD;gBAChE,GAAG,EAAE,aAAa;aACnB;SACF;QACD,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC/D,QAAQ,EAAE,CAAC,KAAK,CAAC;QACjB,QAAQ,EACN,qFAAqF;KACxF;IACD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,mFAAmF;QACrF,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,CAAC,sBAAsB,EAAE,CAAC;QACjC,MAAM,EAAE,EAAE,iBAAiB,EAAE,UAAU,EAAE;QACzC,QAAQ,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"extension-profiles.js","sourceRoot":"","sources":["../src/extension-profiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +1,45 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
1
2
|
import type { CompressInput, ContextCompressor, SyncContextCompressor } from "./context-compressor.js";
|
|
2
|
-
import type {
|
|
3
|
+
import type { SafetyPolicy } from "./safety-policy.js";
|
|
4
|
+
import type { SafetyEvent } from "./run-report.js";
|
|
5
|
+
import type { ToolConfig, ToolDefinition } from "./tools.js";
|
|
3
6
|
/**
|
|
4
|
-
* Headroom adapter (issue #112 P20)
|
|
7
|
+
* Headroom adapter (issue #112 P20).
|
|
5
8
|
* [Headroom](https://github.com/headroomlabs-ai/headroom) compresses token-heavy
|
|
6
|
-
* content (tool outputs, logs, RAG chunks, files, history).
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the
|
|
9
|
+
* content (tool outputs, logs, RAG chunks, files, history). A
|
|
10
|
+
* {@link headroomToolDefinition} entry under `.otto/tools/` makes it
|
|
11
|
+
* `otto-tools list`/`health`-visible and governs it: {@link authorizeCompressor}
|
|
12
|
+
* honors the tool's `enabled` flag and authorizes its command against
|
|
13
|
+
* `.otto/policy.json`. It is **not** *stage*-gated, though — the compressor runs
|
|
14
|
+
* at the render boundary, not per stage ([#192](https://github.com/phamvuhoang/otto/issues/192)).
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* TypeScript library path slot in behind the same {@link ContextCompressor}
|
|
15
|
-
* interface without changing callers; proxy/wrapper mode stays an explicit
|
|
16
|
-
* advanced option because it alters provider transport.
|
|
16
|
+
* Otto drives Headroom's real `compress(messages, model)` library through a
|
|
17
|
+
* synchronous subprocess (the render/`@spill` boundary cannot await). Two runners
|
|
18
|
+
* sit behind one {@link HeadroomRunner} contract:
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
20
|
+
* - **library mode (default):** spawn `python3 -c <bridge>` calling
|
|
21
|
+
* `from headroom import compress` — Headroom's documented API (needs the
|
|
22
|
+
* `headroom-ai[ml]` extra; the base package leaves plain text unchanged).
|
|
23
|
+
* Inference is **local** with **no per-call API/cost** (`HEADROOM_MODEL` only
|
|
24
|
+
* selects the tokenizer), but the ML model is **downloaded once from Hugging
|
|
25
|
+
* Face** (~260–600 MB) on first use. Otto forces offline by default (no fetch);
|
|
26
|
+
* when you opt in ({@link authorizeCompressor} pre-authorizes the resolved
|
|
27
|
+
* endpoint against policy + declared domains, though it cannot intercept the
|
|
28
|
+
* subprocess's traffic), so pre-warm it (`HF_HUB_OFFLINE=0` / `HF_ENDPOINT`). The
|
|
29
|
+
* interpreter is overridable via `OTTO_HEADROOM_PYTHON`.
|
|
30
|
+
* - **command mode:** when `OTTO_HEADROOM_BIN` is set, shell out to that binary
|
|
31
|
+
* with `compress --category <c>` (stdin → compressed stdout) — an escape hatch
|
|
32
|
+
* for a custom compressor that already speaks this contract.
|
|
33
|
+
*
|
|
34
|
+
* {@link resolveHeadroomRunner} picks the mode. Everything is injectable (the
|
|
35
|
+
* runner and its `spawn`) so tests never spawn a real process, and a missing
|
|
36
|
+
* interpreter / library degrades cleanly (the compressor reports unavailable or
|
|
37
|
+
* `ok: false` and the orchestrator keeps the original content).
|
|
21
38
|
*/
|
|
22
|
-
/**
|
|
23
|
-
export declare const HEADROOM_VERSION = "headroom-
|
|
39
|
+
/** Compressor identity recorded on each compression (mode-agnostic). */
|
|
40
|
+
export declare const HEADROOM_VERSION = "headroom-1";
|
|
41
|
+
/** The injectable process spawner (defaults to `spawnSync`); tests pass a fake. */
|
|
42
|
+
type Spawn = typeof spawnSync;
|
|
24
43
|
/**
|
|
25
44
|
* The low-level transport the adapter drives. The default shells out to the
|
|
26
45
|
* `headroom` CLI; tests inject a double. `available` is the health probe;
|
|
@@ -35,12 +54,54 @@ export type HeadroomRunner = {
|
|
|
35
54
|
};
|
|
36
55
|
};
|
|
37
56
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
57
|
+
* Whether the compressor subprocess runs offline. Otto forces `HF_HUB_OFFLINE=1`
|
|
58
|
+
* by default (the runner injects `env.HF_HUB_OFFLINE ?? "1"`), and this MUST match
|
|
59
|
+
* Hugging Face's own parsing so {@link authorizeCompressor}'s "can it reach the
|
|
60
|
+
* network?" matches reality: HF treats only `1`/`true`/`yes`/`on` (case-insensitive)
|
|
61
|
+
* as offline — every other value (e.g. `maybe`) is **online**. Treating an
|
|
62
|
+
* unrecognized value as offline would skip policy authorization while the run
|
|
63
|
+
* actually went online.
|
|
64
|
+
*/
|
|
65
|
+
export declare function headroomOffline(env?: NodeJS.ProcessEnv): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* The network host(s) the ML model fetch would ACTUALLY reach, resolved from env
|
|
68
|
+
* like Hugging Face does: `HF_ENDPOINT` (its host) overrides the default HF hosts.
|
|
69
|
+
* Authorizing the resolved endpoint — not the static `tool.networkDomains` — closes
|
|
70
|
+
* the gap where `HF_ENDPOINT=https://evil.example` would slip past a policy that
|
|
71
|
+
* only allows `huggingface.co`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function headroomNetworkDomains(env?: NodeJS.ProcessEnv): string[];
|
|
74
|
+
/**
|
|
75
|
+
* The Python bridge driven in library mode: read the spill text on stdin, run it
|
|
76
|
+
* through Headroom's `compress(messages, model)`, and write the compressed text to
|
|
77
|
+
* stdout. Built line-by-line (Python is whitespace-sensitive) so it survives as a
|
|
78
|
+
* `python3 -c` argument. Exit codes are diagnostic only — any non-zero exit is a
|
|
79
|
+
* recoverable failure the orchestrator turns into a degraded passthrough:
|
|
80
|
+
* 2 = library not importable, 1 = compress() raised (e.g. weights not cached
|
|
81
|
+
* while offline), 3 = empty output (never blank out a non-empty spill).
|
|
82
|
+
*/
|
|
83
|
+
export declare const HEADROOM_BRIDGE: string;
|
|
84
|
+
/**
|
|
85
|
+
* Library-mode runner (default): probe {@link KOMPRESS_PROBE} for availability
|
|
86
|
+
* (Headroom's `is_kompress_available()` — the real ML backend, not just an import;
|
|
87
|
+
* base is passthrough-only), then run {@link HEADROOM_BRIDGE} per compression.
|
|
88
|
+
* Honors `OTTO_HEADROOM_PYTHON`; inference is local (no API key) and runs with
|
|
89
|
+
* `HF_HUB_OFFLINE=1` by default, so first use needs pre-cached model weights.
|
|
90
|
+
*/
|
|
91
|
+
export declare function libraryHeadroomRunner(env?: NodeJS.ProcessEnv, timeoutMs?: number, spawn?: Spawn): HeadroomRunner;
|
|
92
|
+
/**
|
|
93
|
+
* Command-mode runner: `<bin> --version` for availability, and
|
|
94
|
+
* `<bin> compress --category <c>` (content on stdin → compressed stdout) for one
|
|
95
|
+
* compression. Selected only when `OTTO_HEADROOM_BIN` is set — a custom compressor
|
|
96
|
+
* already speaking this contract. A non-zero exit / spawn error degrades cleanly.
|
|
42
97
|
*/
|
|
43
|
-
export declare function defaultHeadroomRunner(env?: NodeJS.ProcessEnv, timeoutMs?: number): HeadroomRunner;
|
|
98
|
+
export declare function defaultHeadroomRunner(env?: NodeJS.ProcessEnv, timeoutMs?: number, spawn?: Spawn): HeadroomRunner;
|
|
99
|
+
/**
|
|
100
|
+
* Pick the runner: command mode when `OTTO_HEADROOM_BIN` is set (custom binary),
|
|
101
|
+
* else library mode (Headroom's `compress()` via the Python bridge). The default
|
|
102
|
+
* for both compressor factories.
|
|
103
|
+
*/
|
|
104
|
+
export declare function resolveHeadroomRunner(env?: NodeJS.ProcessEnv, timeoutMs?: number, spawn?: Spawn): HeadroomRunner;
|
|
44
105
|
/**
|
|
45
106
|
* Build a {@link ContextCompressor} over a {@link HeadroomRunner}. Availability
|
|
46
107
|
* is cached per instance after the first probe so a run does not re-spawn
|
|
@@ -55,11 +116,61 @@ export declare function createHeadroomCompressor(runner?: HeadroomRunner): Conte
|
|
|
55
116
|
*/
|
|
56
117
|
export declare function createHeadroomSyncCompressor(runner?: HeadroomRunner): SyncContextCompressor;
|
|
57
118
|
/**
|
|
58
|
-
* The {@link ToolDefinition} a repo drops into `.otto/tools/headroom.json
|
|
59
|
-
* the
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
119
|
+
* The {@link ToolDefinition} a repo drops into `.otto/tools/headroom.json`. It is
|
|
120
|
+
* the registry/`otto-tools` surface and the governance hook ({@link
|
|
121
|
+
* authorizeCompressor} reads its `enabled` flag and authorizes its `command`
|
|
122
|
+
* against policy). `stages: []` is irrelevant to the compressor — it runs at the
|
|
123
|
+
* render boundary, not per stage — so it is NOT stage-gated. Returned as a value
|
|
124
|
+
* so `otto-extensions` (P21 `context-saver`) can generate it.
|
|
63
125
|
*/
|
|
64
126
|
export declare function headroomToolDefinition(): ToolDefinition;
|
|
127
|
+
/**
|
|
128
|
+
* Every command a run could ACTUALLY execute, resolved from env exactly as
|
|
129
|
+
* {@link resolveHeadroomRunner} does — so policy authorizes what runs, not a
|
|
130
|
+
* static placeholder (issue #192 part 2 follow-up). Command mode emits one entry
|
|
131
|
+
* **per category** (`<bin> compress --category <c>`), matching the real argv, so
|
|
132
|
+
* an argument-specific `blockedCommands` pattern (e.g. `--category command-log`)
|
|
133
|
+
* cannot slip past. Library mode is a single `<python> -c <bridge>` (the bridge
|
|
134
|
+
* text carries `headroom`, so a pattern can match the interpreter or the library).
|
|
135
|
+
*/
|
|
136
|
+
export declare function headroomCommands(env?: NodeJS.ProcessEnv): string[];
|
|
137
|
+
/** The compressor governance verdict (issue #192 part 2). */
|
|
138
|
+
export type CompressorAuthorization = {
|
|
139
|
+
allowed: boolean;
|
|
140
|
+
reason: string;
|
|
141
|
+
/** Blocked `policy-violation` events when a registered tool's command is denied. */
|
|
142
|
+
events: SafetyEvent[];
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Gate the compressor on tool-registry + policy authority (issue #192 part 2).
|
|
146
|
+
* The compressor is a render-boundary concern, not a per-stage tool, so it is NOT
|
|
147
|
+
* stage-gated (a registered `headroom` tool's `stages: []` is irrelevant here).
|
|
148
|
+
* But when a repo registers the `headroom` tool, the registry and policy DO govern
|
|
149
|
+
* it:
|
|
150
|
+
*
|
|
151
|
+
* - no `headroom` tool registered → the **built-in** {@link headroomToolDefinition}
|
|
152
|
+
* is used for the policy checks (the compressor is enabled by flag/config, not the
|
|
153
|
+
* registry, so a flag/config-only run must still be pre-authorized). A bare repo
|
|
154
|
+
* under `DEFAULT_POLICY` still passes; a restrictive policy still gates it;
|
|
155
|
+
* - tool disabled (registry `enabled: false` or a config override) → denied;
|
|
156
|
+
* - any command that WOULD RUN ({@link headroomCommands}, resolved from `env` like
|
|
157
|
+
* the runtime — one per category in command mode, with `--category <c>`) blocked
|
|
158
|
+
* by `.otto/policy.json` → denied, with the blocked {@link SafetyEvent}s for the
|
|
159
|
+
* evidence bundle. Authorizing the resolved commands (not the static
|
|
160
|
+
* `tool.command`) closes the gap where `OTTO_HEADROOM_BIN` pointed at a
|
|
161
|
+
* policy-blocked binary, or an argument-specific pattern, that authorization
|
|
162
|
+
* never saw;
|
|
163
|
+
* - in **library mode** only, when the run is **not** offline (the user set an
|
|
164
|
+
* online `HF_HUB_OFFLINE`, opting into the in-run model download), the **resolved**
|
|
165
|
+
* endpoint ({@link headroomNetworkDomains}, honoring `HF_ENDPOINT`) is authorized
|
|
166
|
+
* against the repo's `allowedNetworkDomains` — so a network-restricted repo denies
|
|
167
|
+
* the compressor rather than letting it reach an ungoverned host. Offline (the
|
|
168
|
+
* default) reaches no network; command mode (a custom `OTTO_HEADROOM_BIN`) does
|
|
169
|
+
* not use the Python library, so neither triggers the HF check.
|
|
170
|
+
*
|
|
171
|
+
* Pure: the registry, config, policy, and `env` are injected (the loop passes the
|
|
172
|
+
* process env). Default policy + no override always allows.
|
|
173
|
+
*/
|
|
174
|
+
export declare function authorizeCompressor(tools: ToolDefinition[], config: ToolConfig, policy: SafetyPolicy, env?: NodeJS.ProcessEnv): CompressorAuthorization;
|
|
175
|
+
export {};
|
|
65
176
|
//# sourceMappingURL=headroom-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headroom-adapter.d.ts","sourceRoot":"","sources":["../src/headroom-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headroom-adapter.d.ts","sourceRoot":"","sources":["../src/headroom-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C,mFAAmF;AACnF,KAAK,KAAK,GAAG,OAAO,SAAS,CAAC;AAE9B;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E,CAAC;AA4BF;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAG7E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAUV;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,QA2BhB,CAAC;AAmBb;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,SAAS,EAClB,KAAK,GAAE,KAAiB,GACvB,cAAc,CA2ChB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,SAAS,EAClB,KAAK,GAAE,KAAiB,GACvB,cAAc,CAqBhB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,SAAS,EAClB,KAAK,GAAE,KAAiB,GACvB,cAAc,CAKhB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,GAAE,cAAwC,GAC/C,iBAAiB,CAWnB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,GAAE,cAAwC,GAC/C,qBAAqB,CAOvB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,cAAc,CAqCvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAMV;AAED,6DAA6D;AAC7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,YAAY,EACpB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,uBAAuB,CA2DzB"}
|