chore: import broken Phase-1 extension as received

Snapshot of /home/parf/Downloads/manifest.zip as delivered, before any
GSD-driven remediation. Contains a partially-broken first attempt at the
Russian SPEC "Тз расширение фаза1.md" (Phase 1 of operator-session-recorder).

Source layout:
- manifest.json — MV3 declaration with tabCapture/activeTab/downloads/etc.
- src/background/index.ts — service worker (video buffer + archive packaging)
- src/content/index.ts — rrweb + user-event logger
- src/popup/{index.html,index.ts,style.css} — Russian popup UI
- offscreen/{index.html,index.ts} — orphaned offscreen (see audit)
- vite.config.ts — inline plugin emitting a separate live offscreen.js
- generate-icons.js, icons/ — minimal PNG icons
- "Тз расширение фаза1.md" — authoritative Russian SPEC

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 15:16:23 +02:00
commit 555eb0543f
21 changed files with 3935 additions and 0 deletions

10
offscreen/index.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Offscreen Page</title>
</head>
<body>
<script src="./index.ts" type="module"></script>
</body>
</html>

60
offscreen/index.ts Normal file
View File

@@ -0,0 +1,60 @@
let mediaRecorder: MediaRecorder | null = null;
let videoChunks: Blob[] = [];
// Запись видео
async function startRecording(streamId: string) {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
mandatory: {
chromeMediaSource: 'tab',
chromeMediaSourceId: streamId
}
} as any,
audio: false
});
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
videoChunks.push(event.data);
chrome.runtime.sendMessage({
type: 'VIDEO_CHUNK',
data: event.data,
timestamp: Date.now()
});
}
};
mediaRecorder.start(1000);
}
// Остановка записи
function stopRecording() {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
}
}
// Получение чанков
function getChunks(): Blob[] {
return videoChunks;
}
// Обработка сообщений
chrome.runtime.onMessage.addListener((message) => {
switch (message.type) {
case 'START_RECORDING':
startRecording(message.streamId);
break;
case 'STOP_RECORDING':
stopRecording();
break;
case 'GET_CHUNKS':
chrome.runtime.sendMessage({
type: 'CHUNKS_RESPONSE',
chunks: getChunks()
});
break;
}
});