@withtruing/companion 0.13.3 → 0.14.1
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 +24 -25
- package/dist/anthropic-output-schema.js +41 -0
- package/dist/api-key-caller.js +9 -2
- package/dist/claude-cli-caller.js +107 -8
- package/dist/cli.js +833 -206
- package/dist/codex-cli-caller.js +85 -14
- package/dist/config.js +177 -2
- package/dist/git-range.js +88 -46
- package/dist/http-client.js +107 -10
- package/dist/investigation-reader.js +12 -6
- package/dist/managed-repo.js +132 -0
- package/dist/observed-sources.js +132 -6
- package/dist/reader-result-contract.js +296 -2
- package/dist/repository-provider.js +608 -0
- package/dist/schema-entities.js +18 -18
- package/dist/service.js +7 -2
- package/dist/surface-mapper.js +53 -11
- package/dist/text-model.js +91 -8
- package/dist/whole-read/archive.js +196 -0
- package/dist/whole-read/checks.js +297 -0
- package/dist/whole-read/claims.js +196 -0
- package/dist/whole-read/coverage-ledger.js +51 -0
- package/dist/whole-read/decode.js +234 -0
- package/dist/whole-read/drafting.js +502 -0
- package/dist/whole-read/generated-rules.js +68 -0
- package/dist/whole-read/go-proof.js +255 -0
- package/dist/whole-read/grouping-prompt.js +19 -0
- package/dist/whole-read/grouping.js +247 -0
- package/dist/whole-read/identity.js +103 -0
- package/dist/whole-read/import-graph.js +293 -0
- package/dist/whole-read/inventory-collector.js +55 -0
- package/dist/whole-read/inventory-rules.js +141 -0
- package/dist/whole-read/lockfiles.js +947 -0
- package/dist/whole-read/notes.js +216 -0
- package/dist/whole-read/npm-proof.js +272 -0
- package/dist/whole-read/owner-decision-detectors.js +270 -0
- package/dist/whole-read/packing.js +612 -0
- package/dist/whole-read/pages.js +429 -0
- package/dist/whole-read/phase-policy.js +54 -0
- package/dist/whole-read/prd-build.js +279 -0
- package/dist/whole-read/prd-fidelity.js +14 -0
- package/dist/whole-read/python-proof.js +489 -0
- package/dist/whole-read/read-prompt.js +67 -0
- package/dist/whole-read/redaction.js +411 -0
- package/dist/whole-read/relationship-mapping.js +98 -0
- package/dist/whole-read/sanitize.js +266 -0
- package/dist/whole-read/secret-rules.js +26 -0
- package/dist/whole-read/structure.js +300 -0
- package/dist/whole-read/types.js +2 -0
- package/dist/whole-read-claims.js +12 -0
- package/dist/whole-read-git.js +340 -0
- package/dist/whole-read-pool.js +80 -0
- package/dist/whole-read-runner.js +945 -0
- package/dist/whole-read-shared-source.js +194 -0
- package/dist/whole-read-temp.js +479 -0
- package/package.json +8 -2
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
const continuation = (value) => value !== undefined && value >= 0x80 && value <= 0xbf;
|
|
2
|
+
function parseUtf8(bytes, startByte) {
|
|
3
|
+
const characterByteOffsets = [startByte];
|
|
4
|
+
const characterCodeUnitOffsets = [0];
|
|
5
|
+
let byte = startByte;
|
|
6
|
+
let codeUnit = 0;
|
|
7
|
+
while (byte < bytes.byteLength) {
|
|
8
|
+
const first = bytes[byte];
|
|
9
|
+
let width;
|
|
10
|
+
let codeUnits = 1;
|
|
11
|
+
if (first <= 0x7f)
|
|
12
|
+
width = 1;
|
|
13
|
+
else if (first >= 0xc2 && first <= 0xdf && continuation(bytes[byte + 1]))
|
|
14
|
+
width = 2;
|
|
15
|
+
else if (first === 0xe0 && (bytes[byte + 1] ?? 0) >= 0xa0 && (bytes[byte + 1] ?? 0) <= 0xbf
|
|
16
|
+
&& continuation(bytes[byte + 2]))
|
|
17
|
+
width = 3;
|
|
18
|
+
else if (first >= 0xe1 && first <= 0xec && continuation(bytes[byte + 1]) && continuation(bytes[byte + 2]))
|
|
19
|
+
width = 3;
|
|
20
|
+
else if (first === 0xed && (bytes[byte + 1] ?? 0) >= 0x80 && (bytes[byte + 1] ?? 0) <= 0x9f
|
|
21
|
+
&& continuation(bytes[byte + 2]))
|
|
22
|
+
width = 3;
|
|
23
|
+
else if (first >= 0xee && first <= 0xef && continuation(bytes[byte + 1]) && continuation(bytes[byte + 2]))
|
|
24
|
+
width = 3;
|
|
25
|
+
else if (first === 0xf0 && (bytes[byte + 1] ?? 0) >= 0x90 && (bytes[byte + 1] ?? 0) <= 0xbf
|
|
26
|
+
&& continuation(bytes[byte + 2]) && continuation(bytes[byte + 3])) {
|
|
27
|
+
width = 4;
|
|
28
|
+
codeUnits = 2;
|
|
29
|
+
}
|
|
30
|
+
else if (first >= 0xf1 && first <= 0xf3 && continuation(bytes[byte + 1])
|
|
31
|
+
&& continuation(bytes[byte + 2]) && continuation(bytes[byte + 3])) {
|
|
32
|
+
width = 4;
|
|
33
|
+
codeUnits = 2;
|
|
34
|
+
}
|
|
35
|
+
else if (first === 0xf4 && (bytes[byte + 1] ?? 0) >= 0x80 && (bytes[byte + 1] ?? 0) <= 0x8f
|
|
36
|
+
&& continuation(bytes[byte + 2]) && continuation(bytes[byte + 3])) {
|
|
37
|
+
width = 4;
|
|
38
|
+
codeUnits = 2;
|
|
39
|
+
}
|
|
40
|
+
else
|
|
41
|
+
return null;
|
|
42
|
+
byte += width;
|
|
43
|
+
codeUnit += codeUnits;
|
|
44
|
+
characterByteOffsets.push(byte);
|
|
45
|
+
characterCodeUnitOffsets.push(codeUnit);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
text: new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes.subarray(startByte)),
|
|
49
|
+
characterByteOffsets,
|
|
50
|
+
characterCodeUnitOffsets,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const readCodeUnit = (bytes, byte, littleEndian) => littleEndian
|
|
54
|
+
? bytes[byte] | (bytes[byte + 1] << 8)
|
|
55
|
+
: (bytes[byte] << 8) | bytes[byte + 1];
|
|
56
|
+
function parseUtf16(bytes, startByte, littleEndian) {
|
|
57
|
+
if ((bytes.byteLength - startByte) % 2 !== 0)
|
|
58
|
+
return null;
|
|
59
|
+
const characterByteOffsets = [startByte];
|
|
60
|
+
const characterCodeUnitOffsets = [0];
|
|
61
|
+
let byte = startByte;
|
|
62
|
+
let codeUnitOffset = 0;
|
|
63
|
+
while (byte < bytes.byteLength) {
|
|
64
|
+
const first = readCodeUnit(bytes, byte, littleEndian);
|
|
65
|
+
let width = 2;
|
|
66
|
+
let codeUnits = 1;
|
|
67
|
+
if (first >= 0xd800 && first <= 0xdbff) {
|
|
68
|
+
if (byte + 3 >= bytes.byteLength)
|
|
69
|
+
return null;
|
|
70
|
+
const second = readCodeUnit(bytes, byte + 2, littleEndian);
|
|
71
|
+
if (second < 0xdc00 || second > 0xdfff)
|
|
72
|
+
return null;
|
|
73
|
+
width = 4;
|
|
74
|
+
codeUnits = 2;
|
|
75
|
+
}
|
|
76
|
+
else if (first >= 0xdc00 && first <= 0xdfff)
|
|
77
|
+
return null;
|
|
78
|
+
byte += width;
|
|
79
|
+
codeUnitOffset += codeUnits;
|
|
80
|
+
characterByteOffsets.push(byte);
|
|
81
|
+
characterCodeUnitOffsets.push(codeUnitOffset);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
text: new TextDecoder(littleEndian ? 'utf-16le' : 'utf-16be', { fatal: true, ignoreBOM: true })
|
|
85
|
+
.decode(bytes.subarray(startByte)),
|
|
86
|
+
characterByteOffsets,
|
|
87
|
+
characterCodeUnitOffsets,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function linesFor(text, byteOffsets) {
|
|
91
|
+
if (text.length === 0)
|
|
92
|
+
return [];
|
|
93
|
+
const lines = [];
|
|
94
|
+
let lineStart = 0;
|
|
95
|
+
let character = 0;
|
|
96
|
+
let previousWasCr = false;
|
|
97
|
+
for (const value of text) {
|
|
98
|
+
if (value === '\n') {
|
|
99
|
+
const contentEnd = previousWasCr ? character - 1 : character;
|
|
100
|
+
lines.push({
|
|
101
|
+
lineNumber: lines.length + 1,
|
|
102
|
+
startCharacter: lineStart,
|
|
103
|
+
contentEndCharacter: contentEnd,
|
|
104
|
+
endCharacter: character + 1,
|
|
105
|
+
startByte: byteOffsets[lineStart],
|
|
106
|
+
contentEndByte: byteOffsets[contentEnd],
|
|
107
|
+
endByte: byteOffsets[character + 1],
|
|
108
|
+
});
|
|
109
|
+
lineStart = character + 1;
|
|
110
|
+
}
|
|
111
|
+
previousWasCr = value === '\r';
|
|
112
|
+
character += 1;
|
|
113
|
+
}
|
|
114
|
+
lines.push({
|
|
115
|
+
lineNumber: lines.length + 1,
|
|
116
|
+
startCharacter: lineStart,
|
|
117
|
+
contentEndCharacter: character,
|
|
118
|
+
endCharacter: character,
|
|
119
|
+
startByte: byteOffsets[lineStart],
|
|
120
|
+
contentEndByte: byteOffsets[character],
|
|
121
|
+
endByte: byteOffsets[character],
|
|
122
|
+
});
|
|
123
|
+
return lines;
|
|
124
|
+
}
|
|
125
|
+
const exactIndex = (offsets, byteOffset) => {
|
|
126
|
+
let low = 0;
|
|
127
|
+
let high = offsets.length - 1;
|
|
128
|
+
while (low <= high) {
|
|
129
|
+
const middle = (low + high) >>> 1;
|
|
130
|
+
const value = offsets[middle];
|
|
131
|
+
if (value === byteOffset)
|
|
132
|
+
return middle;
|
|
133
|
+
if (value < byteOffset)
|
|
134
|
+
low = middle + 1;
|
|
135
|
+
else
|
|
136
|
+
high = middle - 1;
|
|
137
|
+
}
|
|
138
|
+
return -1;
|
|
139
|
+
};
|
|
140
|
+
function mappingFor(parsed) {
|
|
141
|
+
const characterByteOffsets = parsed.characterByteOffsets;
|
|
142
|
+
const characterCodeUnitOffsets = parsed.characterCodeUnitOffsets;
|
|
143
|
+
const characterCount = characterByteOffsets.length - 1;
|
|
144
|
+
const firstByte = characterByteOffsets[0];
|
|
145
|
+
const lastByte = characterByteOffsets[characterCount];
|
|
146
|
+
const validCharacterOffset = (offset) => Number.isInteger(offset) && offset >= 0 && offset <= characterCount;
|
|
147
|
+
const byteOffsetAtCharacter = (characterOffset) => {
|
|
148
|
+
if (!validCharacterOffset(characterOffset))
|
|
149
|
+
throw new RangeError('character offset is outside decoded text');
|
|
150
|
+
return characterByteOffsets[characterOffset];
|
|
151
|
+
};
|
|
152
|
+
const characterOffsetAtByte = (byteOffset) => {
|
|
153
|
+
if (!Number.isInteger(byteOffset) || byteOffset < firstByte || byteOffset > lastByte) {
|
|
154
|
+
throw new RangeError('canonical byte offset is outside decoded text');
|
|
155
|
+
}
|
|
156
|
+
const characterOffset = exactIndex(characterByteOffsets, byteOffset);
|
|
157
|
+
if (characterOffset < 0)
|
|
158
|
+
throw new RangeError('canonical byte offset is inside an encoded character');
|
|
159
|
+
return characterOffset;
|
|
160
|
+
};
|
|
161
|
+
const canonicalSpanForCharacters = (startCharacter, endCharacter) => {
|
|
162
|
+
if (!validCharacterOffset(startCharacter) || !validCharacterOffset(endCharacter) || startCharacter > endCharacter) {
|
|
163
|
+
throw new RangeError('invalid character span');
|
|
164
|
+
}
|
|
165
|
+
return { startByte: characterByteOffsets[startCharacter], endByte: characterByteOffsets[endCharacter] };
|
|
166
|
+
};
|
|
167
|
+
const characterSpanForCanonicalBytes = (startByte, endByte) => {
|
|
168
|
+
if (startByte > endByte)
|
|
169
|
+
throw new RangeError('invalid canonical byte span');
|
|
170
|
+
return {
|
|
171
|
+
startCharacter: characterOffsetAtByte(startByte),
|
|
172
|
+
endCharacter: characterOffsetAtByte(endByte),
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
return {
|
|
176
|
+
canonicalByteOffsets: characterByteOffsets,
|
|
177
|
+
characterCodeUnitOffsets,
|
|
178
|
+
lines: linesFor(parsed.text, characterByteOffsets),
|
|
179
|
+
byteOffsetAtCharacter,
|
|
180
|
+
characterOffsetAtByte,
|
|
181
|
+
canonicalSpanForCharacters,
|
|
182
|
+
characterSpanForCanonicalBytes,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function successfulDecode(parsed, encoding, bom, canonicalByteLength) {
|
|
186
|
+
const mapping = mappingFor(parsed);
|
|
187
|
+
return {
|
|
188
|
+
status: 'decoded',
|
|
189
|
+
text: parsed.text,
|
|
190
|
+
encoding,
|
|
191
|
+
bom,
|
|
192
|
+
canonicalByteLength,
|
|
193
|
+
characterCount: parsed.characterByteOffsets.length - 1,
|
|
194
|
+
lineCount: mapping.lines.length,
|
|
195
|
+
mapping,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const startsWith = (bytes, prefix) => prefix.every((value, index) => bytes[index] === value);
|
|
199
|
+
/** Strictly decodes canonical blob bytes and retains their original byte positions. */
|
|
200
|
+
export function decodeCanonicalBlob(bytes) {
|
|
201
|
+
const canonicalByteLength = bytes.byteLength;
|
|
202
|
+
let encoding = null;
|
|
203
|
+
let bomLength = 0;
|
|
204
|
+
if (startsWith(bytes, [0xef, 0xbb, 0xbf])) {
|
|
205
|
+
encoding = 'utf8';
|
|
206
|
+
bomLength = 3;
|
|
207
|
+
}
|
|
208
|
+
else if (startsWith(bytes, [0xff, 0xfe])) {
|
|
209
|
+
encoding = 'utf16le';
|
|
210
|
+
bomLength = 2;
|
|
211
|
+
}
|
|
212
|
+
else if (startsWith(bytes, [0xfe, 0xff])) {
|
|
213
|
+
encoding = 'utf16be';
|
|
214
|
+
bomLength = 2;
|
|
215
|
+
}
|
|
216
|
+
if (encoding) {
|
|
217
|
+
const bom = { encoding, startByte: 0, endByte: bomLength };
|
|
218
|
+
const parsed = encoding === 'utf8'
|
|
219
|
+
? parseUtf8(bytes, bomLength)
|
|
220
|
+
: parseUtf16(bytes, bomLength, encoding === 'utf16le');
|
|
221
|
+
return parsed
|
|
222
|
+
? successfulDecode(parsed, encoding, bom, canonicalByteLength)
|
|
223
|
+
: { status: 'decode_failed', encoding, bom, canonicalByteLength };
|
|
224
|
+
}
|
|
225
|
+
const nulLimit = Math.min(8_000, canonicalByteLength);
|
|
226
|
+
for (let byte = 0; byte < nulLimit; byte += 1) {
|
|
227
|
+
if (bytes[byte] === 0)
|
|
228
|
+
return { status: 'nul_bytes', canonicalByteLength, firstNulByte: byte };
|
|
229
|
+
}
|
|
230
|
+
const parsed = parseUtf8(bytes, 0);
|
|
231
|
+
return parsed
|
|
232
|
+
? successfulDecode(parsed, 'utf8', null, canonicalByteLength)
|
|
233
|
+
: { status: 'unsupported_encoding', canonicalByteLength };
|
|
234
|
+
}
|