-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add predict and predictions CLI commands #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| import { Command } from "commander"; | ||
| import { post } from "../client.js"; | ||
| import { printJson, printError } from "../output.js"; | ||
|
|
||
| /** | ||
| * `recoup predict` — run a neural engagement prediction on content. | ||
| * | ||
| * Sends the file URL and modality to POST /api/predictions, then | ||
| * displays the engagement score, peak moments, and weak spots. | ||
| */ | ||
| export const predictCommand = new Command("predict") | ||
| .description("Run a neural engagement prediction on video, audio, or text content") | ||
| .requiredOption("--url <fileUrl>", "Public URL to the content file") | ||
| .requiredOption( | ||
| "--modality <modality>", | ||
| "Content type: video, audio, or text", | ||
| ) | ||
| .option("--json", "Output as JSON") | ||
| .action(async (opts) => { | ||
| try { | ||
| const data = await post("/api/predictions", { | ||
| file_url: opts.url, | ||
| modality: opts.modality, | ||
| }); | ||
|
|
||
| if (opts.json) { | ||
| printJson(data); | ||
| return; | ||
| } | ||
|
|
||
| console.log(); | ||
| console.log(` Engagement Score: ${data.engagement_score}`); | ||
| console.log(` Modality: ${data.modality}`); | ||
| console.log( | ||
| ` Duration: ${data.total_duration_seconds}s`, | ||
| ); | ||
| console.log(` Inference Time: ${data.elapsed_seconds}s`); | ||
| console.log(); | ||
|
|
||
| const peaks = data.peak_moments as | ||
| | { time_seconds: number; score: number }[] | ||
| | undefined; | ||
| if (peaks && peaks.length > 0) { | ||
| console.log(" Peak Moments:"); | ||
| for (const p of peaks) { | ||
| console.log(` ${p.time_seconds}s → ${p.score}`); | ||
| } | ||
| console.log(); | ||
| } | ||
|
|
||
| const weak = data.weak_spots as | ||
| | { time_seconds: number; score: number }[] | ||
| | undefined; | ||
| if (weak && weak.length > 0) { | ||
| console.log(" Weak Spots:"); | ||
| for (const w of weak) { | ||
| console.log(` ${w.time_seconds}s → ${w.score}`); | ||
| } | ||
| console.log(); | ||
| } | ||
|
|
||
| console.log(` ID: ${data.id}`); | ||
| console.log(); | ||
| } catch (err) { | ||
| printError((err as Error).message); | ||
| } | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { Command } from "commander"; | ||
| import { get } from "../client.js"; | ||
| import { printJson, printTable, printError } from "../output.js"; | ||
|
|
||
| const listCommand = new Command("list") | ||
| .description("List past engagement predictions") | ||
| .option("--json", "Output as JSON") | ||
| .option("--limit <limit>", "Maximum results to return", "20") | ||
| .option("--offset <offset>", "Number of results to skip", "0") | ||
| .action(async (opts) => { | ||
| try { | ||
| const params: Record<string, string> = {}; | ||
| if (opts.limit) params.limit = opts.limit; | ||
| if (opts.offset) params.offset = opts.offset; | ||
|
|
||
| const data = await get("/api/predictions", params); | ||
| const predictions = | ||
| (data.predictions as Record<string, unknown>[]) || []; | ||
|
|
||
| if (opts.json) { | ||
| printJson(predictions); | ||
| } else { | ||
| printTable(predictions, [ | ||
| { key: "id", label: "ID" }, | ||
| { key: "modality", label: "MODALITY" }, | ||
| { key: "engagement_score", label: "SCORE" }, | ||
| { key: "created_at", label: "CREATED" }, | ||
| ]); | ||
| } | ||
| } catch (err) { | ||
| printError((err as Error).message); | ||
| } | ||
| }); | ||
|
|
||
| const getCommand = new Command("get") | ||
| .description("Get a specific prediction by ID") | ||
| .argument("<id>", "Prediction UUID") | ||
| .option("--json", "Output as JSON") | ||
| .action(async (id: string, opts) => { | ||
| try { | ||
| const data = await get(`/api/predictions/${id}`); | ||
|
|
||
| if (opts.json) { | ||
| printJson(data); | ||
| return; | ||
| } | ||
|
|
||
| console.log(); | ||
| console.log(` ID: ${data.id}`); | ||
| console.log(` Engagement Score: ${data.engagement_score}`); | ||
| console.log(` Modality: ${data.modality}`); | ||
| console.log(` File URL: ${data.file_url}`); | ||
| console.log( | ||
| ` Duration: ${data.total_duration_seconds}s`, | ||
| ); | ||
| console.log(` Inference Time: ${data.elapsed_seconds}s`); | ||
| console.log(` Created: ${data.created_at}`); | ||
| console.log(); | ||
|
|
||
| const peaks = data.peak_moments as | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The peak-moments and weak-spots rendering blocks are duplicated almost verbatim from Prompt for AI agents |
||
| | { time_seconds: number; score: number }[] | ||
| | undefined; | ||
| if (peaks && peaks.length > 0) { | ||
| console.log(" Peak Moments:"); | ||
| for (const p of peaks) { | ||
| console.log(` ${p.time_seconds}s → ${p.score}`); | ||
| } | ||
| console.log(); | ||
| } | ||
|
|
||
| const weak = data.weak_spots as | ||
| | { time_seconds: number; score: number }[] | ||
| | undefined; | ||
| if (weak && weak.length > 0) { | ||
| console.log(" Weak Spots:"); | ||
| for (const w of weak) { | ||
| console.log(` ${w.time_seconds}s → ${w.score}`); | ||
| } | ||
| console.log(); | ||
| } | ||
| } catch (err) { | ||
| printError((err as Error).message); | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Custom agent: Flag AI Slop and Fabricated Changes Remove this narrating JSDoc block — it restates what Prompt for AI agents |
||
| * `recoup predictions` — manage engagement prediction history. | ||
| * | ||
| * Subcommands: | ||
| * list — List past predictions with scores | ||
| * get — Get full prediction detail by ID | ||
| */ | ||
| export const predictionsCommand = new Command("predictions") | ||
| .description("Manage engagement prediction history") | ||
| .addCommand(listCommand) | ||
| .addCommand(getCommand); | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Custom agent: Flag AI Slop and Fabricated Changes
Narrating JSDoc that restates the code. The first line duplicates the
.description()string, and the rest summarizes the obviouspost()call andconsole.logoutput. Remove it or replace with genuinely useful context (e.g., expected API error codes, rate-limit behavior).Prompt for AI agents