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,106 @@
|
|
|
1
|
+
(function initCodexOverleafModels(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafModels = factory();
|
|
6
|
+
}
|
|
7
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function modelsFactory() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const FALLBACK_MODELS = Object.freeze([
|
|
11
|
+
Object.freeze({ id: 'gpt-5.5', label: 'GPT-5.5' }),
|
|
12
|
+
Object.freeze({ id: 'gpt-5.4', label: 'GPT-5.4' }),
|
|
13
|
+
Object.freeze({ id: 'gpt-5.4-mini', label: 'GPT-5.4 Mini' }),
|
|
14
|
+
Object.freeze({ id: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' }),
|
|
15
|
+
Object.freeze({ id: 'gpt-5.3-codex-spark', label: 'GPT-5.3 Codex Spark' }),
|
|
16
|
+
Object.freeze({ id: 'gpt-5.2', label: 'GPT-5.2' })
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
function normalizeDiscoveredModels({ models, selectedModel } = {}) {
|
|
20
|
+
const normalized = normalizeModelList(models);
|
|
21
|
+
const usedFallback = normalized.length === 0;
|
|
22
|
+
const resultModels = usedFallback ? cloneModels(FALLBACK_MODELS) : normalized;
|
|
23
|
+
const selectedId = normalizeModelId(selectedModel);
|
|
24
|
+
|
|
25
|
+
if (selectedId && !resultModels.some(model => model.id === selectedId)) {
|
|
26
|
+
resultModels.push({
|
|
27
|
+
id: selectedId,
|
|
28
|
+
label: `${selectedId} (custom)`,
|
|
29
|
+
unverified: true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
models: resultModels,
|
|
35
|
+
usedFallback
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function normalizeModelList(models) {
|
|
40
|
+
if (!Array.isArray(models)) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
const result = [];
|
|
46
|
+
|
|
47
|
+
for (const model of models) {
|
|
48
|
+
const id = normalizeModelId(typeof model === 'string' ? model : model?.id);
|
|
49
|
+
if (!id || seen.has(id)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
seen.add(id);
|
|
54
|
+
result.push(normalizeModelEntry(model, id));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeModelEntry(model, id) {
|
|
61
|
+
const label = typeof model?.label === 'string' && model.label.length > 0 ? model.label : id;
|
|
62
|
+
const normalized = {
|
|
63
|
+
id,
|
|
64
|
+
label,
|
|
65
|
+
reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
|
|
66
|
+
speedTiers: normalizeSpeedTiers(model?.speedTiers)
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultReasoningEffort')) {
|
|
70
|
+
normalized.defaultReasoningEffort = model.defaultReasoningEffort;
|
|
71
|
+
}
|
|
72
|
+
if (Object.prototype.hasOwnProperty.call(Object(model), 'defaultSpeedTier')) {
|
|
73
|
+
normalized.defaultSpeedTier = model.defaultSpeedTier;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return normalized;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function normalizeSpeedTiers(speedTiers) {
|
|
80
|
+
if (!Array.isArray(speedTiers)) {
|
|
81
|
+
return ['standard'];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = [];
|
|
85
|
+
for (const tier of speedTiers) {
|
|
86
|
+
const normalized = normalizeModelId(tier);
|
|
87
|
+
if (normalized && !result.includes(normalized)) {
|
|
88
|
+
result.push(normalized);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result.includes('standard') ? result : ['standard', ...result];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function normalizeModelId(id) {
|
|
95
|
+
return typeof id === 'string' ? id.trim() : '';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function cloneModels(models) {
|
|
99
|
+
return models.map(model => ({ ...model }));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
FALLBACK_MODELS,
|
|
104
|
+
normalizeDiscoveredModels
|
|
105
|
+
};
|
|
106
|
+
});
|
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
(function initCodexOverleafOtText(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafOtText = factory();
|
|
6
|
+
}
|
|
7
|
+
})(typeof globalThis !== 'undefined' ? globalThis : window, function otTextFactory() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const SHA256_K = [
|
|
11
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
12
|
+
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
13
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
14
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
15
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
16
|
+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
17
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
18
|
+
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
19
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
20
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
21
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
22
|
+
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
23
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
24
|
+
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
25
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
26
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
function applyTextOps(text, ops) {
|
|
30
|
+
if (!Array.isArray(ops)) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
reason: 'invalid_ops'
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let next = normalizeText(text);
|
|
38
|
+
for (const rawOp of ops) {
|
|
39
|
+
const validated = validateTextOp(rawOp, next);
|
|
40
|
+
if (!validated.ok) {
|
|
41
|
+
return validated;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const op = validated.op;
|
|
45
|
+
if (Object.prototype.hasOwnProperty.call(op, 'i')) {
|
|
46
|
+
next = next.slice(0, op.p) + op.i + next.slice(op.p);
|
|
47
|
+
} else {
|
|
48
|
+
next = next.slice(0, op.p) + next.slice(op.p + op.d.length);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
ok: true,
|
|
54
|
+
text: next
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function validateTextOp(rawOp, text) {
|
|
59
|
+
if (!rawOp || typeof rawOp !== 'object' || Array.isArray(rawOp)) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
reason: 'invalid_op'
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const keys = Object.keys(rawOp);
|
|
67
|
+
if (keys.some(key => key !== 'p' && key !== 'i' && key !== 'd')) {
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
reason: 'unknown_field'
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const hasInsert = Object.prototype.hasOwnProperty.call(rawOp, 'i');
|
|
75
|
+
const hasDelete = Object.prototype.hasOwnProperty.call(rawOp, 'd');
|
|
76
|
+
if (keys.length !== 2 || !Object.prototype.hasOwnProperty.call(rawOp, 'p') || hasInsert === hasDelete) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
reason: 'invalid_op'
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!Number.isInteger(rawOp.p) || rawOp.p < 0) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
reason: 'invalid_position'
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hasText = typeof text !== 'undefined';
|
|
91
|
+
const content = hasText ? normalizeText(text) : '';
|
|
92
|
+
if (hasInsert) {
|
|
93
|
+
if (typeof rawOp.i !== 'string') {
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
reason: 'invalid_op'
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (rawOp.i.length === 0) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
reason: 'empty_text'
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (hasText && rawOp.p > content.length) {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
reason: 'invalid_position'
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
ok: true,
|
|
113
|
+
op: {
|
|
114
|
+
p: rawOp.p,
|
|
115
|
+
i: rawOp.i
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (typeof rawOp.d !== 'string') {
|
|
121
|
+
return {
|
|
122
|
+
ok: false,
|
|
123
|
+
reason: 'invalid_op'
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (rawOp.d.length === 0) {
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
reason: 'empty_text'
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (hasText && rawOp.p + rawOp.d.length > content.length) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
reason: 'invalid_position'
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (hasText && content.slice(rawOp.p, rawOp.p + rawOp.d.length) !== rawOp.d) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
reason: 'delete_mismatch',
|
|
142
|
+
message: `Delete text did not match current content at position ${rawOp.p}.`
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
ok: true,
|
|
148
|
+
op: {
|
|
149
|
+
p: rawOp.p,
|
|
150
|
+
d: rawOp.d
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function diffToTextOps(oldText, newText) {
|
|
156
|
+
const previous = normalizeText(oldText);
|
|
157
|
+
const next = normalizeText(newText);
|
|
158
|
+
if (previous === next) {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const sharedLength = Math.min(previous.length, next.length);
|
|
163
|
+
let prefix = 0;
|
|
164
|
+
while (prefix < sharedLength && previous[prefix] === next[prefix]) {
|
|
165
|
+
prefix += 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let previousEnd = previous.length;
|
|
169
|
+
let nextEnd = next.length;
|
|
170
|
+
while (
|
|
171
|
+
previousEnd > prefix &&
|
|
172
|
+
nextEnd > prefix &&
|
|
173
|
+
previous[previousEnd - 1] === next[nextEnd - 1]
|
|
174
|
+
) {
|
|
175
|
+
previousEnd -= 1;
|
|
176
|
+
nextEnd -= 1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const deleted = previous.slice(prefix, previousEnd);
|
|
180
|
+
const inserted = next.slice(prefix, nextEnd);
|
|
181
|
+
const ops = [];
|
|
182
|
+
if (deleted) {
|
|
183
|
+
ops.push({
|
|
184
|
+
p: prefix,
|
|
185
|
+
d: deleted
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (inserted) {
|
|
189
|
+
ops.push({
|
|
190
|
+
p: prefix,
|
|
191
|
+
i: inserted
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return ops;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function normalizeObservedTextEvent(rawEvent) {
|
|
198
|
+
const event = rawEvent && typeof rawEvent === 'object' ? rawEvent : {};
|
|
199
|
+
const path = normalizePath(event.path);
|
|
200
|
+
if (!path) {
|
|
201
|
+
return {
|
|
202
|
+
ok: false,
|
|
203
|
+
reason: 'missing_path'
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const previousContent = normalizeText(event.previousContent);
|
|
208
|
+
const nextContent = normalizeText(event.nextContent);
|
|
209
|
+
const ops = Array.isArray(event.ops)
|
|
210
|
+
? normalizeTextOps(event.ops, previousContent)
|
|
211
|
+
: {
|
|
212
|
+
ok: true,
|
|
213
|
+
ops: diffToTextOps(previousContent, nextContent)
|
|
214
|
+
};
|
|
215
|
+
if (!ops.ok) {
|
|
216
|
+
return {
|
|
217
|
+
ok: false,
|
|
218
|
+
reason: ops.reason,
|
|
219
|
+
path
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const applied = applyTextOps(previousContent, ops.ops);
|
|
224
|
+
if (!applied.ok) {
|
|
225
|
+
return {
|
|
226
|
+
ok: false,
|
|
227
|
+
reason: applied.reason,
|
|
228
|
+
path
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (applied.text !== nextContent) {
|
|
232
|
+
return {
|
|
233
|
+
ok: false,
|
|
234
|
+
reason: 'ops_do_not_produce_next_content',
|
|
235
|
+
path
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
ok: true,
|
|
241
|
+
path,
|
|
242
|
+
previousContent,
|
|
243
|
+
nextContent,
|
|
244
|
+
observedAt: normalizeObservedAt(event.observedAt),
|
|
245
|
+
observedVersion: normalizeObservedVersion(event.observedVersion),
|
|
246
|
+
source: normalizeSource(event.source),
|
|
247
|
+
baseHash: hashText(previousContent),
|
|
248
|
+
nextHash: hashText(nextContent),
|
|
249
|
+
ops: ops.ops
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function normalizeTextOps(rawOps, baseText) {
|
|
254
|
+
const normalized = [];
|
|
255
|
+
let current = normalizeText(baseText);
|
|
256
|
+
for (const rawOp of rawOps) {
|
|
257
|
+
const validated = validateTextOp(rawOp, current);
|
|
258
|
+
if (!validated.ok) {
|
|
259
|
+
return validated;
|
|
260
|
+
}
|
|
261
|
+
const op = validated.op;
|
|
262
|
+
normalized.push(op);
|
|
263
|
+
if (Object.prototype.hasOwnProperty.call(op, 'i')) {
|
|
264
|
+
current = current.slice(0, op.p) + op.i + current.slice(op.p);
|
|
265
|
+
} else {
|
|
266
|
+
current = current.slice(0, op.p) + current.slice(op.p + op.d.length);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
ok: true,
|
|
271
|
+
ops: normalized
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function hashText(text) {
|
|
276
|
+
const value = String(text ?? '');
|
|
277
|
+
const nodeCrypto = getNodeCrypto();
|
|
278
|
+
if (nodeCrypto) {
|
|
279
|
+
return nodeCrypto.createHash('sha256').update(value, 'utf8').digest('hex');
|
|
280
|
+
}
|
|
281
|
+
return sha256Hex(utf8Bytes(value));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function getNodeCrypto() {
|
|
285
|
+
if (typeof require !== 'function') {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
return require('node:crypto');
|
|
290
|
+
} catch (error) {
|
|
291
|
+
try {
|
|
292
|
+
return require('crypto');
|
|
293
|
+
} catch (fallbackError) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function normalizePath(value) {
|
|
300
|
+
return String(value || '')
|
|
301
|
+
.replace(/\s+/g, ' ')
|
|
302
|
+
.replace(/\\/g, '/')
|
|
303
|
+
.trim()
|
|
304
|
+
.replace(/^\/+/, '');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function normalizeText(value) {
|
|
308
|
+
return String(value ?? '');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function normalizeObservedAt(value) {
|
|
312
|
+
if (value instanceof Date) {
|
|
313
|
+
return validDateToIso(value) || new Date().toISOString();
|
|
314
|
+
}
|
|
315
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
316
|
+
return validDateToIso(new Date(value)) || new Date().toISOString();
|
|
317
|
+
}
|
|
318
|
+
const text = String(value || '').trim();
|
|
319
|
+
return text || new Date().toISOString();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function validDateToIso(date) {
|
|
323
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function normalizeObservedVersion(value) {
|
|
327
|
+
if (value === null || typeof value === 'undefined' || value === '') {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
return String(value);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function normalizeSource(value) {
|
|
334
|
+
if (value === null || typeof value === 'undefined') {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
338
|
+
const source = String(value).trim();
|
|
339
|
+
return source || null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const normalized = {};
|
|
343
|
+
for (const [key, sourceValue] of Object.entries(value)) {
|
|
344
|
+
if (isContentSourceField(key) || sourceValue === null || typeof sourceValue === 'undefined') {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (typeof sourceValue === 'string' || typeof sourceValue === 'number' || typeof sourceValue === 'boolean') {
|
|
348
|
+
normalized[key] = sourceValue;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return Object.keys(normalized).length ? normalized : null;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function isContentSourceField(key) {
|
|
355
|
+
return /^(content|previousContent|nextContent|text|body|raw|rawContent)$/i.test(key);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function utf8Bytes(text) {
|
|
359
|
+
if (typeof TextEncoder === 'function') {
|
|
360
|
+
return Array.from(new TextEncoder().encode(text));
|
|
361
|
+
}
|
|
362
|
+
if (typeof Buffer === 'function' && typeof Buffer.from === 'function') {
|
|
363
|
+
return Array.from(Buffer.from(text, 'utf8'));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const bytes = [];
|
|
367
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
368
|
+
let codePoint = text.charCodeAt(index);
|
|
369
|
+
if (codePoint >= 0xd800 && codePoint <= 0xdbff) {
|
|
370
|
+
const next = index + 1 < text.length ? text.charCodeAt(index + 1) : 0;
|
|
371
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
372
|
+
codePoint = 0x10000 + ((codePoint - 0xd800) << 10) + (next - 0xdc00);
|
|
373
|
+
index += 1;
|
|
374
|
+
} else {
|
|
375
|
+
codePoint = 0xfffd;
|
|
376
|
+
}
|
|
377
|
+
} else if (codePoint >= 0xdc00 && codePoint <= 0xdfff) {
|
|
378
|
+
codePoint = 0xfffd;
|
|
379
|
+
}
|
|
380
|
+
if (codePoint <= 0x7f) {
|
|
381
|
+
bytes.push(codePoint);
|
|
382
|
+
} else if (codePoint <= 0x7ff) {
|
|
383
|
+
bytes.push(
|
|
384
|
+
0xc0 | (codePoint >> 6),
|
|
385
|
+
0x80 | (codePoint & 0x3f)
|
|
386
|
+
);
|
|
387
|
+
} else if (codePoint <= 0xffff) {
|
|
388
|
+
bytes.push(
|
|
389
|
+
0xe0 | (codePoint >> 12),
|
|
390
|
+
0x80 | ((codePoint >> 6) & 0x3f),
|
|
391
|
+
0x80 | (codePoint & 0x3f)
|
|
392
|
+
);
|
|
393
|
+
} else {
|
|
394
|
+
bytes.push(
|
|
395
|
+
0xf0 | (codePoint >> 18),
|
|
396
|
+
0x80 | ((codePoint >> 12) & 0x3f),
|
|
397
|
+
0x80 | ((codePoint >> 6) & 0x3f),
|
|
398
|
+
0x80 | (codePoint & 0x3f)
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return bytes;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function sha256Hex(inputBytes) {
|
|
406
|
+
const bytes = inputBytes.slice();
|
|
407
|
+
const bitLength = bytes.length * 8;
|
|
408
|
+
bytes.push(0x80);
|
|
409
|
+
while (bytes.length % 64 !== 56) {
|
|
410
|
+
bytes.push(0);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const high = Math.floor(bitLength / 0x100000000);
|
|
414
|
+
const low = bitLength >>> 0;
|
|
415
|
+
bytes.push(
|
|
416
|
+
(high >>> 24) & 0xff,
|
|
417
|
+
(high >>> 16) & 0xff,
|
|
418
|
+
(high >>> 8) & 0xff,
|
|
419
|
+
high & 0xff,
|
|
420
|
+
(low >>> 24) & 0xff,
|
|
421
|
+
(low >>> 16) & 0xff,
|
|
422
|
+
(low >>> 8) & 0xff,
|
|
423
|
+
low & 0xff
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
const hash = [
|
|
427
|
+
0x6a09e667,
|
|
428
|
+
0xbb67ae85,
|
|
429
|
+
0x3c6ef372,
|
|
430
|
+
0xa54ff53a,
|
|
431
|
+
0x510e527f,
|
|
432
|
+
0x9b05688c,
|
|
433
|
+
0x1f83d9ab,
|
|
434
|
+
0x5be0cd19
|
|
435
|
+
];
|
|
436
|
+
const words = new Array(64);
|
|
437
|
+
|
|
438
|
+
for (let chunk = 0; chunk < bytes.length; chunk += 64) {
|
|
439
|
+
for (let index = 0; index < 16; index += 1) {
|
|
440
|
+
const offset = chunk + index * 4;
|
|
441
|
+
words[index] = (
|
|
442
|
+
(bytes[offset] << 24) |
|
|
443
|
+
(bytes[offset + 1] << 16) |
|
|
444
|
+
(bytes[offset + 2] << 8) |
|
|
445
|
+
bytes[offset + 3]
|
|
446
|
+
) >>> 0;
|
|
447
|
+
}
|
|
448
|
+
for (let index = 16; index < 64; index += 1) {
|
|
449
|
+
const s0 = rotr(words[index - 15], 7) ^ rotr(words[index - 15], 18) ^ (words[index - 15] >>> 3);
|
|
450
|
+
const s1 = rotr(words[index - 2], 17) ^ rotr(words[index - 2], 19) ^ (words[index - 2] >>> 10);
|
|
451
|
+
words[index] = (words[index - 16] + s0 + words[index - 7] + s1) >>> 0;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
let a = hash[0];
|
|
455
|
+
let b = hash[1];
|
|
456
|
+
let c = hash[2];
|
|
457
|
+
let d = hash[3];
|
|
458
|
+
let e = hash[4];
|
|
459
|
+
let f = hash[5];
|
|
460
|
+
let g = hash[6];
|
|
461
|
+
let h = hash[7];
|
|
462
|
+
|
|
463
|
+
for (let index = 0; index < 64; index += 1) {
|
|
464
|
+
const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
465
|
+
const ch = (e & f) ^ (~e & g);
|
|
466
|
+
const temp1 = (h + s1 + ch + SHA256_K[index] + words[index]) >>> 0;
|
|
467
|
+
const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
468
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
469
|
+
const temp2 = (s0 + maj) >>> 0;
|
|
470
|
+
|
|
471
|
+
h = g;
|
|
472
|
+
g = f;
|
|
473
|
+
f = e;
|
|
474
|
+
e = (d + temp1) >>> 0;
|
|
475
|
+
d = c;
|
|
476
|
+
c = b;
|
|
477
|
+
b = a;
|
|
478
|
+
a = (temp1 + temp2) >>> 0;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
hash[0] = (hash[0] + a) >>> 0;
|
|
482
|
+
hash[1] = (hash[1] + b) >>> 0;
|
|
483
|
+
hash[2] = (hash[2] + c) >>> 0;
|
|
484
|
+
hash[3] = (hash[3] + d) >>> 0;
|
|
485
|
+
hash[4] = (hash[4] + e) >>> 0;
|
|
486
|
+
hash[5] = (hash[5] + f) >>> 0;
|
|
487
|
+
hash[6] = (hash[6] + g) >>> 0;
|
|
488
|
+
hash[7] = (hash[7] + h) >>> 0;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return hash.map(word => word.toString(16).padStart(8, '0')).join('');
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function rotr(value, bits) {
|
|
495
|
+
return (value >>> bits) | (value << (32 - bits));
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
applyTextOps,
|
|
500
|
+
validateTextOp,
|
|
501
|
+
diffToTextOps,
|
|
502
|
+
normalizeObservedTextEvent,
|
|
503
|
+
hashText
|
|
504
|
+
};
|
|
505
|
+
});
|