codex-overleaf-link 2.2.1 → 2.3.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/README.md +25 -23
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/runtime-manifest.json +5 -71
- package/extension/src/background.js +53 -69
- package/extension/src/backgroundUpdateCoordinator.js +128 -66
- package/extension/src/content/applyResultFormatters.js +2 -3
- package/extension/src/content/contentRuntime.js +650 -1449
- package/extension/src/content/contextTray.js +4 -6
- package/extension/src/content/diagnosticsController.js +1 -2
- package/extension/src/content/diffReviewPanel.js +14 -13
- package/extension/src/content/generated/content.bundle.js +41370 -0
- package/extension/src/content/generated/content.bundle.meta.json +102 -0
- package/extension/src/content/legacyGlobalRegistry.js +129 -0
- package/extension/src/content/markdownText.js +5 -7
- package/extension/src/content/modelPicker.js +1 -1
- package/extension/src/content/modelPickerSupport.js +10 -5
- package/extension/src/content/moduleRegistryKernel.js +125 -0
- package/extension/src/content/nativeCompatibilityController.js +313 -0
- package/extension/src/content/otWarmMirror.js +7 -5
- package/extension/src/content/pageBridgeClient.js +224 -0
- package/extension/src/content/panelMaintenance.js +8 -3
- package/extension/src/content/postNavigationSettlementPersistence.js +100 -0
- package/extension/src/content/projectProviderSelection.js +4 -12
- package/extension/src/content/projectSessionCleanup.js +3 -3
- package/extension/src/content/providerSettingsCoordinator.js +59 -26
- package/extension/src/content/providerSettingsDialog.js +30 -18
- package/extension/src/content/recentProjects.js +15 -23
- package/extension/src/content/runGuidanceController.js +1 -1
- package/extension/src/content/runQueueScheduler.js +129 -29
- package/extension/src/content/runSettlementPersistence.js +51 -0
- package/extension/src/content/runTimelineView.js +11 -8
- package/extension/src/content/scopedPersistenceCoordinator.js +100 -0
- package/extension/src/content/scopedPersistenceDetachedCommit.js +47 -0
- package/extension/src/content/scopedPersistencePanelState.js +111 -0
- package/extension/src/content/sessionManager.js +15 -12
- package/extension/src/content/sessionPersistence.js +67 -8
- package/extension/src/content/updateNotice.js +10 -4
- package/extension/src/content/writebackOrchestrator.js +91 -23
- package/extension/src/contentScript.js +5 -1
- package/extension/src/page/trackedChangesLifecycle.js +6 -1
- package/extension/src/pageBridge.js +47 -98
- package/extension/src/shared/agentTranscript.js +8 -5
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/governanceRules.js +1 -1
- package/extension/src/shared/managedUpdateProjection.js +337 -0
- package/extension/src/shared/nativeRequestIdentity.js +60 -0
- package/extension/src/shared/otText.js +0 -19
- package/extension/src/shared/pageRpcContract.js +136 -0
- package/extension/src/shared/runExecutionSnapshot.js +177 -0
- package/extension/src/shared/runExecutionSnapshotCodec.js +168 -0
- package/extension/src/shared/runInputQueue.js +81 -34
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +79 -0
- package/extension/src/shared/scopedPersistenceQueuePolicy.js +181 -0
- package/extension/src/shared/scopedPersistenceTransaction.js +238 -0
- package/extension/src/shared/sessionState.js +64 -48
- package/extension/src/shared/settlementFacts.js +351 -0
- package/extension/src/shared/storageDb.js +19 -5
- package/extension/src/shared/storageMigration.js +275 -61
- package/extension/src/shared/storageSessionClaims.js +60 -0
- package/extension/src/shared/updateConsent.js +4 -0
- package/extension/src/shared/updateRevocationIntent.js +109 -0
- package/extension/src/shared/writebackEvidenceProjection.js +150 -0
- package/extension/src/shared/writebackOperationEvidence.js +143 -0
- package/extension/src/shared/writebackSettlement.js +705 -0
- package/native-host/src/codexRuntimeIdentity.js +1 -1
- package/native-host/src/codexSessionRunner.js +7 -13
- package/native-host/src/index.js +3 -69
- package/native-host/src/managedInstall.js +50 -8
- package/native-host/src/nativeTransportEnvelope.js +148 -0
- package/native-host/src/taskRunnerRuntime.js +3 -3
- package/package.json +13 -5
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
var api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
4
|
+
if (root) root.CodexOverleafPageRpcContract = api;
|
|
5
|
+
})(typeof window !== 'undefined' ? window : (typeof globalThis !== 'undefined' ? globalThis : this), function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
var REVISION = '2026-07-26-page-rpc-contract-v13';
|
|
9
|
+
var METHODS = freezeCatalog({
|
|
10
|
+
initializeCapability: entry('bridge.initialize', 'control', 'none', 'default', false, 'none'),
|
|
11
|
+
probe: entry('bridge.probe', 'read', 'none', 'default', false, 'safe'),
|
|
12
|
+
cancelActiveWrite: entry('write.cancel', 'control', 'none', 'default', false, 'idempotent'),
|
|
13
|
+
getProjectSnapshot: entry('snapshot.read', 'read', 'none', 'snapshot', true, 'safe'),
|
|
14
|
+
getProjectFileList: entry('snapshot.list', 'read', 'none', 'file_list', true, 'safe'),
|
|
15
|
+
invalidateProjectSnapshot: entry('snapshot.invalidate', 'cache', 'none', 'default', false, 'idempotent'),
|
|
16
|
+
createCheckpoint: entry('checkpoint.create', 'page_state', 'none', 'default', false, 'no_retry'),
|
|
17
|
+
ensureReviewing: entry('reviewing.enable', 'page_state', 'optional', 'default', true, 'idempotent'),
|
|
18
|
+
ensureEditing: entry('reviewing.disable', 'page_state', 'optional', 'default', true, 'idempotent'),
|
|
19
|
+
applyOperations: entry('document.write', 'document', 'required', 'writeback', true, 'no_retry'),
|
|
20
|
+
jumpToPosition: entry('editor.navigate', 'navigation', 'required', 'default', false, 'idempotent'),
|
|
21
|
+
rejectTrackedChanges: entry('tracked_changes.reject', 'document', 'required', 'lifecycle', true, 'no_retry'),
|
|
22
|
+
acceptTrackedChanges: entry('tracked_changes.accept', 'document', 'required', 'lifecycle', true, 'no_retry'),
|
|
23
|
+
triggerCompile: entry('compile.trigger', 'page_state', 'required', 'compile', false, 'no_retry'),
|
|
24
|
+
getCompileLog: entry('compile.log', 'read', 'required', 'compile', true, 'safe'),
|
|
25
|
+
getCompileState: entry('compile.state', 'read', 'none', 'default', false, 'safe'),
|
|
26
|
+
waitForSaveState: entry('save.wait', 'read', 'none', 'default', true, 'safe'),
|
|
27
|
+
startOtObserver: entry('ot.start', 'observer', 'none', 'default', false, 'idempotent'),
|
|
28
|
+
stopOtObserver: entry('ot.stop', 'observer', 'none', 'default', false, 'idempotent'),
|
|
29
|
+
getOtStatus: entry('ot.status', 'read', 'none', 'default', false, 'safe'),
|
|
30
|
+
drainOtEvents: entry('ot.drain', 'observer', 'none', 'default', false, 'no_retry')
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function entry(capability, mutation, projectIdentity, timeoutClass, cancellable, retryClass) {
|
|
34
|
+
return {
|
|
35
|
+
capability: capability,
|
|
36
|
+
mutation: mutation,
|
|
37
|
+
projectIdentity: projectIdentity,
|
|
38
|
+
timeoutClass: timeoutClass,
|
|
39
|
+
cancellation: cancellable ? 'content_abort' : 'none',
|
|
40
|
+
retryClass: retryClass,
|
|
41
|
+
failureClass: mutation === 'document' ? 'write' : mutation
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getMethod(name) {
|
|
46
|
+
return typeof name === 'string' && METHODS[name] ? METHODS[name] : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function listMethods() {
|
|
50
|
+
return Object.keys(METHODS);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isCancellable(name) {
|
|
54
|
+
return getMethod(name)?.cancellation === 'content_abort';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function requiresProjectIdentity(name) {
|
|
58
|
+
return getMethod(name)?.projectIdentity === 'required';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolveTimeoutMs(name, overrides) {
|
|
62
|
+
overrides = overrides || {};
|
|
63
|
+
var timeoutClass = getMethod(name)?.timeoutClass || 'default';
|
|
64
|
+
var defaults = {
|
|
65
|
+
default: 8000,
|
|
66
|
+
snapshot: 70000,
|
|
67
|
+
file_list: 35000,
|
|
68
|
+
compile: 75000,
|
|
69
|
+
lifecycle: 120000,
|
|
70
|
+
writeback: 30000
|
|
71
|
+
};
|
|
72
|
+
var candidate = Number(overrides[timeoutClass]);
|
|
73
|
+
return Number.isFinite(candidate) && candidate > 0 ? candidate : defaults[timeoutClass];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function resolveDispatchPolicy(name, overrides) {
|
|
77
|
+
var method = getMethod(name);
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
timeoutMs: resolveTimeoutMs(name, overrides),
|
|
80
|
+
cancellation: method ? method.cancellation : 'none',
|
|
81
|
+
retryClass: method ? method.retryClass : 'none',
|
|
82
|
+
automaticAttempts: 1
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function capabilityReport() {
|
|
87
|
+
var report = {};
|
|
88
|
+
listMethods().forEach(function (name) {
|
|
89
|
+
var method = METHODS[name];
|
|
90
|
+
report[name] = {
|
|
91
|
+
capability: method.capability,
|
|
92
|
+
mutation: method.mutation,
|
|
93
|
+
projectIdentity: method.projectIdentity,
|
|
94
|
+
retryClass: method.retryClass,
|
|
95
|
+
timeoutClass: method.timeoutClass,
|
|
96
|
+
cancellation: method.cancellation
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
return report;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function withCapabilityReport(capabilities) {
|
|
103
|
+
return Object.assign({}, capabilities || {}, { pageRpc: capabilityReport() });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function normalizeFailure(method, error) {
|
|
107
|
+
var contract = getMethod(method);
|
|
108
|
+
var message = error && error.message ? error.message : String(error || 'Page bridge request failed');
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
code: 'page_bridge_dispatch_failed',
|
|
112
|
+
error: message,
|
|
113
|
+
rpcMethod: typeof method === 'string' ? method : '',
|
|
114
|
+
failureClass: contract ? contract.failureClass : 'unknown'
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function freezeCatalog(catalog) {
|
|
119
|
+
Object.keys(catalog).forEach(function (name) { Object.freeze(catalog[name]); });
|
|
120
|
+
return Object.freeze(catalog);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return Object.freeze({
|
|
124
|
+
METHODS: METHODS,
|
|
125
|
+
REVISION: REVISION,
|
|
126
|
+
capabilityReport: capabilityReport,
|
|
127
|
+
getMethod: getMethod,
|
|
128
|
+
isCancellable: isCancellable,
|
|
129
|
+
listMethods: listMethods,
|
|
130
|
+
normalizeFailure: normalizeFailure,
|
|
131
|
+
requiresProjectIdentity: requiresProjectIdentity,
|
|
132
|
+
resolveDispatchPolicy: resolveDispatchPolicy,
|
|
133
|
+
resolveTimeoutMs: resolveTimeoutMs,
|
|
134
|
+
withCapabilityReport: withCapabilityReport
|
|
135
|
+
});
|
|
136
|
+
});
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
(function initCodexOverleafRunExecutionSnapshot(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory(require('./providerProfiles'), require('./runExecutionSnapshotCodec'));
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafModuleRegistry.define('RunExecutionSnapshot', [
|
|
6
|
+
'ProviderProfiles',
|
|
7
|
+
'RunExecutionSnapshotCodec'
|
|
8
|
+
], factory);
|
|
9
|
+
}
|
|
10
|
+
})(typeof window !== 'undefined' ? window : globalThis, function runExecutionSnapshotFactory(ProviderProfiles, Codec) {
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
function create(input = {}) {
|
|
14
|
+
const providerId = Codec.normalizeText(input.providerId) || 'builtin';
|
|
15
|
+
return Codec.normalizeSnapshot(input, {
|
|
16
|
+
source: input.source || 'submitted',
|
|
17
|
+
requireProviderRevision: providerId !== 'builtin'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function capture(input = {}, options = {}) {
|
|
22
|
+
return Codec.normalizeSnapshot(input, options);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function captureRawQueueTuple(rawQueueItem = {}, fallbackInput = {}) {
|
|
26
|
+
const rawPayload = rawQueueItem?.payload && typeof rawQueueItem.payload === 'object'
|
|
27
|
+
? rawQueueItem.payload
|
|
28
|
+
: rawQueueItem;
|
|
29
|
+
const persisted = rawQueueItem?.executionSnapshot || rawPayload?.executionSnapshot;
|
|
30
|
+
if (persisted && typeof persisted === 'object') {
|
|
31
|
+
return Codec.normalizeSnapshot(persisted, { source: persisted.source || 'submitted' });
|
|
32
|
+
}
|
|
33
|
+
const raw = rawPayload && typeof rawPayload === 'object' ? rawPayload : {};
|
|
34
|
+
const fallback = fallbackInput && typeof fallbackInput === 'object' ? fallbackInput : {};
|
|
35
|
+
const captured = {};
|
|
36
|
+
let inferred = false;
|
|
37
|
+
for (const field of Codec.TUPLE_FIELDS) {
|
|
38
|
+
if (Codec.hasOwn(raw, field)) captured[field] = Codec.cloneValue(raw[field]);
|
|
39
|
+
else {
|
|
40
|
+
captured[field] = Codec.cloneValue(fallback[field]);
|
|
41
|
+
inferred = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const providerId = Codec.normalizeText(captured.providerId) || 'builtin';
|
|
45
|
+
if (providerId !== 'builtin' && !Codec.normalizeRevision(captured.providerRevision)
|
|
46
|
+
&& (!Codec.hasOwn(raw, 'providerRevision') || captured.providerRevision === '' || captured.providerRevision == null)) {
|
|
47
|
+
captured.providerRevision = fallback.providerRevision;
|
|
48
|
+
inferred = true;
|
|
49
|
+
}
|
|
50
|
+
return Codec.normalizeSnapshot(captured, {
|
|
51
|
+
source: inferred ? 'legacy-inferred' : 'legacy-captured'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function resolveForExecution(value = {}, options = {}) {
|
|
56
|
+
const persisted = value.executionSnapshot || value;
|
|
57
|
+
const snapshot = Codec.normalizeSnapshot(persisted, { source: persisted.source || 'submitted' });
|
|
58
|
+
if (snapshot.providerId === 'builtin') return Codec.normalizeSnapshot(snapshot, { source: snapshot.source });
|
|
59
|
+
const catalog = options.catalog || {};
|
|
60
|
+
const provider = ProviderProfiles?.getProviderById
|
|
61
|
+
? ProviderProfiles.getProviderById(catalog, snapshot.providerId)
|
|
62
|
+
: (catalog.providers || []).find(item => item?.id === snapshot.providerId);
|
|
63
|
+
if (!provider) throw Codec.snapshotError('provider_not_found', 'The selected provider no longer exists.');
|
|
64
|
+
const currentRevision = Codec.normalizeRevision(provider.revision);
|
|
65
|
+
if (!currentRevision) throw Codec.snapshotError('provider_revision_conflict', 'The selected provider has no usable revision.');
|
|
66
|
+
if (!snapshot.providerRevision) {
|
|
67
|
+
if (snapshot.source !== 'legacy-inferred') {
|
|
68
|
+
throw Codec.snapshotError('provider_revision_conflict', 'The selected provider revision was not captured for this run.');
|
|
69
|
+
}
|
|
70
|
+
return Codec.normalizeSnapshot({ ...snapshot, providerRevision: currentRevision }, {
|
|
71
|
+
source: 'legacy-inferred',
|
|
72
|
+
requireProviderRevision: true
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (snapshot.providerRevision !== currentRevision) {
|
|
76
|
+
throw Codec.snapshotError('provider_revision_conflict', 'The selected provider changed after this run was submitted.');
|
|
77
|
+
}
|
|
78
|
+
return Codec.normalizeSnapshot(snapshot, { source: snapshot.source, requireProviderRevision: true });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function snapshotOf(value = {}) {
|
|
82
|
+
const persisted = value.executionSnapshot || value;
|
|
83
|
+
return Codec.normalizeSnapshot(persisted, { source: persisted.source || 'submitted' });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function cloneSnapshot(value = {}) {
|
|
87
|
+
const snapshot = snapshotOf(value);
|
|
88
|
+
return { ...snapshot, focusFiles: [...snapshot.focusFiles] };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function toLegacyQueueTuple(value = {}) {
|
|
92
|
+
const snapshot = snapshotOf(value);
|
|
93
|
+
return {
|
|
94
|
+
mode: snapshot.mode,
|
|
95
|
+
providerId: snapshot.providerId,
|
|
96
|
+
providerRevision: snapshot.providerRevision,
|
|
97
|
+
model: snapshot.model,
|
|
98
|
+
reasoningEffort: snapshot.reasoningEffort,
|
|
99
|
+
speedTier: snapshot.speedTier,
|
|
100
|
+
autoRecompile: snapshot.autoRecompile,
|
|
101
|
+
requireReviewing: snapshot.requireReviewing,
|
|
102
|
+
focusFiles: [...snapshot.focusFiles]
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function toQueuePayload(value = {}) {
|
|
107
|
+
const snapshot = snapshotOf(value);
|
|
108
|
+
return { executionSnapshot: cloneSnapshot(snapshot), ...toLegacyQueueTuple(snapshot) };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function toRunCompatibilityTuple(value = {}) {
|
|
112
|
+
const snapshot = snapshotOf(value);
|
|
113
|
+
return {
|
|
114
|
+
...toLegacyQueueTuple(snapshot),
|
|
115
|
+
providerRevision: snapshot.providerId === 'builtin' ? 0 : Number(snapshot.providerRevision),
|
|
116
|
+
executionSnapshot: cloneSnapshot(snapshot)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function projectForDisplay(value = {}) {
|
|
121
|
+
const snapshot = snapshotOf(value);
|
|
122
|
+
return {
|
|
123
|
+
providerId: snapshot.providerId,
|
|
124
|
+
model: snapshot.model,
|
|
125
|
+
reasoningEffort: snapshot.reasoningEffort,
|
|
126
|
+
speedTier: snapshot.speedTier,
|
|
127
|
+
mode: snapshot.mode,
|
|
128
|
+
focusFiles: [...snapshot.focusFiles]
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function equalsExecutionConfig(left = {}, right = {}) {
|
|
133
|
+
const leftTuple = toLegacyQueueTuple(left);
|
|
134
|
+
const rightTuple = toLegacyQueueTuple(right);
|
|
135
|
+
return Codec.TUPLE_FIELDS.every(field =>
|
|
136
|
+
JSON.stringify(leftTuple[field]) === JSON.stringify(rightTuple[field])
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function applyToState(state = {}, value = {}) {
|
|
141
|
+
const snapshot = snapshotOf(value);
|
|
142
|
+
return {
|
|
143
|
+
...state,
|
|
144
|
+
...toLegacyQueueTuple(snapshot),
|
|
145
|
+
providerRevision: snapshot.providerId === 'builtin' ? 0 : Number(snapshot.providerRevision)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function toProviderSelection(value = {}) {
|
|
150
|
+
const snapshot = snapshotOf(value);
|
|
151
|
+
return {
|
|
152
|
+
providerId: snapshot.providerId,
|
|
153
|
+
providerRevision: snapshot.providerId === 'builtin' ? 0 : Number(snapshot.providerRevision)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
SCHEMA_VERSION: Codec.SCHEMA_VERSION,
|
|
159
|
+
TUPLE_FIELDS: Codec.TUPLE_FIELDS,
|
|
160
|
+
applyToState,
|
|
161
|
+
capture,
|
|
162
|
+
captureRawQueueTuple,
|
|
163
|
+
cloneSnapshot,
|
|
164
|
+
create,
|
|
165
|
+
equalsExecutionConfig,
|
|
166
|
+
fromQueuePayload: captureRawQueueTuple,
|
|
167
|
+
normalizeRevision: Codec.normalizeRevision,
|
|
168
|
+
normalizeSnapshot: Codec.normalizeSnapshot,
|
|
169
|
+
projectForDisplay,
|
|
170
|
+
resolveForExecution,
|
|
171
|
+
toLegacyQueueTuple,
|
|
172
|
+
toProviderSelection,
|
|
173
|
+
toQueuePayload,
|
|
174
|
+
toRunCompatibilityTuple,
|
|
175
|
+
validate: Codec.validate
|
|
176
|
+
};
|
|
177
|
+
});
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
(function initCodexOverleafRunExecutionSnapshotCodec(root, factory) {
|
|
2
|
+
if (typeof module === 'object' && module.exports) {
|
|
3
|
+
module.exports = factory();
|
|
4
|
+
} else {
|
|
5
|
+
root.CodexOverleafRunExecutionSnapshotCodec = factory();
|
|
6
|
+
}
|
|
7
|
+
})(typeof window !== 'undefined' ? window : globalThis, function runExecutionSnapshotCodecFactory() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const SCHEMA_VERSION = 1;
|
|
11
|
+
const VALID_MODES = new Set(['ask', 'confirm', 'auto']);
|
|
12
|
+
const VALID_SOURCES = new Set(['submitted', 'legacy-captured', 'legacy-inferred']);
|
|
13
|
+
const TUPLE_FIELDS = Object.freeze([
|
|
14
|
+
'mode', 'providerId', 'providerRevision', 'model', 'reasoningEffort',
|
|
15
|
+
'speedTier', 'autoRecompile', 'requireReviewing', 'focusFiles'
|
|
16
|
+
]);
|
|
17
|
+
const SECRET_FIELD_PATTERN = /(?:api.?key|authorization|password|secret|access.?token|refresh.?token)/i;
|
|
18
|
+
|
|
19
|
+
function normalizeSnapshot(value = {}, options = {}) {
|
|
20
|
+
const input = value && typeof value === 'object' ? value : {};
|
|
21
|
+
assertNoSecretFields(input);
|
|
22
|
+
const providerId = normalizeText(input.providerId) || 'builtin';
|
|
23
|
+
const revision = normalizeRevisionResult(input.providerRevision);
|
|
24
|
+
if (!revision.ok) throw snapshotError('provider_revision_conflict', revision.error);
|
|
25
|
+
const snapshot = {
|
|
26
|
+
schemaVersion: SCHEMA_VERSION,
|
|
27
|
+
mode: VALID_MODES.has(input.mode) ? input.mode : 'ask',
|
|
28
|
+
providerId,
|
|
29
|
+
providerRevision: providerId === 'builtin' ? '' : revision.value,
|
|
30
|
+
model: normalizeText(input.model).slice(0, 160),
|
|
31
|
+
reasoningEffort: normalizeText(input.reasoningEffort).slice(0, 32),
|
|
32
|
+
speedTier: input.speedTier === 'fast' ? 'fast' : 'standard',
|
|
33
|
+
autoRecompile: input.autoRecompile !== false,
|
|
34
|
+
requireReviewing: input.requireReviewing !== false,
|
|
35
|
+
focusFiles: normalizePaths(input.focusFiles),
|
|
36
|
+
capturedAt: normalizeTimestamp(input.capturedAt),
|
|
37
|
+
source: VALID_SOURCES.has(options.source || input.source)
|
|
38
|
+
? (options.source || input.source)
|
|
39
|
+
: 'submitted'
|
|
40
|
+
};
|
|
41
|
+
const result = validate(snapshot, options);
|
|
42
|
+
if (!result.ok) throw snapshotError(result.errors[0].code, result.errors[0].message);
|
|
43
|
+
snapshot.focusFiles = Object.freeze([...snapshot.focusFiles]);
|
|
44
|
+
return Object.freeze(snapshot);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function validate(value = {}, options = {}) {
|
|
48
|
+
const errors = [];
|
|
49
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
50
|
+
return fail('invalid_execution_snapshot', 'Execution snapshot must be an object.');
|
|
51
|
+
}
|
|
52
|
+
if (value.schemaVersion !== undefined && Number(value.schemaVersion) !== SCHEMA_VERSION) {
|
|
53
|
+
errors.push(errorItem('invalid_execution_snapshot', `Unsupported execution snapshot schema version: ${value.schemaVersion}`));
|
|
54
|
+
}
|
|
55
|
+
if (!VALID_MODES.has(value.mode)) {
|
|
56
|
+
errors.push(errorItem('invalid_execution_snapshot', 'Execution snapshot mode is invalid.'));
|
|
57
|
+
}
|
|
58
|
+
const providerId = normalizeText(value.providerId);
|
|
59
|
+
if (!providerId) errors.push(errorItem('invalid_execution_snapshot', 'Execution snapshot provider is missing.'));
|
|
60
|
+
const revision = normalizeRevisionResult(value.providerRevision);
|
|
61
|
+
if (!revision.ok) {
|
|
62
|
+
errors.push(errorItem('provider_revision_conflict', revision.error));
|
|
63
|
+
} else if (providerId === 'builtin' && revision.value) {
|
|
64
|
+
errors.push(errorItem('provider_revision_conflict', 'Built-in Codex cannot carry a provider revision.'));
|
|
65
|
+
} else if (providerId !== 'builtin' && options.requireProviderRevision === true && !revision.value) {
|
|
66
|
+
errors.push(errorItem('provider_revision_conflict', 'The selected provider revision was not available when the run was submitted.'));
|
|
67
|
+
}
|
|
68
|
+
if (!Array.isArray(value.focusFiles) || value.focusFiles.length > 100) {
|
|
69
|
+
errors.push(errorItem('invalid_execution_snapshot', 'Execution snapshot focus files are invalid.'));
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
assertNoSecretFields(value);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
errors.push(errorItem(error.code, error.message));
|
|
75
|
+
}
|
|
76
|
+
return { ok: errors.length === 0, errors };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function normalizeRevision(value) {
|
|
80
|
+
const result = normalizeRevisionResult(value);
|
|
81
|
+
return result.ok ? result.value : '';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normalizeRevisionResult(value) {
|
|
85
|
+
if (value === undefined || value === null || value === '') return { ok: true, value: '' };
|
|
86
|
+
const text = typeof value === 'string' ? value.trim() : String(value);
|
|
87
|
+
if (!text) return { ok: true, value: '' };
|
|
88
|
+
const number = Number(text);
|
|
89
|
+
return Number.isSafeInteger(number) && number >= 0
|
|
90
|
+
? { ok: true, value: String(number) }
|
|
91
|
+
: { ok: false, value: '', error: 'Provider revision must be a finite non-negative integer.' };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function normalizePaths(value) {
|
|
95
|
+
const seen = new Set();
|
|
96
|
+
const result = [];
|
|
97
|
+
for (const raw of Array.isArray(value) ? value : []) {
|
|
98
|
+
const path = normalizeProjectPath(raw);
|
|
99
|
+
if (!path || seen.has(path)) continue;
|
|
100
|
+
seen.add(path);
|
|
101
|
+
result.push(path);
|
|
102
|
+
if (result.length >= 100) break;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function normalizeProjectPath(value) {
|
|
108
|
+
const result = [];
|
|
109
|
+
for (const segment of String(value || '').replace(/\0/g, '').replace(/\\/g, '/').replace(/^\/+/, '').split('/')) {
|
|
110
|
+
if (!segment || segment === '.') continue;
|
|
111
|
+
if (segment === '..') return '';
|
|
112
|
+
result.push(segment);
|
|
113
|
+
}
|
|
114
|
+
return result.join('/').trim();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function normalizeTimestamp(value) {
|
|
118
|
+
if (typeof value === 'string' && value) return value;
|
|
119
|
+
if (Number.isFinite(Number(value)) && Number(value) > 0) return new Date(Number(value)).toISOString();
|
|
120
|
+
return new Date().toISOString();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function assertNoSecretFields(value) {
|
|
124
|
+
for (const key of Object.keys(value && typeof value === 'object' ? value : {})) {
|
|
125
|
+
if (SECRET_FIELD_PATTERN.test(key)) {
|
|
126
|
+
throw snapshotError('invalid_execution_snapshot', `Execution snapshot cannot contain secret field "${key}".`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function cloneValue(value) {
|
|
132
|
+
return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function normalizeText(value) {
|
|
136
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function hasOwn(value, key) {
|
|
140
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function snapshotError(code, message) {
|
|
144
|
+
const error = new Error(message);
|
|
145
|
+
error.code = code;
|
|
146
|
+
return error;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function errorItem(code, message) {
|
|
150
|
+
return { code, message };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function fail(code, message) {
|
|
154
|
+
return { ok: false, errors: [errorItem(code, message)] };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
SCHEMA_VERSION,
|
|
159
|
+
TUPLE_FIELDS,
|
|
160
|
+
cloneValue,
|
|
161
|
+
hasOwn,
|
|
162
|
+
normalizeRevision,
|
|
163
|
+
normalizeSnapshot,
|
|
164
|
+
normalizeText,
|
|
165
|
+
snapshotError,
|
|
166
|
+
validate
|
|
167
|
+
};
|
|
168
|
+
});
|