Codex Plugin Job Cancellation Cleanup: Operations and Source Code Analysis
When you cancel a job in the OpenAI Codex plugin, the system sends a turn interrupt to the shared app-server, terminates the running process, updates the job status to "cancelled", persists the state to storage, and removes the job from the active tracking list.
The openai/codex-plugin-cc repository implements a robust cleanup sequence when the /codex:cancel command is invoked. This ensures that brokered tasks are safely halted and the internal job state remains consistent. Below is the complete breakdown of the cleanup operations as implemented in the source code.
Step-by-Step Cleanup Operations
Turn Interrupt Signal to App-Server
The first cleanup action occurs in plugins/codex/scripts/codex-companion.mjs at lines 1017–1018. Before terminating the process, the plugin sends a turn interrupt to the shared app-server. This aborts any pending LLM requests and prevents the server from continuing to process tokens for the job being cancelled.
Process Termination and PID Clearing
If the job is running as a local process, the system terminates it and clears the process identifier. In plugins/codex/scripts/lib/job-control.mjs, the cancellation path explicitly sets job.pid = null after killing the process. This ensures the plugin does not attempt to interact with a defunct process during subsequent status checks.
Status and Phase Updates
The job record is updated to reflect the termination. According to lines 992–1002 in codex-companion.mjs, the status field is set to "cancelled" and the phase is also set to "cancelled" on the returned payload. This dual update guarantees that both the internal state and the user-facing response indicate the job is no longer active.
Persistent State Synchronization
After updating the job object, the changes are written to the persistent state store. The job-control.mjs module handles this persistence, ensuring that future queries via /codex:status return the cancelled status even if the session restarts. This write operation commits the cancelled state and the null PID to disk.
Active Job List Removal
The plugin maintains a list of active jobs to prevent duplicate operations. In plugins/codex/scripts/lib/tracked-jobs.mjs, the cancelled job is filtered out from the active jobs collection. This cleanup prevents the system from attempting to cancel the same job twice and ensures that resource counters accurately reflect only running work.
Response Payload Confirmation
The cancellation command returns a JSON payload confirming the operations. As verified in tests/runtime.test.mjs, the response includes status: "cancelled", turnInterruptAttempted: true, and turnInterrupted: true. These fields provide programmatic confirmation that the interrupt signal was sent and the job state was updated.
Code Examples
Cancelling a Job via CLI
Execute the cancel command from the repository root to terminate the active job:
node plugins/codex/scripts/codex-companion.mjs cancel --json
Programmatic Cancellation
Import the job control module to cancel a job within a Node.js application:
import { cancelJob } from './plugins/codex/scripts/lib/job-control.mjs';
async function terminateJob(jobId) {
const result = await cancelJob(jobId);
console.log(`Job ${jobId} status: ${result.status}`);
console.log(`Turn interrupted: ${result.turnInterrupted}`);
}
Expected Cancellation Response
The JSON output confirms the cleanup operations completed:
{
"status": "cancelled",
"jobId": "task-live",
"turnInterruptAttempted": true,
"turnInterrupted": true
}
Key Source Files
The cleanup logic spans four primary files in the repository:
plugins/codex/scripts/codex-companion.mjs– Implements the CLI entry point for thecancelcommand and assembles the JSON response with turn interrupt logic (lines 992–1002, 1017–1018).plugins/codex/scripts/lib/job-control.mjs– Contains core logic that updates job status to"cancelled"and clears the PID field.plugins/codex/scripts/lib/tracked-jobs.mjs– Manages the active job collection and filters out cancelled entries.tests/runtime.test.mjs– Validates the cancellation flow, confirming status updates and turn-interrupt handling.
Summary
- Turn interrupt is sent first to abort pending LLM requests on the shared app-server.
- Process termination kills the local job process and clears the PID in
job-control.mjs. - Status updates set both the status and phase to
"cancelled"in the job record. - Persistence writes the cancelled state to storage for consistency across sessions.
- Active list cleanup removes the job from the tracked active jobs list to prevent duplicate cancellation attempts.
- Confirmation returns a JSON payload with
turnInterruptAttemptedandturnInterruptedflags set totrue.
Frequently Asked Questions
What happens if I cancel a job that has already completed?
If the job is no longer active, the cancellation command will return an error indicating there is no active job to cancel. The job-control.mjs logic checks for active status before attempting termination, preventing unnecessary operations on completed or failed jobs.
Does the turn interrupt affect other jobs running on the shared app-server?
No, the turn interrupt is targeted specifically at the turn associated with the job being cancelled. According to the implementation in codex-companion.mjs, the interrupt signal is scoped to the specific job context, leaving other concurrent jobs unaffected.
Where is the cancelled job status stored permanently?
The job status is persisted through the state management layer in job-control.mjs. After cancellation, the updated job object (with "cancelled" status and null PID) is written to the persistent state store, ensuring the status survives plugin restarts and remains queryable via the status command.
How can I verify that a job was successfully cancelled?
Check the JSON response from the cancel command for status: "cancelled" and turnInterrupted: true. Additionally, you can query the job status using the status command; a successfully cancelled job will show "cancelled" in both the status and phase fields, with a null PID value.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →