diff --git a/packages/cli/package.json b/packages/cli/package.json index 2ecc9704..f28db9f5 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.17.9", + "version": "0.17.10", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/commands/feedback.ts b/packages/cli/src/commands/feedback.ts new file mode 100644 index 00000000..b0d248e2 --- /dev/null +++ b/packages/cli/src/commands/feedback.ts @@ -0,0 +1,50 @@ +import pc from "picocolors"; +import { asyncTryCatch } from "../shared/result.js"; + +const POSTHOG_TOKEN = "phc_7ToS2jDeWBlMu4n2JoNzoA1FnArdKwFMFoHVnAqQ6O1"; +const POSTHOG_URL = "https://us.i.posthog.com/i/v0/e/"; +const SURVEY_ID = "019ce7ef-c3e7-0000-415b-729f190e09bc"; + +export async function cmdFeedback(args: string[]): Promise { + const message = args.join(" ").trim(); + + if (!message) { + console.error(pc.red("Error: Please provide your feedback message.")); + console.error(`\nUsage: ${pc.cyan('spawn feedback "your feedback here"')}`); + process.exit(1); + } + + const body = { + token: POSTHOG_TOKEN, + distinct_id: "anon", + event: "survey sent", + properties: { + $survey_id: SURVEY_ID, + $survey_response: message, + $survey_completed: true, + source: "cli", + }, + }; + + const result = await asyncTryCatch(async () => { + const res = await fetch(POSTHOG_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + signal: AbortSignal.timeout(10_000), + }); + + if (!res.ok) { + throw new Error(`PostHog returned ${String(res.status)}`); + } + }); + + if (!result.ok) { + console.error(pc.red("Failed to send feedback. Please try again later.")); + process.exit(1); + } + + console.log(pc.green("Thanks for your feedback!")); +} diff --git a/packages/cli/src/commands/help.ts b/packages/cli/src/commands/help.ts index 98005932..55a83754 100644 --- a/packages/cli/src/commands/help.ts +++ b/packages/cli/src/commands/help.ts @@ -39,6 +39,7 @@ function getHelpUsageSection(): string { spawn matrix Full availability matrix (alias: m) spawn agents List all agents with descriptions spawn clouds List all cloud providers + spawn feedback "message" Send feedback to the Spawn team spawn update Check for CLI updates spawn version Show version (or --version, -v) spawn help Show this help message (or --help, -h)`; diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index b7ac92ab..2dddae54 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -2,6 +2,8 @@ // delete.ts — cmdDelete export { cmdDelete } from "./delete.js"; +// feedback.ts — cmdFeedback +export { cmdFeedback } from "./feedback.js"; // help.ts — cmdHelp export { cmdHelp } from "./help.js"; // info.ts — cmdMatrix, cmdAgents, cmdClouds, cmdAgentInfo, cmdCloudInfo diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5a220f62..5a1d58df 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -9,6 +9,7 @@ import { cmdCloudInfo, cmdClouds, cmdDelete, + cmdFeedback, cmdHelp, cmdInteractive, cmdLast, @@ -737,6 +738,12 @@ async function main(): Promise { return; } + // ── `spawn feedback` — bypass flag parsing; rest of args are the message ─── + if (rawArgs[0] === "feedback") { + await cmdFeedback(rawArgs.slice(1)); + return; + } + const args = expandEqualsFlags(rawArgs); await checkForUpdates();