codex-overleaf-link 1.1.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/LICENSE +21 -0
- package/README.md +457 -0
- package/bin/codex-overleaf-link.mjs +223 -0
- package/extension/src/shared/agentTranscript.js +1175 -0
- package/extension/src/shared/auditRecords.js +568 -0
- package/extension/src/shared/compatibility.js +372 -0
- package/extension/src/shared/compileAdapter.js +176 -0
- package/extension/src/shared/governanceRules.js +252 -0
- package/extension/src/shared/i18n.js +565 -0
- package/extension/src/shared/models.js +106 -0
- package/extension/src/shared/otText.js +505 -0
- package/extension/src/shared/projectFiles.js +180 -0
- package/extension/src/shared/reviewing.js +99 -0
- package/extension/src/shared/sensitiveScan.js +116 -0
- package/extension/src/shared/sessionState.js +1084 -0
- package/extension/src/shared/staleGuard.js +150 -0
- package/extension/src/shared/storageDb.js +986 -0
- package/extension/src/shared/storageKeys.js +29 -0
- package/extension/src/shared/storageMigration.js +168 -0
- package/extension/src/shared/summary.js +248 -0
- package/extension/src/shared/undoOperations.js +369 -0
- package/native-host/src/codexArgs.js +43 -0
- package/native-host/src/codexHome.js +538 -0
- package/native-host/src/codexModels.js +247 -0
- package/native-host/src/codexPrompt.js +192 -0
- package/native-host/src/codexPromptAssembly.js +411 -0
- package/native-host/src/codexSessionRunner.js +1247 -0
- package/native-host/src/commandApproval.js +914 -0
- package/native-host/src/debugLog.js +78 -0
- package/native-host/src/diffEngine.js +247 -0
- package/native-host/src/index.js +132 -0
- package/native-host/src/launcher.js +81 -0
- package/native-host/src/localSkills.js +476 -0
- package/native-host/src/manifest.js +226 -0
- package/native-host/src/mirrorSensitiveScan.js +119 -0
- package/native-host/src/mirrorWorkspace.js +1019 -0
- package/native-host/src/nativeDoctor.js +826 -0
- package/native-host/src/nativeEnvironment.js +315 -0
- package/native-host/src/nativeHostPlatform.js +112 -0
- package/native-host/src/nativeMessaging.js +60 -0
- package/native-host/src/nativeQuotas.js +294 -0
- package/native-host/src/nativeResponseBudget.js +194 -0
- package/native-host/src/runtimeInstaller.js +357 -0
- package/native-host/src/taskRunner.js +3 -0
- package/native-host/src/taskRunnerRuntime.js +1083 -0
- package/native-host/src/textPatch.js +287 -0
- package/package.json +40 -0
- package/scripts/codex-json-agent.mjs +269 -0
- package/scripts/install-native-host.mjs +255 -0
- package/scripts/npm-package-files-v1.1.1.txt +52 -0
- package/scripts/uninstall-native-host.mjs +298 -0
- package/scripts/verify-npm-package.mjs +296 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
(function initAuditRecords(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafAuditRecords = factory();
|
|
6
|
+
}
|
|
7
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function auditRecordsFactory() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const MAX_SUMMARY_CHARS = 240;
|
|
11
|
+
const REDACTED_SECRET = '[REDACTED_SECRET]';
|
|
12
|
+
const SECRET_REDACTION_PATTERNS = [
|
|
13
|
+
/-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
|
|
14
|
+
/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi,
|
|
15
|
+
/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/g,
|
|
16
|
+
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
17
|
+
/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/gi,
|
|
18
|
+
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
19
|
+
/\b(?:sk|pk)-[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g,
|
|
20
|
+
/\b(?:api[_-]?key|token|password|passwd|secret)\b\s*[:=]\s*["']?[^"'\s,;]+["']?/gi
|
|
21
|
+
];
|
|
22
|
+
const CONTENT_LIKE_KEY_PATTERN = /^(stdout|stderr|output|commandOutput|raw|compileLog|diff|fullDiff|content|fileBody|text|body|message|prompt|task)$/i;
|
|
23
|
+
|
|
24
|
+
function buildAuditDraftRecord(input = {}) {
|
|
25
|
+
const now = new Date().toISOString();
|
|
26
|
+
return {
|
|
27
|
+
id: input.id || generateId('aud'),
|
|
28
|
+
projectId: redactSecretLikeText(stringField(input.projectId)),
|
|
29
|
+
sessionId: redactSecretLikeText(stringField(input.sessionId)),
|
|
30
|
+
turnId: redactSecretLikeText(stringField(input.turnId)),
|
|
31
|
+
createdAt: redactSecretLikeText(stringField(input.createdAt)) || now,
|
|
32
|
+
completedAt: '',
|
|
33
|
+
mode: redactSecretLikeText(stringField(input.mode)),
|
|
34
|
+
model: redactSecretLikeText(stringField(input.model)),
|
|
35
|
+
reasoningEffort: redactSecretLikeText(stringField(input.reasoningEffort)),
|
|
36
|
+
speedTier: redactSecretLikeText(stringField(input.speedTier)),
|
|
37
|
+
promptSummary: summarizePrompt(input.promptSummary || input.task || input.prompt),
|
|
38
|
+
focusFiles: normalizePathList(input.focusFiles),
|
|
39
|
+
selectedSkillIds: normalizeStringList(input.selectedSkillIds),
|
|
40
|
+
sensitiveFindings: normalizeSensitiveFindings(input.sensitiveFindings),
|
|
41
|
+
changedFiles: [],
|
|
42
|
+
diffSummary: normalizeDiffSummary(input.diffSummary),
|
|
43
|
+
blockedFiles: [],
|
|
44
|
+
appliedFiles: [],
|
|
45
|
+
skippedFiles: [],
|
|
46
|
+
resultStatus: 'draft',
|
|
47
|
+
saveVerification: normalizeObjectSummary(input.saveVerification)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function buildAuditFinalRecord(input = {}) {
|
|
52
|
+
const draft = input.draft && typeof input.draft === 'object' ? input.draft : {};
|
|
53
|
+
return Object.assign({}, draft, {
|
|
54
|
+
completedAt: stringField(input.completedAt) || new Date().toISOString(),
|
|
55
|
+
changedFiles: normalizeFileSummaries(input.changedFiles),
|
|
56
|
+
diffSummary: normalizeDiffSummary(input.diffSummary),
|
|
57
|
+
blockedFiles: normalizeFileSummaries(input.blockedFiles),
|
|
58
|
+
appliedFiles: normalizeFileSummaries(input.appliedFiles),
|
|
59
|
+
skippedFiles: normalizeFileSummaries(input.skippedFiles),
|
|
60
|
+
resultStatus: redactSecretLikeText(stringField(input.resultStatus)) || 'completed',
|
|
61
|
+
saveVerification: normalizeObjectSummary(input.saveVerification)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function buildDiagnosticBundle(input = {}) {
|
|
66
|
+
return {
|
|
67
|
+
createdAt: new Date().toISOString(),
|
|
68
|
+
compatibility: summarizeCompatibility(input.compatibility),
|
|
69
|
+
platform: summarizePlatform(input.platform),
|
|
70
|
+
nativeEnvironment: summarizeNativeEnvironment(input.nativeEnvironment),
|
|
71
|
+
mirror: summarizeMirror(input.mirror),
|
|
72
|
+
auditLogs: summarizeAuditLogList(input.auditLogs),
|
|
73
|
+
run: summarizeRun(input.run),
|
|
74
|
+
governance: summarizeGovernance(input.governance),
|
|
75
|
+
projectIdHash: hashString(stringField(input.projectId))
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function normalizeAuditLogRecord(input = {}) {
|
|
80
|
+
return {
|
|
81
|
+
id: redactSecretLikeText(stringField(input.id)) || generateId('aud'),
|
|
82
|
+
projectId: redactSecretLikeText(stringField(input.projectId)),
|
|
83
|
+
sessionId: redactSecretLikeText(stringField(input.sessionId)),
|
|
84
|
+
turnId: redactSecretLikeText(stringField(input.turnId)),
|
|
85
|
+
createdAt: redactSecretLikeText(stringField(input.createdAt)) || new Date().toISOString(),
|
|
86
|
+
completedAt: redactSecretLikeText(stringField(input.completedAt)),
|
|
87
|
+
mode: redactSecretLikeText(stringField(input.mode)),
|
|
88
|
+
model: redactSecretLikeText(stringField(input.model)),
|
|
89
|
+
reasoningEffort: redactSecretLikeText(stringField(input.reasoningEffort)),
|
|
90
|
+
speedTier: redactSecretLikeText(stringField(input.speedTier)),
|
|
91
|
+
promptSummary: summarizePrompt(input.promptSummary),
|
|
92
|
+
focusFiles: normalizePathList(input.focusFiles),
|
|
93
|
+
selectedSkillIds: normalizeStringList(input.selectedSkillIds),
|
|
94
|
+
sensitiveFindings: normalizeSensitiveFindings(input.sensitiveFindings),
|
|
95
|
+
changedFiles: normalizeFileSummaries(input.changedFiles),
|
|
96
|
+
diffSummary: normalizeDiffSummary(input.diffSummary),
|
|
97
|
+
blockedFiles: normalizeFileSummaries(input.blockedFiles),
|
|
98
|
+
appliedFiles: normalizeFileSummaries(input.appliedFiles),
|
|
99
|
+
skippedFiles: normalizeFileSummaries(input.skippedFiles),
|
|
100
|
+
resultStatus: redactSecretLikeText(stringField(input.resultStatus)) || 'draft',
|
|
101
|
+
saveVerification: normalizeObjectSummary(input.saveVerification)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function normalizeSensitiveFindings(findings) {
|
|
106
|
+
return (Array.isArray(findings) ? findings : []).map(finding => ({
|
|
107
|
+
detectorId: redactSecretLikeText(stringField(finding.detectorId)),
|
|
108
|
+
path: normalizePath(finding.path),
|
|
109
|
+
source: redactSecretLikeText(stringField(finding.source)),
|
|
110
|
+
preview: summarizePrompt(finding.preview)
|
|
111
|
+
})).map(removeEmptyFields);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function normalizeFileSummaries(files) {
|
|
115
|
+
return (Array.isArray(files) ? files : []).map(file => {
|
|
116
|
+
if (typeof file === 'string') {
|
|
117
|
+
return { path: normalizePath(file) };
|
|
118
|
+
}
|
|
119
|
+
return removeEmptyFields({
|
|
120
|
+
path: normalizePath(file && file.path),
|
|
121
|
+
destinationPath: normalizePath(file && file.destinationPath),
|
|
122
|
+
type: redactSecretLikeText(stringField(file && file.type)),
|
|
123
|
+
reason: redactSecretLikeText(stringField(file && file.reason)),
|
|
124
|
+
status: redactSecretLikeText(stringField(file && file.status)),
|
|
125
|
+
size: Number.isFinite(Number(file && file.size)) ? Number(file.size) : undefined
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function normalizeDiffSummary(summary = {}) {
|
|
131
|
+
const result = {};
|
|
132
|
+
for (const key of ['filesChanged', 'additions', 'deletions', 'binaryFilesChanged']) {
|
|
133
|
+
if (Object.prototype.hasOwnProperty.call(summary, key)) {
|
|
134
|
+
result[key] = nonNegativeInteger(summary[key]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function normalizeObjectSummary(value) {
|
|
141
|
+
if (!value || typeof value !== 'object') {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return summarizeVerificationObject(value);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function normalizeAuditLogList(records) {
|
|
148
|
+
return (Array.isArray(records) ? records : []).map(normalizeAuditLogRecord);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function summarizeCompatibility(compatibility = {}) {
|
|
152
|
+
const native = compatibility && typeof compatibility.native === 'object' ? compatibility.native : {};
|
|
153
|
+
return removeEmptySummaryFields({
|
|
154
|
+
status: redactSecretLikeText(stringField(compatibility.status)),
|
|
155
|
+
extensionVersion: redactSecretLikeText(stringField(compatibility.extensionVersion)),
|
|
156
|
+
extension: removeEmptySummaryFields({
|
|
157
|
+
version: redactSecretLikeText(stringField(compatibility.extension && compatibility.extension.version)),
|
|
158
|
+
protocolVersion: finiteNumber(compatibility.extension && compatibility.extension.protocolVersion)
|
|
159
|
+
}),
|
|
160
|
+
native: removeEmptySummaryFields({
|
|
161
|
+
status: redactSecretLikeText(stringField(native.status)),
|
|
162
|
+
version: redactSecretLikeText(stringField(native.version)),
|
|
163
|
+
protocolVersion: finiteNumber(native.protocolVersion),
|
|
164
|
+
minExtensionVersion: redactSecretLikeText(stringField(native.minExtensionVersion)),
|
|
165
|
+
supportedProtocol: summarizeProtocol(native.supportedProtocol)
|
|
166
|
+
}),
|
|
167
|
+
modelDiscovery: summarizeStatusObject(compatibility.modelDiscovery)
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function summarizeProtocol(protocol) {
|
|
172
|
+
if (!protocol || typeof protocol !== 'object') {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
return removeEmptySummaryFields({
|
|
176
|
+
min: finiteNumber(protocol.min),
|
|
177
|
+
max: finiteNumber(protocol.max)
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function summarizePlatform(platform = {}) {
|
|
182
|
+
return removeEmptySummaryFields({
|
|
183
|
+
status: redactSecretLikeText(stringField(platform.status)),
|
|
184
|
+
errorCode: redactSecretLikeText(stringField(platform.errorCode)),
|
|
185
|
+
host: redactSecretLikeText(stringField(platform.host)),
|
|
186
|
+
platform: redactSecretLikeText(stringField(platform.platform)),
|
|
187
|
+
os: redactSecretLikeText(stringField(platform.os)),
|
|
188
|
+
arch: redactSecretLikeText(stringField(platform.arch)),
|
|
189
|
+
version: redactSecretLikeText(stringField(platform.version)),
|
|
190
|
+
protocolVersion: finiteNumber(platform.protocolVersion)
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function summarizeNativeEnvironment(environment = {}) {
|
|
195
|
+
return removeEmptySummaryFields({
|
|
196
|
+
status: redactSecretLikeText(stringField(environment.status)),
|
|
197
|
+
errorCode: redactSecretLikeText(stringField(environment.errorCode)),
|
|
198
|
+
codex: summarizeCodexTool(environment.codex),
|
|
199
|
+
latex: summarizeLatexTools(environment.latex),
|
|
200
|
+
pathPreviewCount: Array.isArray(environment.pathPreview) ? environment.pathPreview.length : undefined
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function summarizeCodexTool(codex = {}) {
|
|
205
|
+
if (!codex || typeof codex !== 'object') {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
return removeEmptySummaryFields({
|
|
209
|
+
ok: typeof codex.ok === 'boolean' ? codex.ok : undefined,
|
|
210
|
+
pathPresent: typeof codex.path === 'string' && codex.path.trim().length > 0,
|
|
211
|
+
version: redactSecretLikeText(stringField(codex.version)),
|
|
212
|
+
errorCode: redactSecretLikeText(stringField(codex.errorCode)),
|
|
213
|
+
errorCategory: categorizeError(codex.errorCode || codex.message || codex.error)
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function summarizeLatexTools(latex = {}) {
|
|
218
|
+
if (!latex || typeof latex !== 'object') {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
const available = normalizeToolList(latex.available);
|
|
222
|
+
const missing = normalizeToolList(latex.missing);
|
|
223
|
+
const tools = summarizeToolAvailability(latex.tools);
|
|
224
|
+
return removeEmptySummaryFields({
|
|
225
|
+
ok: typeof latex.ok === 'boolean' ? latex.ok : undefined,
|
|
226
|
+
available,
|
|
227
|
+
missing,
|
|
228
|
+
availableCount: available.length || undefined,
|
|
229
|
+
missingCount: missing.length || undefined,
|
|
230
|
+
tools,
|
|
231
|
+
errorCode: redactSecretLikeText(stringField(latex.errorCode)),
|
|
232
|
+
errorCategory: categorizeError(latex.errorCode || latex.message || latex.error)
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function summarizeToolAvailability(tools) {
|
|
237
|
+
if (!tools || typeof tools !== 'object' || Array.isArray(tools)) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
const result = {};
|
|
241
|
+
for (const name of Object.keys(tools).sort()) {
|
|
242
|
+
const tool = normalizeToolName(name);
|
|
243
|
+
if (tool) {
|
|
244
|
+
result[tool] = Boolean(tools[name]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return removeEmptySummaryFields(result);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function summarizeMirror(mirror = {}) {
|
|
251
|
+
const files = Array.isArray(mirror.files) ? mirror.files : [];
|
|
252
|
+
const skippedFiles = Array.isArray(mirror.skippedFiles) ? mirror.skippedFiles : [];
|
|
253
|
+
return removeEmptySummaryFields({
|
|
254
|
+
status: redactSecretLikeText(stringField(mirror.status)),
|
|
255
|
+
rootStatus: redactSecretLikeText(stringField(mirror.rootStatus)),
|
|
256
|
+
fileCount: files.length || finiteNumber(mirror.fileCount),
|
|
257
|
+
skippedCount: skippedFiles.length || finiteNumber(mirror.skippedCount),
|
|
258
|
+
byteCount: finiteNumber(mirror.byteCount) || sumFileBytes(files),
|
|
259
|
+
skippedByteCount: finiteNumber(mirror.skippedByteCount) || sumFileBytes(skippedFiles),
|
|
260
|
+
binaryFileCount: countBinaryFiles(files),
|
|
261
|
+
errorCode: redactSecretLikeText(stringField(mirror.errorCode)),
|
|
262
|
+
errorCategory: categorizeError(mirror.errorCode || mirror.message || mirror.error)
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function summarizeRun(run = {}) {
|
|
267
|
+
return removeEmptySummaryFields({
|
|
268
|
+
id: redactSecretLikeText(stringField(run.id)),
|
|
269
|
+
status: redactSecretLikeText(stringField(run.status)),
|
|
270
|
+
errorCode: redactSecretLikeText(stringField(run.errorCode)),
|
|
271
|
+
errorCategory: categorizeError(run.errorCode || run.message || run.error),
|
|
272
|
+
events: (Array.isArray(run.events) ? run.events : []).map(event => removeEmptyFields({
|
|
273
|
+
titlePreview: summarizeRedactedPreview(event.title),
|
|
274
|
+
status: redactSecretLikeText(stringField(event.status)),
|
|
275
|
+
errorCode: redactSecretLikeText(stringField(event.errorCode)),
|
|
276
|
+
errorCategory: categorizeError(event.errorCode || event.message || event.error),
|
|
277
|
+
kind: redactSecretLikeText(stringField(event.kind))
|
|
278
|
+
}))
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function summarizeGovernance(rules = {}) {
|
|
283
|
+
return {
|
|
284
|
+
readonlyPatternCount: Array.isArray(rules.readonlyPatterns) ? rules.readonlyPatterns.length : 0,
|
|
285
|
+
writablePatternCount: Array.isArray(rules.writablePatterns) ? rules.writablePatterns.length : 0,
|
|
286
|
+
sensitiveCheckEnabled: rules.sensitiveCheckEnabled === true,
|
|
287
|
+
sensitiveConfirmAllowed: rules.sensitiveConfirmAllowed === true
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function summarizeAuditLogList(records) {
|
|
292
|
+
return (Array.isArray(records) ? records : []).map(summarizeAuditLogRecord);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function summarizeAuditLogRecord(input = {}) {
|
|
296
|
+
const record = normalizeAuditLogRecord(input);
|
|
297
|
+
const changedFiles = Array.isArray(record.changedFiles) ? record.changedFiles : [];
|
|
298
|
+
const blockedFiles = Array.isArray(record.blockedFiles) ? record.blockedFiles : [];
|
|
299
|
+
const appliedFiles = Array.isArray(record.appliedFiles) ? record.appliedFiles : [];
|
|
300
|
+
const skippedFiles = Array.isArray(record.skippedFiles) ? record.skippedFiles : [];
|
|
301
|
+
return removeEmptySummaryFields({
|
|
302
|
+
id: record.id,
|
|
303
|
+
sessionId: record.sessionId,
|
|
304
|
+
turnId: record.turnId,
|
|
305
|
+
createdAt: record.createdAt,
|
|
306
|
+
completedAt: record.completedAt,
|
|
307
|
+
mode: record.mode,
|
|
308
|
+
model: record.model,
|
|
309
|
+
reasoningEffort: record.reasoningEffort,
|
|
310
|
+
speedTier: record.speedTier,
|
|
311
|
+
promptPreview: summarizeRedactedPreview(input.promptSummary || input.task || input.prompt),
|
|
312
|
+
focusFileCount: Array.isArray(record.focusFiles) ? record.focusFiles.length : 0,
|
|
313
|
+
selectedSkillCount: Array.isArray(record.selectedSkillIds) ? record.selectedSkillIds.length : 0,
|
|
314
|
+
sensitiveFindingCount: Array.isArray(record.sensitiveFindings) ? record.sensitiveFindings.length : 0,
|
|
315
|
+
changedFileCount: changedFiles.length,
|
|
316
|
+
changedByteCount: sumFileBytes(changedFiles),
|
|
317
|
+
blockedFileCount: blockedFiles.length,
|
|
318
|
+
appliedFileCount: appliedFiles.length,
|
|
319
|
+
skippedFileCount: skippedFiles.length,
|
|
320
|
+
skippedByteCount: sumFileBytes(skippedFiles),
|
|
321
|
+
diffSummary: record.diffSummary,
|
|
322
|
+
resultStatus: record.resultStatus,
|
|
323
|
+
saveVerification: summarizeStatusObject(input.saveVerification)
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function redactContent(value) {
|
|
328
|
+
if (Array.isArray(value)) {
|
|
329
|
+
return value.map(redactContent);
|
|
330
|
+
}
|
|
331
|
+
if (typeof value === 'string') {
|
|
332
|
+
return redactSecretLikeText(value);
|
|
333
|
+
}
|
|
334
|
+
if (!value || typeof value !== 'object') {
|
|
335
|
+
return value;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const result = {};
|
|
339
|
+
for (const key of Object.keys(value)) {
|
|
340
|
+
if (isContentKey(key)) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
result[key] = redactContent(value[key]);
|
|
344
|
+
}
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function isContentKey(key) {
|
|
349
|
+
return CONTENT_LIKE_KEY_PATTERN.test(key);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function normalizePathList(paths) {
|
|
353
|
+
return normalizeStringList(paths).map(normalizePath);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function normalizePath(value) {
|
|
357
|
+
return redactSecretLikeText(stringField(value)).replace(/\\/g, '/').replace(/^\/+/, '');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function normalizeStringList(values) {
|
|
361
|
+
const seen = new Set();
|
|
362
|
+
const result = [];
|
|
363
|
+
for (const value of Array.isArray(values) ? values : []) {
|
|
364
|
+
const text = redactSecretLikeText(stringField(value)).trim();
|
|
365
|
+
if (!text || seen.has(text)) {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
seen.add(text);
|
|
369
|
+
result.push(text);
|
|
370
|
+
}
|
|
371
|
+
return result;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function summarizePrompt(value) {
|
|
375
|
+
const text = redactSecretLikeText(stringField(value)).replace(/\s+/g, ' ').trim();
|
|
376
|
+
if (!text) {
|
|
377
|
+
return '';
|
|
378
|
+
}
|
|
379
|
+
return `[prompt omitted; chars=${text.length}; hash=${hashString(text)}]`;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function summarizeStatusObject(value) {
|
|
383
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
384
|
+
return undefined;
|
|
385
|
+
}
|
|
386
|
+
return removeEmptySummaryFields({
|
|
387
|
+
state: redactSecretLikeText(stringField(value.state)),
|
|
388
|
+
status: redactSecretLikeText(stringField(value.status)),
|
|
389
|
+
ok: typeof value.ok === 'boolean' ? value.ok : undefined,
|
|
390
|
+
errorCode: redactSecretLikeText(stringField(value.errorCode || value.code)),
|
|
391
|
+
errorCategory: redactSecretLikeText(stringField(value.errorCategory)) ||
|
|
392
|
+
categorizeError(value.errorCode || value.code || value.message || value.error)
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function summarizeVerificationObject(value) {
|
|
397
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
const summary = {
|
|
401
|
+
state: redactSecretLikeText(stringField(value.state)),
|
|
402
|
+
status: redactSecretLikeText(stringField(value.status)),
|
|
403
|
+
ok: typeof value.ok === 'boolean' ? value.ok : undefined,
|
|
404
|
+
errorCode: redactSecretLikeText(stringField(value.errorCode || value.code)),
|
|
405
|
+
errorCategory: categorizeError(value.errorCode || value.code || value.reason || value.message || value.error)
|
|
406
|
+
};
|
|
407
|
+
if (value.diagnostics && typeof value.diagnostics === 'object' && !Array.isArray(value.diagnostics)) {
|
|
408
|
+
summary.diagnostics = summarizeStatusObject(value.diagnostics);
|
|
409
|
+
}
|
|
410
|
+
return removeEmptySummaryFields(summary);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function summarizeRedactedPreview(value) {
|
|
414
|
+
const text = stringField(value);
|
|
415
|
+
if (!text) {
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
redacted: true,
|
|
420
|
+
chars: text.length,
|
|
421
|
+
hash: hashString(text)
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function normalizeToolList(values) {
|
|
426
|
+
const seen = new Set();
|
|
427
|
+
const result = [];
|
|
428
|
+
for (const value of Array.isArray(values) ? values : []) {
|
|
429
|
+
const name = normalizeToolName(value);
|
|
430
|
+
if (!name || seen.has(name)) {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
seen.add(name);
|
|
434
|
+
result.push(name);
|
|
435
|
+
}
|
|
436
|
+
return result;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function normalizeToolName(value) {
|
|
440
|
+
const text = redactSecretLikeText(stringField(value)).replace(/\\/g, '/').split('/').filter(Boolean).pop() || '';
|
|
441
|
+
return text.replace(/[^a-zA-Z0-9_.+-]/g, '').slice(0, 48);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function sumFileBytes(files) {
|
|
445
|
+
let total = 0;
|
|
446
|
+
for (const file of Array.isArray(files) ? files : []) {
|
|
447
|
+
const explicitSize = finiteNumber(file && (file.size ?? file.byteLength ?? file.bytes));
|
|
448
|
+
if (explicitSize !== undefined) {
|
|
449
|
+
total += explicitSize;
|
|
450
|
+
} else if (typeof file?.content === 'string') {
|
|
451
|
+
total += file.content.length;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return total || undefined;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function countBinaryFiles(files) {
|
|
458
|
+
let count = 0;
|
|
459
|
+
for (const file of Array.isArray(files) ? files : []) {
|
|
460
|
+
if (file?.binary === true || file?.type === 'binary' || file?.kind === 'binary') {
|
|
461
|
+
count += 1;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return count || undefined;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function categorizeError(value) {
|
|
468
|
+
const text = redactSecretLikeText(stringField(value)).toLowerCase();
|
|
469
|
+
if (!text) {
|
|
470
|
+
return undefined;
|
|
471
|
+
}
|
|
472
|
+
if (/timeout|timed out|etimedout/.test(text)) {
|
|
473
|
+
return 'timeout';
|
|
474
|
+
}
|
|
475
|
+
if (/permission|denied|eacces|eperm/.test(text)) {
|
|
476
|
+
return 'permission';
|
|
477
|
+
}
|
|
478
|
+
if (/not found|missing|enoent|unavailable/.test(text)) {
|
|
479
|
+
return 'missing';
|
|
480
|
+
}
|
|
481
|
+
if (/quota|too large|limit/.test(text)) {
|
|
482
|
+
return 'quota';
|
|
483
|
+
}
|
|
484
|
+
return 'error';
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function finiteNumber(value) {
|
|
488
|
+
const number = Number(value);
|
|
489
|
+
return Number.isFinite(number) && number >= 0 ? Math.floor(number) : undefined;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function redactSecretLikeText(value) {
|
|
493
|
+
let redacted = stringField(value);
|
|
494
|
+
for (const pattern of SECRET_REDACTION_PATTERNS) {
|
|
495
|
+
pattern.lastIndex = 0;
|
|
496
|
+
redacted = redacted.replace(pattern, REDACTED_SECRET);
|
|
497
|
+
}
|
|
498
|
+
return redacted;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function stringField(value) {
|
|
502
|
+
return typeof value === 'string' ? value : '';
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function nonNegativeInteger(value) {
|
|
506
|
+
const number = Number(value);
|
|
507
|
+
return Number.isFinite(number) && number > 0 ? Math.floor(number) : 0;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function removeEmptyFields(value) {
|
|
511
|
+
const result = {};
|
|
512
|
+
for (const key of Object.keys(value)) {
|
|
513
|
+
if (value[key] !== undefined && value[key] !== '') {
|
|
514
|
+
result[key] = value[key];
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function removeEmptySummaryFields(value) {
|
|
521
|
+
const result = {};
|
|
522
|
+
for (const key of Object.keys(value)) {
|
|
523
|
+
const item = value[key];
|
|
524
|
+
if (item === undefined || item === '' || item === null) {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (Array.isArray(item) && item.length === 0) {
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (
|
|
531
|
+
item &&
|
|
532
|
+
typeof item === 'object' &&
|
|
533
|
+
!Array.isArray(item) &&
|
|
534
|
+
Object.keys(item).length === 0
|
|
535
|
+
) {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
result[key] = item;
|
|
539
|
+
}
|
|
540
|
+
return result;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function hashString(value) {
|
|
544
|
+
let hash = 2166136261;
|
|
545
|
+
const text = String(value || '');
|
|
546
|
+
for (let i = 0; i < text.length; i++) {
|
|
547
|
+
hash ^= text.charCodeAt(i);
|
|
548
|
+
hash = Math.imul(hash, 16777619);
|
|
549
|
+
}
|
|
550
|
+
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function generateId(prefix) {
|
|
554
|
+
return prefix + '_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return {
|
|
558
|
+
buildAuditDraftRecord,
|
|
559
|
+
buildAuditFinalRecord,
|
|
560
|
+
buildDiagnosticBundle,
|
|
561
|
+
normalizeAuditLogRecord,
|
|
562
|
+
normalizeSensitiveFindings,
|
|
563
|
+
normalizeFileSummaries,
|
|
564
|
+
normalizeDiffSummary,
|
|
565
|
+
redactContent,
|
|
566
|
+
hashString
|
|
567
|
+
};
|
|
568
|
+
});
|