Last active
June 9, 2025 03:39
-
-
Save toriningen/9f7b4d663902ae62654613dc65d51028 to your computer and use it in GitHub Desktop.
Notify when a Codex task completes or fails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Codex Task Notifier | |
// @namespace http://tampermonkey.net/ | |
// @version 1.1 | |
// @description Notify when a Codex task completes or fails | |
// @match https://chatgpt.com/codex/tasks/* | |
// @grant GM_notification | |
// @grant window.focus | |
// @run-at document-end | |
// @updateURL https://gist.githubusercontent.com/toriningen/9f7b4d663902ae62654613dc65d51028/raw/codex-notifier.user.js | |
// @downloadURL https://gist.githubusercontent.com/toriningen/9f7b4d663902ae62654613dc65d51028/raw/codex-notifier.user.js | |
// @supportURL https://gist.github.com/toriningen/9f7b4d663902ae62654613dc65d51028 | |
// ==/UserScript== | |
(async function() { | |
'use strict'; | |
const ICON_SUCCESS = "data:image/png;base64,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"; | |
const ICON_FAILURE = "data:image/png;base64,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"; | |
const CHECK_INTERVAL = 5000; | |
const STATUS_RUNNING = "running"; | |
const STATUS_SUCCESS = "success"; | |
const STATUS_FAILURE = "failure"; | |
function delay(timeout) { | |
return new Promise((resolve) => { | |
setTimeout(resolve, timeout); | |
}); | |
} | |
function getTaskName() { | |
const el = document.querySelector('div.min-w-0:nth-child(3) > div:nth-child(1)'); | |
if (el) { | |
return el.textContent.trim(); | |
} | |
return "(unknown task)"; | |
} | |
function getStatus() { | |
const footer = document.querySelector('#wham-message-modal-footer'); | |
if (!footer) { | |
return STATUS_RUNNING; | |
} | |
if (footer.querySelector('#prompt-textarea')) { | |
return STATUS_SUCCESS; | |
} else { | |
return STATUS_FAILURE; | |
} | |
} | |
async function waitUntilComplete() { | |
console.debug(`codex-notifier: wait until complete`); | |
while (true) { | |
const status = getStatus(); | |
if (status != STATUS_RUNNING) { | |
return status == STATUS_SUCCESS; | |
} | |
await delay(CHECK_INTERVAL); | |
} | |
} | |
async function waitUntilRunning() { | |
console.debug(`codex-notifier: wait until running`); | |
while (true) { | |
const status = getStatus(); | |
if (status == STATUS_RUNNING) { | |
return; | |
} | |
await delay(CHECK_INTERVAL); | |
} | |
} | |
while (true) { | |
await waitUntilRunning(); | |
const success = await waitUntilComplete(); | |
const title = `Codex task ${success ? "completed" : "failed"}`; | |
const text = getTaskName(); | |
const image = success ? ICON_SUCCESS : ICON_FAILURE; | |
console.debug(`codex-notifier: showing notification`); | |
GM_notification({ | |
title, | |
text, | |
image, | |
timeout: 0, | |
onclick(event) { | |
console.debug(`codex-notifier: notification clicked`); | |
window.focus(); | |
} | |
}); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment