feat(omo-codex): batch 20 (3 files)
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import { stdin as processStdin, stdout as processStdout } from "node:process";
|
||||||
|
|
||||||
|
import { runUserPromptSubmitHook } from "./codex-hook.js";
|
||||||
|
|
||||||
|
const command = process.argv[2];
|
||||||
|
const subcommand = process.argv[3];
|
||||||
|
|
||||||
|
if (command === "hook" && subcommand === "user-prompt-submit") {
|
||||||
|
await runHookCli();
|
||||||
|
} else {
|
||||||
|
process.stderr.write("Usage: omo-ultrawork hook user-prompt-submit\n");
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runHookCli(): Promise<void> {
|
||||||
|
const raw = await readStdin();
|
||||||
|
if (raw.trim().length === 0) return;
|
||||||
|
const parsed = parseHookInput(raw);
|
||||||
|
const output = runUserPromptSubmitHook(parsed);
|
||||||
|
if (output.length > 0) {
|
||||||
|
processStdout.write(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHookInput(raw: string): unknown | undefined {
|
||||||
|
try {
|
||||||
|
const parsed: unknown = JSON.parse(raw);
|
||||||
|
return parsed;
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof SyntaxError) return undefined;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readStdin(): Promise<string> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
let data = "";
|
||||||
|
processStdin.setEncoding("utf8");
|
||||||
|
processStdin.on("data", (chunk: string) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
processStdin.once("error", () => {
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
processStdin.once("end", () => {
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
|
import { ULTRAWORK_DIRECTIVE } from "./directive.js";
|
||||||
|
|
||||||
|
const ULTRAWORK_PATTERN = /\b(?:ultrawork|ulw)\b/i;
|
||||||
|
const CONTEXT_PRESSURE_MARKERS = [
|
||||||
|
"context compacted",
|
||||||
|
"context_length_exceeded",
|
||||||
|
"skill descriptions were shortened",
|
||||||
|
"context_too_large",
|
||||||
|
"codex ran out of room in the model's context window",
|
||||||
|
"your input exceeds the context window",
|
||||||
|
"long threads and multiple compactions",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type CodexUserPromptSubmitInput = {
|
||||||
|
readonly hook_event_name: "UserPromptSubmit";
|
||||||
|
readonly prompt: string;
|
||||||
|
readonly transcript_path?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface UserPromptSubmitHookOutput {
|
||||||
|
readonly hookSpecificOutput: {
|
||||||
|
readonly hookEventName: "UserPromptSubmit";
|
||||||
|
readonly additionalContext: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runUserPromptSubmitHook(input: unknown): string {
|
||||||
|
if (!isCodexUserPromptSubmitInput(input)) return "";
|
||||||
|
if (isContextPressureRecoveryPrompt(input.prompt)) return "";
|
||||||
|
if (isContextPressureTranscript(input.transcript_path)) return "";
|
||||||
|
return isUltraworkPrompt(input.prompt) ? formatAdditionalContextOutput(ULTRAWORK_DIRECTIVE) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isUltraworkPrompt(prompt: string): boolean {
|
||||||
|
return ULTRAWORK_PATTERN.test(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isContextPressureRecoveryPrompt(prompt: string): boolean {
|
||||||
|
const normalizedPrompt = prompt.toLowerCase();
|
||||||
|
return CONTEXT_PRESSURE_MARKERS.some((marker) => normalizedPrompt.includes(marker));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isContextPressureTranscript(transcriptPath: string | null | undefined): boolean {
|
||||||
|
if (transcriptPath === undefined || transcriptPath === null) return false;
|
||||||
|
try {
|
||||||
|
return isContextPressureRecoveryPrompt(readFileSync(transcriptPath, "utf8"));
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) return false;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatAdditionalContextOutput(additionalContext: string): string {
|
||||||
|
const normalizedContext = normalizeAdditionalContext(additionalContext);
|
||||||
|
if (normalizedContext.length === 0) return "";
|
||||||
|
const output: UserPromptSubmitHookOutput = {
|
||||||
|
hookSpecificOutput: {
|
||||||
|
hookEventName: "UserPromptSubmit",
|
||||||
|
additionalContext: normalizedContext,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return `${JSON.stringify(output)}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeAdditionalContext(additionalContext: string): string {
|
||||||
|
return additionalContext.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCodexUserPromptSubmitInput(value: unknown): value is CodexUserPromptSubmitInput {
|
||||||
|
return (
|
||||||
|
isRecord(value) &&
|
||||||
|
value["hook_event_name"] === "UserPromptSubmit" &&
|
||||||
|
typeof value["prompt"] === "string" &&
|
||||||
|
(value["transcript_path"] === undefined ||
|
||||||
|
value["transcript_path"] === null ||
|
||||||
|
typeof value["transcript_path"] === "string")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
|
export const ULTRAWORK_DIRECTIVE: string = readFileSync(new URL("../directive.md", import.meta.url), "utf8");
|
||||||
Reference in New Issue
Block a user