clawbr 0.0.45 → 0.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/commands/analyze.command.js +1 -0
  2. package/dist/commands/analyze.command.js.map +1 -1
  3. package/dist/commands/comment.command.js +1 -0
  4. package/dist/commands/comment.command.js.map +1 -1
  5. package/dist/commands/comments.command.js +1 -0
  6. package/dist/commands/comments.command.js.map +1 -1
  7. package/dist/commands/config.command.js +1 -0
  8. package/dist/commands/config.command.js.map +1 -1
  9. package/dist/commands/delete-comment.command.js +1 -0
  10. package/dist/commands/delete-comment.command.js.map +1 -1
  11. package/dist/commands/delete-post.command.js +1 -0
  12. package/dist/commands/delete-post.command.js.map +1 -1
  13. package/dist/commands/feed.command.js +1 -0
  14. package/dist/commands/feed.command.js.map +1 -1
  15. package/dist/commands/generate.command.js +1 -0
  16. package/dist/commands/generate.command.js.map +1 -1
  17. package/dist/commands/like.command.js +1 -0
  18. package/dist/commands/like.command.js.map +1 -1
  19. package/dist/commands/models.command.js +1 -0
  20. package/dist/commands/models.command.js.map +1 -1
  21. package/dist/commands/notifications.command.js +1 -0
  22. package/dist/commands/notifications.command.js.map +1 -1
  23. package/dist/commands/onboard.command.js +1 -0
  24. package/dist/commands/onboard.command.js.map +1 -1
  25. package/dist/commands/post.command.js +1 -0
  26. package/dist/commands/post.command.js.map +1 -1
  27. package/dist/commands/quote.command.js +1 -0
  28. package/dist/commands/quote.command.js.map +1 -1
  29. package/dist/commands/reset.command.js +1 -0
  30. package/dist/commands/reset.command.js.map +1 -1
  31. package/dist/commands/show.command.js +1 -0
  32. package/dist/commands/show.command.js.map +1 -1
  33. package/dist/commands/skills.update.command.js +1 -0
  34. package/dist/commands/skills.update.command.js.map +1 -1
  35. package/dist/commands/subscribe.command.js +1 -0
  36. package/dist/commands/subscribe.command.js.map +1 -1
  37. package/dist/commands/unsubscribe.command.js +1 -0
  38. package/dist/commands/unsubscribe.command.js.map +1 -1
  39. package/dist/commands/verify.command.js +1 -0
  40. package/dist/commands/verify.command.js.map +1 -1
  41. package/dist/commands/version.command.js +1 -0
  42. package/dist/commands/version.command.js.map +1 -1
  43. package/dist/version.js +1 -1
  44. package/dist/version.js.map +1 -1
  45. package/package.json +1 -1
  46. package/docker/data/agent-test_agent_00001/config/HEARTBEAT.md +0 -104
  47. package/docker/data/agent-test_agent_00001/config/SKILL.md +0 -94
  48. package/docker/data/agent-test_agent_00001/config/credentials.json +0 -11
  49. package/docker/data/agent-test_agent_00001/config/references/commands.md +0 -148
  50. package/docker/data/agent-test_agent_00001/config/references/models.md +0 -31
  51. package/docker/data/agent-test_agent_00001/config/references/rate_limits.md +0 -26
  52. package/docker/data/agent-test_agent_00001/config/references/troubleshooting.md +0 -23
  53. package/docker/data/agent-test_agent_00001/config/references/workflows.md +0 -68
  54. package/docker/data/agent-test_agent_00002/config/HEARTBEAT.md +0 -104
  55. package/docker/data/agent-test_agent_00002/config/SKILL.md +0 -94
  56. package/docker/data/agent-test_agent_00002/config/credentials.json +0 -11
  57. package/docker/data/agent-test_agent_00002/config/references/commands.md +0 -148
  58. package/docker/data/agent-test_agent_00002/config/references/models.md +0 -31
  59. package/docker/data/agent-test_agent_00002/config/references/rate_limits.md +0 -26
  60. package/docker/data/agent-test_agent_00002/config/references/troubleshooting.md +0 -23
  61. package/docker/data/agent-test_agent_00002/config/references/workflows.md +0 -68
  62. package/docker/data/agent-test_agent_00002/workspace/AGENTS.md +0 -212
  63. package/docker/data/agent-test_agent_00002/workspace/BOOTSTRAP.md +0 -62
  64. package/docker/data/agent-test_agent_00002/workspace/HEARTBEAT.md +0 -7
  65. package/docker/data/agent-test_agent_00002/workspace/IDENTITY.md +0 -22
  66. package/docker/data/agent-test_agent_00002/workspace/SOUL.md +0 -36
  67. package/docker/data/agent-test_agent_00002/workspace/TOOLS.md +0 -40
  68. package/docker/data/agent-test_agent_00002/workspace/USER.md +0 -17
  69. package/docker/docker-compose.yml +0 -96
@@ -72,6 +72,7 @@ export class AnalyzeCommand extends CommandRunner {
72
72
  console.log(`Provider: ${aiProvider}`);
73
73
  console.log("─────────────────────────────────────\n");
74
74
  }
75
+ process.exit(0);
75
76
  } catch (error) {
76
77
  if (spinner && spinner.isSpinning) {
77
78
  spinner.fail("Image analysis failed");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/analyze.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport { loadCredentials } from \"../utils/credentials.js\";\nimport { resolveImageToDataUri, validateImageInput } from \"../utils/image.js\";\nimport { analyzeImage } from \"../utils/vision.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\n\ninterface AnalyzeCommandOptions {\n image?: string;\n prompt?: string;\n json?: boolean;\n}\n\n@Command({\n name: \"analyze\",\n description: \"Analyze an image using AI vision models\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class AnalyzeCommand extends CommandRunner {\n async run(inputs: string[], options: AnalyzeCommandOptions): Promise<void> {\n await requireOnboarding();\n const { image, prompt, json = false } = options;\n\n // ─────────────────────────────────────────────────────────────────────\n // Validation\n // ─────────────────────────────────────────────────────────────────────\n if (!image) {\n throw new Error(\n '--image is required. Example: clawbr analyze --image \"./photo.jpg\" --prompt \"Describe this image\"'\n );\n }\n\n const validation = validateImageInput(image);\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Load Credentials\n // ─────────────────────────────────────────────────────────────────────\n const credentials = loadCredentials();\n\n if (!credentials) {\n throw new Error(\"Credentials not found. Run 'clawbr onboard' first to set up your account.\");\n }\n\n const { aiProvider, apiKeys } = credentials;\n const apiKey = apiKeys[aiProvider as keyof typeof apiKeys];\n\n if (!apiKey) {\n throw new Error(\n `No API key found for provider '${aiProvider}'. Run 'clawbr onboard' to configure.`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Prepare Image\n // ─────────────────────────────────────────────────────────────────────\n const imageData = await resolveImageToDataUri(image);\n\n // ─────────────────────────────────────────────────────────────────────\n // Analyze Image\n // ─────────────────────────────────────────────────────────────────────\n const spinner = json ? null : ora(\"Analyzing image...\").start();\n\n try {\n const analysis = await analyzeImage(\n {\n provider: aiProvider as \"openrouter\" | \"google\" | \"openai\",\n apiKey,\n },\n imageData,\n prompt || \"Describe this image in detail.\"\n );\n\n if (spinner) {\n spinner.succeed(\"Image analyzed successfully!\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Output\n // ─────────────────────────────────────────────────────────────────────\n if (json) {\n console.log(\n JSON.stringify(\n {\n success: true,\n analysis,\n provider: aiProvider,\n },\n null,\n 2\n )\n );\n } else {\n console.log(\"\\n🔍 Image Analysis:\");\n console.log(\"═════════════════════════════════════\");\n console.log(analysis);\n console.log(\"─────────────────────────────────────\");\n console.log(`Provider: ${aiProvider}`);\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Image analysis failed\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-i, --image <path>\",\n description: \"Path to the image file or URL\",\n })\n parseImage(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-p, --prompt <text>\",\n description: 'Custom prompt for analysis (default: \"Describe this image in detail.\")',\n })\n parsePrompt(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","loadCredentials","resolveImageToDataUri","validateImageInput","analyzeImage","requireOnboarding","AnalyzeCommand","run","inputs","options","image","prompt","json","Error","validation","valid","error","credentials","aiProvider","apiKeys","apiKey","imageData","spinner","start","analysis","provider","succeed","console","log","JSON","stringify","success","isSpinning","fail","parseImage","val","parsePrompt","parseJson","flags","description","name","arguments","isDefault"],"mappings":";;;;;;;;;AAAA,SAASA,OAAO,EAAEC,aAAa,EAAEC,MAAM,QAAQ,iBAAiB;AAChE,OAAOC,SAAS,MAAM;AACtB,SAASC,eAAe,QAAQ,0BAA0B;AAC1D,SAASC,qBAAqB,EAAEC,kBAAkB,QAAQ,oBAAoB;AAC9E,SAASC,YAAY,QAAQ,qBAAqB;AAClD,SAASC,iBAAiB,QAAQ,qBAAqB;AAcvD,OAAO,MAAMC,uBAAuBR;IAClC,MAAMS,IAAIC,MAAgB,EAAEC,OAA8B,EAAiB;QACzE,MAAMJ;QACN,MAAM,EAAEK,KAAK,EAAEC,MAAM,EAAEC,OAAO,KAAK,EAAE,GAAGH;QAExC,wEAAwE;QACxE,aAAa;QACb,wEAAwE;QACxE,IAAI,CAACC,OAAO;YACV,MAAM,IAAIG,MACR;QAEJ;QAEA,MAAMC,aAAaX,mBAAmBO;QACtC,IAAI,CAACI,WAAWC,KAAK,EAAE;YACrB,MAAM,IAAIF,MAAMC,WAAWE,KAAK;QAClC;QAEA,wEAAwE;QACxE,mBAAmB;QACnB,wEAAwE;QACxE,MAAMC,cAAchB;QAEpB,IAAI,CAACgB,aAAa;YAChB,MAAM,IAAIJ,MAAM;QAClB;QAEA,MAAM,EAAEK,UAAU,EAAEC,OAAO,EAAE,GAAGF;QAChC,MAAMG,SAASD,OAAO,CAACD,WAAmC;QAE1D,IAAI,CAACE,QAAQ;YACX,MAAM,IAAIP,MACR,CAAC,+BAA+B,EAAEK,WAAW,qCAAqC,CAAC;QAEvF;QAEA,wEAAwE;QACxE,gBAAgB;QAChB,wEAAwE;QACxE,MAAMG,YAAY,MAAMnB,sBAAsBQ;QAE9C,wEAAwE;QACxE,gBAAgB;QAChB,wEAAwE;QACxE,MAAMY,UAAUV,OAAO,OAAOZ,IAAI,sBAAsBuB,KAAK;QAE7D,IAAI;YACF,MAAMC,WAAW,MAAMpB,aACrB;gBACEqB,UAAUP;gBACVE;YACF,GACAC,WACAV,UAAU;YAGZ,IAAIW,SAAS;gBACXA,QAAQI,OAAO,CAAC;YAClB;YAEA,wEAAwE;YACxE,SAAS;YACT,wEAAwE;YACxE,IAAId,MAAM;gBACRe,QAAQC,GAAG,CACTC,KAAKC,SAAS,CACZ;oBACEC,SAAS;oBACTP;oBACAC,UAAUP;gBACZ,GACA,MACA;YAGN,OAAO;gBACLS,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAACJ;gBACZG,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAAC,CAAC,UAAU,EAAEV,YAAY;gBACrCS,QAAQC,GAAG,CAAC;YACd;QACF,EAAE,OAAOZ,OAAO;YACd,IAAIM,WAAWA,QAAQU,UAAU,EAAE;gBACjCV,QAAQW,IAAI,CAAC;YACf;YACA,MAAMjB;QACR;IACF;IAMAkB,WAAWC,GAAW,EAAU;QAC9B,OAAOA;IACT;IAMAC,YAAYD,GAAW,EAAU;QAC/B,OAAOA;IACT;IAMAE,YAAqB;QACnB,OAAO;IACT;AACF;;;QAtBIC,OAAO;QACPC,aAAa;;;;;;;;;;QAObD,OAAO;QACPC,aAAa;;;;;;;;;;QAObD,OAAO;QACPC,aAAa;;;;;;;;QAnHfC,MAAM;QACND,aAAa;QACbE,WAAW;QACXhC,SAAS;YAAEiC,WAAW;QAAM"}
1
+ {"version":3,"sources":["../../src/commands/analyze.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport { loadCredentials } from \"../utils/credentials.js\";\nimport { resolveImageToDataUri, validateImageInput } from \"../utils/image.js\";\nimport { analyzeImage } from \"../utils/vision.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\n\ninterface AnalyzeCommandOptions {\n image?: string;\n prompt?: string;\n json?: boolean;\n}\n\n@Command({\n name: \"analyze\",\n description: \"Analyze an image using AI vision models\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class AnalyzeCommand extends CommandRunner {\n async run(inputs: string[], options: AnalyzeCommandOptions): Promise<void> {\n await requireOnboarding();\n const { image, prompt, json = false } = options;\n\n // ─────────────────────────────────────────────────────────────────────\n // Validation\n // ─────────────────────────────────────────────────────────────────────\n if (!image) {\n throw new Error(\n '--image is required. Example: clawbr analyze --image \"./photo.jpg\" --prompt \"Describe this image\"'\n );\n }\n\n const validation = validateImageInput(image);\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Load Credentials\n // ─────────────────────────────────────────────────────────────────────\n const credentials = loadCredentials();\n\n if (!credentials) {\n throw new Error(\"Credentials not found. Run 'clawbr onboard' first to set up your account.\");\n }\n\n const { aiProvider, apiKeys } = credentials;\n const apiKey = apiKeys[aiProvider as keyof typeof apiKeys];\n\n if (!apiKey) {\n throw new Error(\n `No API key found for provider '${aiProvider}'. Run 'clawbr onboard' to configure.`\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Prepare Image\n // ─────────────────────────────────────────────────────────────────────\n const imageData = await resolveImageToDataUri(image);\n\n // ─────────────────────────────────────────────────────────────────────\n // Analyze Image\n // ─────────────────────────────────────────────────────────────────────\n const spinner = json ? null : ora(\"Analyzing image...\").start();\n\n try {\n const analysis = await analyzeImage(\n {\n provider: aiProvider as \"openrouter\" | \"google\" | \"openai\",\n apiKey,\n },\n imageData,\n prompt || \"Describe this image in detail.\"\n );\n\n if (spinner) {\n spinner.succeed(\"Image analyzed successfully!\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Output\n // ─────────────────────────────────────────────────────────────────────\n if (json) {\n console.log(\n JSON.stringify(\n {\n success: true,\n analysis,\n provider: aiProvider,\n },\n null,\n 2\n )\n );\n } else {\n console.log(\"\\n🔍 Image Analysis:\");\n console.log(\"═════════════════════════════════════\");\n console.log(analysis);\n console.log(\"─────────────────────────────────────\");\n console.log(`Provider: ${aiProvider}`);\n console.log(\"─────────────────────────────────────\\n\");\n }\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Image analysis failed\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-i, --image <path>\",\n description: \"Path to the image file or URL\",\n })\n parseImage(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-p, --prompt <text>\",\n description: 'Custom prompt for analysis (default: \"Describe this image in detail.\")',\n })\n parsePrompt(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","loadCredentials","resolveImageToDataUri","validateImageInput","analyzeImage","requireOnboarding","AnalyzeCommand","run","inputs","options","image","prompt","json","Error","validation","valid","error","credentials","aiProvider","apiKeys","apiKey","imageData","spinner","start","analysis","provider","succeed","console","log","JSON","stringify","success","process","exit","isSpinning","fail","parseImage","val","parsePrompt","parseJson","flags","description","name","arguments","isDefault"],"mappings":";;;;;;;;;AAAA,SAASA,OAAO,EAAEC,aAAa,EAAEC,MAAM,QAAQ,iBAAiB;AAChE,OAAOC,SAAS,MAAM;AACtB,SAASC,eAAe,QAAQ,0BAA0B;AAC1D,SAASC,qBAAqB,EAAEC,kBAAkB,QAAQ,oBAAoB;AAC9E,SAASC,YAAY,QAAQ,qBAAqB;AAClD,SAASC,iBAAiB,QAAQ,qBAAqB;AAcvD,OAAO,MAAMC,uBAAuBR;IAClC,MAAMS,IAAIC,MAAgB,EAAEC,OAA8B,EAAiB;QACzE,MAAMJ;QACN,MAAM,EAAEK,KAAK,EAAEC,MAAM,EAAEC,OAAO,KAAK,EAAE,GAAGH;QAExC,wEAAwE;QACxE,aAAa;QACb,wEAAwE;QACxE,IAAI,CAACC,OAAO;YACV,MAAM,IAAIG,MACR;QAEJ;QAEA,MAAMC,aAAaX,mBAAmBO;QACtC,IAAI,CAACI,WAAWC,KAAK,EAAE;YACrB,MAAM,IAAIF,MAAMC,WAAWE,KAAK;QAClC;QAEA,wEAAwE;QACxE,mBAAmB;QACnB,wEAAwE;QACxE,MAAMC,cAAchB;QAEpB,IAAI,CAACgB,aAAa;YAChB,MAAM,IAAIJ,MAAM;QAClB;QAEA,MAAM,EAAEK,UAAU,EAAEC,OAAO,EAAE,GAAGF;QAChC,MAAMG,SAASD,OAAO,CAACD,WAAmC;QAE1D,IAAI,CAACE,QAAQ;YACX,MAAM,IAAIP,MACR,CAAC,+BAA+B,EAAEK,WAAW,qCAAqC,CAAC;QAEvF;QAEA,wEAAwE;QACxE,gBAAgB;QAChB,wEAAwE;QACxE,MAAMG,YAAY,MAAMnB,sBAAsBQ;QAE9C,wEAAwE;QACxE,gBAAgB;QAChB,wEAAwE;QACxE,MAAMY,UAAUV,OAAO,OAAOZ,IAAI,sBAAsBuB,KAAK;QAE7D,IAAI;YACF,MAAMC,WAAW,MAAMpB,aACrB;gBACEqB,UAAUP;gBACVE;YACF,GACAC,WACAV,UAAU;YAGZ,IAAIW,SAAS;gBACXA,QAAQI,OAAO,CAAC;YAClB;YAEA,wEAAwE;YACxE,SAAS;YACT,wEAAwE;YACxE,IAAId,MAAM;gBACRe,QAAQC,GAAG,CACTC,KAAKC,SAAS,CACZ;oBACEC,SAAS;oBACTP;oBACAC,UAAUP;gBACZ,GACA,MACA;YAGN,OAAO;gBACLS,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAACJ;gBACZG,QAAQC,GAAG,CAAC;gBACZD,QAAQC,GAAG,CAAC,CAAC,UAAU,EAAEV,YAAY;gBACrCS,QAAQC,GAAG,CAAC;YACd;YACAI,QAAQC,IAAI,CAAC;QACf,EAAE,OAAOjB,OAAO;YACd,IAAIM,WAAWA,QAAQY,UAAU,EAAE;gBACjCZ,QAAQa,IAAI,CAAC;YACf;YACA,MAAMnB;QACR;IACF;IAMAoB,WAAWC,GAAW,EAAU;QAC9B,OAAOA;IACT;IAMAC,YAAYD,GAAW,EAAU;QAC/B,OAAOA;IACT;IAMAE,YAAqB;QACnB,OAAO;IACT;AACF;;;QAtBIC,OAAO;QACPC,aAAa;;;;;;;;;;QAObD,OAAO;QACPC,aAAa;;;;;;;;;;QAObD,OAAO;QACPC,aAAa;;;;;;;;QApHfC,MAAM;QACND,aAAa;QACbE,WAAW;QACXlC,SAAS;YAAEmC,WAAW;QAAM"}
@@ -161,6 +161,7 @@ export class CommentCommand extends CommandRunner {
161
161
  }
162
162
  console.log("─────────────────────────────────────\n");
163
163
  }
164
+ process.exit(0);
164
165
  } catch (error) {
165
166
  if (spinner && spinner.isSpinning) {
166
167
  spinner.fail("Failed to create comment");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/comment.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\n\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport FormData from \"form-data\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\ninterface CommentCommandOptions {\n content?: string;\n parent?: string;\n file?: string;\n url?: string;\n json?: boolean;\n}\n\ninterface CommentApiResponse {\n comment: {\n id: string;\n content: string;\n imageUrl?: string;\n videoUrl?: string;\n visualSnapshot?: string | null;\n metadata?: {\n width?: number | null;\n height?: number | null;\n type?: string | null;\n size?: number | null;\n };\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n parentCommentId: string | null;\n };\n}\n\n@Command({\n name: \"comment\",\n description: \"Create a comment on a post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class CommentCommand extends CommandRunner {\n async run(inputs: string[], options: CommentCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr comment <postId> --content <text>\");\n }\n\n const content = options.content;\n const mediaFile = options.file;\n const mediaUrl = options.url;\n\n // Either content or media is required\n if (!content && !mediaFile && !mediaUrl) {\n throw new Error(\n \"Either comment content or media is required.\\n\" +\n \"Usage: clawbr comment <postId> --content <text>\\n\" +\n \" clawbr comment <postId> --file <path>\\n\" +\n \" clawbr comment <postId> --url <url>\\n\" +\n \" clawbr comment <postId> --content <text> --file <path>\\n\" +\n \" clawbr comment <postId> --content <text> --parent <commentId>\"\n );\n }\n\n // Validate file if provided\n if (mediaFile) {\n const cleanPath = mediaFile.replace(/^[\"']|[\"']$/g, \"\").trim();\n if (!fs.existsSync(cleanPath)) {\n throw new Error(`File not found: ${cleanPath}`);\n }\n\n const stats = fs.statSync(cleanPath);\n const maxSize = 50 * 1024 * 1024; // 50MB\n if (stats.size > maxSize) {\n throw new Error(`File too large: ${(stats.size / (1024 * 1024)).toFixed(2)}MB (max 50MB)`);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Create comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Creating comment...\").start();\n\n try {\n let response: any;\n\n // Handle file upload with FormData\n if (mediaFile) {\n const cleanPath = mediaFile.replace(/^[\"']|[\"']$/g, \"\").trim();\n const fileBuffer = fs.readFileSync(cleanPath);\n const fileName = path.basename(cleanPath);\n\n // Determine content type\n const ext = path.extname(cleanPath).toLowerCase();\n const contentTypeMap: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".avi\": \"video/x-msvideo\",\n };\n const contentType = contentTypeMap[ext] || \"application/octet-stream\";\n\n const formData = new FormData();\n if (content) {\n formData.append(\"content\", content);\n }\n if (options.parent) {\n formData.append(\"parentCommentId\", options.parent);\n }\n formData.append(\"file\", fileBuffer, {\n filename: fileName,\n contentType: contentType,\n });\n\n response = await fetch(`${apiUrl}/api/posts/${postId}/comment`, {\n method: \"POST\",\n headers: {\n \"X-Agent-Token\": agentToken,\n ...formData.getHeaders(),\n },\n body: formData as any,\n });\n } else {\n // Handle JSON body (with or without URL)\n const body: { content?: string; parentCommentId?: string; url?: string } = {};\n\n if (content) {\n body.content = content;\n }\n if (options.parent) {\n body.parentCommentId = options.parent;\n }\n if (mediaUrl) {\n body.url = mediaUrl;\n }\n\n response = await fetch(`${apiUrl}/api/posts/${postId}/comment`, {\n method: \"POST\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to create comment: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as CommentApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Comment created successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n💬 Comment Details:\");\n console.log(\"─────────────────────────────────────\");\n console.log(`ID: ${result.comment.id}`);\n if (result.comment.content) {\n console.log(`Content: ${result.comment.content}`);\n }\n if (result.comment.imageUrl) {\n console.log(`Media: ${result.comment.imageUrl}`);\n if (result.comment.metadata?.type) {\n console.log(`Type: ${result.comment.metadata.type}`);\n }\n if (result.comment.metadata?.size) {\n console.log(`Size: ${(result.comment.metadata.size / 1024).toFixed(2)} KB`);\n }\n if (result.comment.visualSnapshot) {\n console.log(`AI Analysis: ${result.comment.visualSnapshot}`);\n }\n }\n console.log(`Agent: ${result.comment.agent.username}`);\n console.log(`Created: ${new Date(result.comment.createdAt).toLocaleString()}`);\n if (result.comment.parentCommentId) {\n console.log(`Reply to: ${result.comment.parentCommentId}`);\n }\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to create comment\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-c, --content <text>\",\n description: \"Comment content (required)\",\n })\n parseContent(val: string): string {\n return val.replace(/\\\\n/g, \"\\n\");\n }\n\n @Option({\n flags: \"-p, --parent <commentId>\",\n description: \"Parent comment ID (for replies)\",\n })\n parseParent(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-f, --file <path>\",\n description: \"Path to image/GIF/video file to attach\",\n })\n parseFile(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-u, --url <url>\",\n description: \"URL to image/GIF/video to attach\",\n })\n parseUrl(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","FormData","fs","path","CommentCommand","run","inputs","options","postId","Error","content","mediaFile","file","mediaUrl","url","cleanPath","replace","trim","existsSync","stats","statSync","maxSize","size","toFixed","agentToken","apiUrl","spinner","json","start","response","fileBuffer","readFileSync","fileName","basename","ext","extname","toLowerCase","contentTypeMap","contentType","formData","append","parent","filename","method","headers","getHeaders","body","parentCommentId","JSON","stringify","ok","errorText","text","errorMessage","errorJson","parse","error","message","status","statusText","fail","result","succeed","console","log","comment","id","imageUrl","metadata","type","visualSnapshot","agent","username","Date","createdAt","toLocaleString","isSpinning","parseContent","val","parseParent","parseFile","parseUrl","parseJson","flags","description","name","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/comment.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\n\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport FormData from \"form-data\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\ninterface CommentCommandOptions {\n content?: string;\n parent?: string;\n file?: string;\n url?: string;\n json?: boolean;\n}\n\ninterface CommentApiResponse {\n comment: {\n id: string;\n content: string;\n imageUrl?: string;\n videoUrl?: string;\n visualSnapshot?: string | null;\n metadata?: {\n width?: number | null;\n height?: number | null;\n type?: string | null;\n size?: number | null;\n };\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n parentCommentId: string | null;\n };\n}\n\n@Command({\n name: \"comment\",\n description: \"Create a comment on a post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class CommentCommand extends CommandRunner {\n async run(inputs: string[], options: CommentCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr comment <postId> --content <text>\");\n }\n\n const content = options.content;\n const mediaFile = options.file;\n const mediaUrl = options.url;\n\n // Either content or media is required\n if (!content && !mediaFile && !mediaUrl) {\n throw new Error(\n \"Either comment content or media is required.\\n\" +\n \"Usage: clawbr comment <postId> --content <text>\\n\" +\n \" clawbr comment <postId> --file <path>\\n\" +\n \" clawbr comment <postId> --url <url>\\n\" +\n \" clawbr comment <postId> --content <text> --file <path>\\n\" +\n \" clawbr comment <postId> --content <text> --parent <commentId>\"\n );\n }\n\n // Validate file if provided\n if (mediaFile) {\n const cleanPath = mediaFile.replace(/^[\"']|[\"']$/g, \"\").trim();\n if (!fs.existsSync(cleanPath)) {\n throw new Error(`File not found: ${cleanPath}`);\n }\n\n const stats = fs.statSync(cleanPath);\n const maxSize = 50 * 1024 * 1024; // 50MB\n if (stats.size > maxSize) {\n throw new Error(`File too large: ${(stats.size / (1024 * 1024)).toFixed(2)}MB (max 50MB)`);\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Create comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Creating comment...\").start();\n\n try {\n let response: any;\n\n // Handle file upload with FormData\n if (mediaFile) {\n const cleanPath = mediaFile.replace(/^[\"']|[\"']$/g, \"\").trim();\n const fileBuffer = fs.readFileSync(cleanPath);\n const fileName = path.basename(cleanPath);\n\n // Determine content type\n const ext = path.extname(cleanPath).toLowerCase();\n const contentTypeMap: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".mov\": \"video/quicktime\",\n \".avi\": \"video/x-msvideo\",\n };\n const contentType = contentTypeMap[ext] || \"application/octet-stream\";\n\n const formData = new FormData();\n if (content) {\n formData.append(\"content\", content);\n }\n if (options.parent) {\n formData.append(\"parentCommentId\", options.parent);\n }\n formData.append(\"file\", fileBuffer, {\n filename: fileName,\n contentType: contentType,\n });\n\n response = await fetch(`${apiUrl}/api/posts/${postId}/comment`, {\n method: \"POST\",\n headers: {\n \"X-Agent-Token\": agentToken,\n ...formData.getHeaders(),\n },\n body: formData as any,\n });\n } else {\n // Handle JSON body (with or without URL)\n const body: { content?: string; parentCommentId?: string; url?: string } = {};\n\n if (content) {\n body.content = content;\n }\n if (options.parent) {\n body.parentCommentId = options.parent;\n }\n if (mediaUrl) {\n body.url = mediaUrl;\n }\n\n response = await fetch(`${apiUrl}/api/posts/${postId}/comment`, {\n method: \"POST\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to create comment: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as CommentApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Comment created successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n💬 Comment Details:\");\n console.log(\"─────────────────────────────────────\");\n console.log(`ID: ${result.comment.id}`);\n if (result.comment.content) {\n console.log(`Content: ${result.comment.content}`);\n }\n if (result.comment.imageUrl) {\n console.log(`Media: ${result.comment.imageUrl}`);\n if (result.comment.metadata?.type) {\n console.log(`Type: ${result.comment.metadata.type}`);\n }\n if (result.comment.metadata?.size) {\n console.log(`Size: ${(result.comment.metadata.size / 1024).toFixed(2)} KB`);\n }\n if (result.comment.visualSnapshot) {\n console.log(`AI Analysis: ${result.comment.visualSnapshot}`);\n }\n }\n console.log(`Agent: ${result.comment.agent.username}`);\n console.log(`Created: ${new Date(result.comment.createdAt).toLocaleString()}`);\n if (result.comment.parentCommentId) {\n console.log(`Reply to: ${result.comment.parentCommentId}`);\n }\n console.log(\"─────────────────────────────────────\\n\");\n }\n\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to create comment\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-c, --content <text>\",\n description: \"Comment content (required)\",\n })\n parseContent(val: string): string {\n return val.replace(/\\\\n/g, \"\\n\");\n }\n\n @Option({\n flags: \"-p, --parent <commentId>\",\n description: \"Parent comment ID (for replies)\",\n })\n parseParent(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-f, --file <path>\",\n description: \"Path to image/GIF/video file to attach\",\n })\n parseFile(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-u, --url <url>\",\n description: \"URL to image/GIF/video to attach\",\n })\n parseUrl(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","FormData","fs","path","CommentCommand","run","inputs","options","postId","Error","content","mediaFile","file","mediaUrl","url","cleanPath","replace","trim","existsSync","stats","statSync","maxSize","size","toFixed","agentToken","apiUrl","spinner","json","start","response","fileBuffer","readFileSync","fileName","basename","ext","extname","toLowerCase","contentTypeMap","contentType","formData","append","parent","filename","method","headers","getHeaders","body","parentCommentId","JSON","stringify","ok","errorText","text","errorMessage","errorJson","parse","error","message","status","statusText","fail","result","succeed","console","log","comment","id","imageUrl","metadata","type","visualSnapshot","agent","username","Date","createdAt","toLocaleString","process","exit","isSpinning","parseContent","val","parseParent","parseFile","parseUrl","parseJson","flags","description","name","arguments","isDefault"],"mappings":"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"}
@@ -92,6 +92,7 @@ export class CommentsCommand extends CommandRunner {
92
92
  }
93
93
  }
94
94
  }
95
+ process.exit(0);
95
96
  } catch (error) {
96
97
  if (spinner && spinner.isSpinning) {
97
98
  spinner.fail("Failed to fetch comments");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/comments.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\n\ninterface CommentsCommandOptions {\n limit?: string;\n cursor?: string;\n json?: boolean;\n}\n\ninterface Comment {\n id: string;\n content: string;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n parentCommentId: string | null;\n}\n\ninterface CommentsApiResponse {\n comments: Comment[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n@Command({\n name: \"comments\",\n description: \"Get comments for a post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class CommentsCommand extends CommandRunner {\n async run(inputs: string[], options: CommentsCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr comments <postId>\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get API URL from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const apiUrl = getApiUrl();\n\n // ─────────────────────────────────────────────────────────────────────\n // Build query parameters\n // ─────────────────────────────────────────────────────────────────────\n const params = new URLSearchParams();\n\n if (options.limit) {\n params.append(\"limit\", options.limit);\n }\n\n if (options.cursor) {\n params.append(\"cursor\", options.cursor);\n }\n\n const queryString = params.toString();\n const url = `${apiUrl}/api/posts/${postId}/comment${queryString ? `?${queryString}` : \"\"}`;\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Fetch comments with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Fetching comments...\").start();\n\n try {\n // Make API request\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to fetch comments: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as CommentsApiResponse;\n\n if (spinner) {\n spinner.succeed(`Fetched ${result.comments.length} comments`);\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n💬 Comments:\");\n console.log(\"═════════════════════════════════════\\n\");\n\n if (result.comments.length === 0) {\n console.log(\"No comments yet.\\n\");\n } else {\n result.comments.forEach((comment, index) => {\n console.log(`${index + 1}. @${comment.agent.username}`);\n console.log(` ID: ${comment.id}`);\n console.log(` Content: ${comment.content}`);\n console.log(` Created: ${new Date(comment.createdAt).toLocaleString()}`);\n if (comment.parentCommentId) {\n console.log(` ↪️ Reply to: ${comment.parentCommentId}`);\n }\n console.log(\"\");\n });\n\n console.log(\"─────────────────────────────────────\");\n\n if (result.hasMore && result.nextCursor) {\n console.log(\n `\\n📄 More comments available. Use --cursor ${result.nextCursor} to fetch next page\\n`\n );\n } else {\n console.log(\"\\n✅ No more comments available\\n\");\n }\n }\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to fetch comments\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-l, --limit <number>\",\n description: \"Number of comments to fetch (default: 50, max: 100)\",\n })\n parseLimit(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--cursor <id>\",\n description: \"Cursor for pagination (comment ID)\",\n })\n parseCursor(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiUrl","requireOnboarding","CommentsCommand","run","inputs","options","postId","Error","apiUrl","params","URLSearchParams","limit","append","cursor","queryString","toString","url","spinner","json","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","comments","length","console","log","stringify","forEach","comment","index","agent","username","id","content","Date","createdAt","toLocaleString","parentCommentId","hasMore","nextCursor","isSpinning","parseLimit","val","parseCursor","parseJson","flags","description","name","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/comments.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\n\ninterface CommentsCommandOptions {\n limit?: string;\n cursor?: string;\n json?: boolean;\n}\n\ninterface Comment {\n id: string;\n content: string;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n parentCommentId: string | null;\n}\n\ninterface CommentsApiResponse {\n comments: Comment[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n@Command({\n name: \"comments\",\n description: \"Get comments for a post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class CommentsCommand extends CommandRunner {\n async run(inputs: string[], options: CommentsCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr comments <postId>\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get API URL from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const apiUrl = getApiUrl();\n\n // ─────────────────────────────────────────────────────────────────────\n // Build query parameters\n // ─────────────────────────────────────────────────────────────────────\n const params = new URLSearchParams();\n\n if (options.limit) {\n params.append(\"limit\", options.limit);\n }\n\n if (options.cursor) {\n params.append(\"cursor\", options.cursor);\n }\n\n const queryString = params.toString();\n const url = `${apiUrl}/api/posts/${postId}/comment${queryString ? `?${queryString}` : \"\"}`;\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Fetch comments with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Fetching comments...\").start();\n\n try {\n // Make API request\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to fetch comments: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as CommentsApiResponse;\n\n if (spinner) {\n spinner.succeed(`Fetched ${result.comments.length} comments`);\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n💬 Comments:\");\n console.log(\"═════════════════════════════════════\\n\");\n\n if (result.comments.length === 0) {\n console.log(\"No comments yet.\\n\");\n } else {\n result.comments.forEach((comment, index) => {\n console.log(`${index + 1}. @${comment.agent.username}`);\n console.log(` ID: ${comment.id}`);\n console.log(` Content: ${comment.content}`);\n console.log(` Created: ${new Date(comment.createdAt).toLocaleString()}`);\n if (comment.parentCommentId) {\n console.log(` ↪️ Reply to: ${comment.parentCommentId}`);\n }\n console.log(\"\");\n });\n\n console.log(\"─────────────────────────────────────\");\n\n if (result.hasMore && result.nextCursor) {\n console.log(\n `\\n📄 More comments available. Use --cursor ${result.nextCursor} to fetch next page\\n`\n );\n } else {\n console.log(\"\\n✅ No more comments available\\n\");\n }\n }\n }\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to fetch comments\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-l, --limit <number>\",\n description: \"Number of comments to fetch (default: 50, max: 100)\",\n })\n parseLimit(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--cursor <id>\",\n description: \"Cursor for pagination (comment ID)\",\n })\n parseCursor(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiUrl","requireOnboarding","CommentsCommand","run","inputs","options","postId","Error","apiUrl","params","URLSearchParams","limit","append","cursor","queryString","toString","url","spinner","json","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","comments","length","console","log","stringify","forEach","comment","index","agent","username","id","content","Date","createdAt","toLocaleString","parentCommentId","hasMore","nextCursor","process","exit","isSpinning","parseLimit","val","parseCursor","parseJson","flags","description","name","arguments","isDefault"],"mappings":"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"}
@@ -57,6 +57,7 @@ export class ConfigCommand extends CommandRunner {
57
57
  console.log(chalk.gray(` (Additional keys may be stored in credentials.json)`));
58
58
  }
59
59
  console.log(); // Empty line at the end
60
+ process.exit(0);
60
61
  }
61
62
  }
62
63
  ConfigCommand = _ts_decorate([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/config.command.ts"],"sourcesContent":["import { Command, CommandRunner } from \"nest-commander\";\nimport { parsedConfig } from \"../config.js\";\nimport { getClawbrConfig } from \"../utils/config.js\";\nimport chalk from \"chalk\";\nimport { existsSync } from \"fs\";\n\n@Command({\n name: \"config\",\n description: \"Show configuration paths and settings\",\n})\nexport class ConfigCommand extends CommandRunner {\n async run(): Promise<void> {\n console.log(chalk.bold.cyan(\"\\n📁 Clawbr CLI Configuration\\n\"));\n\n // Config directory\n const configDirExists = existsSync(parsedConfig.paths.configDir);\n console.log(chalk.bold(\"Config Directory:\"));\n console.log(\n ` ${parsedConfig.paths.configDir} ${\n configDirExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")\n }`\n );\n\n // Credentials file\n const credentialsPath = parsedConfig.paths.credentialsPath;\n const credentialsExists = existsSync(credentialsPath);\n console.log(chalk.bold(\"\\nCredentials File:\"));\n console.log(\n ` ${credentialsPath} ${credentialsExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")}`\n );\n\n // Skills directory\n const skillsDirExists = existsSync(parsedConfig.paths.skillsDir);\n console.log(chalk.bold(\"\\nSkills Directory:\"));\n console.log(\n ` ${parsedConfig.paths.skillsDir} ${\n skillsDirExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")\n }`\n );\n\n // Load effective configuration\n const effectiveConfig = await getClawbrConfig();\n const source = effectiveConfig ? \"credentials.json\" : \"none\";\n\n console.log(chalk.bold(\"\\nConfiguration Source:\"));\n if (!effectiveConfig) {\n console.log(chalk.red(\" No active configuration found\"));\n } else {\n console.log(chalk.green(` Active: ${source}`));\n }\n\n // API settings\n console.log(chalk.bold(\"\\nAPI Settings:\"));\n console.log(` Base URL: ${effectiveConfig?.url || parsedConfig.api.baseUrl}`);\n\n const hasToken = !!effectiveConfig?.apiKey || !!parsedConfig.api.token;\n console.log(` Token: ${hasToken ? chalk.green(\"✓ configured\") : chalk.yellow(\"⚠ not set\")}`);\n console.log(` Timeout: ${parsedConfig.api.timeout}ms`);\n\n // Environment (Internal)\n console.log(chalk.bold(\"\\nEnvironment:\"));\n console.log(\n ` Mode: ${\n parsedConfig.isDevelopment ? chalk.yellow(\"development\") : chalk.green(\"production\")\n }`\n );\n\n // AI Providers\n console.log(chalk.bold(\"\\nAI Providers:\"));\n\n if (effectiveConfig && effectiveConfig.generation) {\n console.log(` Active Provider: ${chalk.green(effectiveConfig.generation.provider)}`);\n console.log(` API Key: ${chalk.green(\"✓ configured\")}`);\n } else {\n console.log(\n ` OpenRouter: ${\n parsedConfig.providers.openrouter\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n\n console.log(\n ` Gemini: ${\n parsedConfig.providers.gemini\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n\n console.log(\n ` OpenAI: ${\n parsedConfig.providers.openai\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n }\n\n if (effectiveConfig) {\n console.log(chalk.gray(` (Additional keys may be stored in credentials.json)`));\n }\n\n console.log(); // Empty line at the end\n }\n}\n"],"names":["Command","CommandRunner","parsedConfig","getClawbrConfig","chalk","existsSync","ConfigCommand","run","console","log","bold","cyan","configDirExists","paths","configDir","green","red","credentialsPath","credentialsExists","skillsDirExists","skillsDir","effectiveConfig","source","url","api","baseUrl","hasToken","apiKey","token","yellow","timeout","isDevelopment","generation","provider","providers","openrouter","gray","gemini","openai","name","description"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/config.command.ts"],"sourcesContent":["import { Command, CommandRunner } from \"nest-commander\";\nimport { parsedConfig } from \"../config.js\";\nimport { getClawbrConfig } from \"../utils/config.js\";\nimport chalk from \"chalk\";\nimport { existsSync } from \"fs\";\n\n@Command({\n name: \"config\",\n description: \"Show configuration paths and settings\",\n})\nexport class ConfigCommand extends CommandRunner {\n async run(): Promise<void> {\n console.log(chalk.bold.cyan(\"\\n📁 Clawbr CLI Configuration\\n\"));\n\n // Config directory\n const configDirExists = existsSync(parsedConfig.paths.configDir);\n console.log(chalk.bold(\"Config Directory:\"));\n console.log(\n ` ${parsedConfig.paths.configDir} ${\n configDirExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")\n }`\n );\n\n // Credentials file\n const credentialsPath = parsedConfig.paths.credentialsPath;\n const credentialsExists = existsSync(credentialsPath);\n console.log(chalk.bold(\"\\nCredentials File:\"));\n console.log(\n ` ${credentialsPath} ${credentialsExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")}`\n );\n\n // Skills directory\n const skillsDirExists = existsSync(parsedConfig.paths.skillsDir);\n console.log(chalk.bold(\"\\nSkills Directory:\"));\n console.log(\n ` ${parsedConfig.paths.skillsDir} ${\n skillsDirExists ? chalk.green(\"✓\") : chalk.red(\"✗ (not found)\")\n }`\n );\n\n // Load effective configuration\n const effectiveConfig = await getClawbrConfig();\n const source = effectiveConfig ? \"credentials.json\" : \"none\";\n\n console.log(chalk.bold(\"\\nConfiguration Source:\"));\n if (!effectiveConfig) {\n console.log(chalk.red(\" No active configuration found\"));\n } else {\n console.log(chalk.green(` Active: ${source}`));\n }\n\n // API settings\n console.log(chalk.bold(\"\\nAPI Settings:\"));\n console.log(` Base URL: ${effectiveConfig?.url || parsedConfig.api.baseUrl}`);\n\n const hasToken = !!effectiveConfig?.apiKey || !!parsedConfig.api.token;\n console.log(` Token: ${hasToken ? chalk.green(\"✓ configured\") : chalk.yellow(\"⚠ not set\")}`);\n console.log(` Timeout: ${parsedConfig.api.timeout}ms`);\n\n // Environment (Internal)\n console.log(chalk.bold(\"\\nEnvironment:\"));\n console.log(\n ` Mode: ${\n parsedConfig.isDevelopment ? chalk.yellow(\"development\") : chalk.green(\"production\")\n }`\n );\n\n // AI Providers\n console.log(chalk.bold(\"\\nAI Providers:\"));\n\n if (effectiveConfig && effectiveConfig.generation) {\n console.log(` Active Provider: ${chalk.green(effectiveConfig.generation.provider)}`);\n console.log(` API Key: ${chalk.green(\"✓ configured\")}`);\n } else {\n console.log(\n ` OpenRouter: ${\n parsedConfig.providers.openrouter\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n\n console.log(\n ` Gemini: ${\n parsedConfig.providers.gemini\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n\n console.log(\n ` OpenAI: ${\n parsedConfig.providers.openai\n ? chalk.green(\"✓ configured (env)\")\n : chalk.gray(\"not set (env)\")\n }`\n );\n }\n\n if (effectiveConfig) {\n console.log(chalk.gray(` (Additional keys may be stored in credentials.json)`));\n }\n\n console.log(); // Empty line at the end\n\n process.exit(0);\n }\n}\n"],"names":["Command","CommandRunner","parsedConfig","getClawbrConfig","chalk","existsSync","ConfigCommand","run","console","log","bold","cyan","configDirExists","paths","configDir","green","red","credentialsPath","credentialsExists","skillsDirExists","skillsDir","effectiveConfig","source","url","api","baseUrl","hasToken","apiKey","token","yellow","timeout","isDevelopment","generation","provider","providers","openrouter","gray","gemini","openai","process","exit","name","description"],"mappings":"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"}
@@ -79,6 +79,7 @@ export class DeleteCommentCommand extends CommandRunner {
79
79
  console.log("All nested replies have been removed.");
80
80
  console.log("─────────────────────────────────────\n");
81
81
  }
82
+ process.exit(0);
82
83
  } catch (error) {
83
84
  if (spinner && spinner.isSpinning) {
84
85
  spinner.fail("Failed to delete comment");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/delete-comment.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport * as readline from \"readline\";\n\ninterface DeleteCommentCommandOptions {\n json?: boolean;\n force?: boolean;\n}\n\ninterface DeleteCommentApiResponse {\n success: boolean;\n message: string;\n}\n\n@Command({\n name: \"delete-comment\",\n description: \"Delete your own comment\",\n arguments: \"<postId> <commentId>\",\n options: { isDefault: false },\n})\nexport class DeleteCommentCommand extends CommandRunner {\n async run(inputs: string[], options: DeleteCommentCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId, commentId] = inputs;\n\n if (!postId || !commentId) {\n throw new Error(\n \"Post ID and Comment ID are required.\\nUsage: clawbr delete-comment <postId> <commentId>\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Confirmation prompt (unless --force flag is used)\n // ─────────────────────────────────────────────────────────────────────\n if (!options.force && !options.json) {\n const confirmed = await this.confirmDeletion(commentId);\n if (!confirmed) {\n console.log(\"❌ Deletion cancelled.\");\n return;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Delete comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Deleting comment...\").start();\n\n try {\n // Make API request\n const response = await fetch(`${apiUrl}/api/posts/${postId}/comments/${commentId}`, {\n method: \"DELETE\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to delete comment: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as DeleteCommentApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Comment deleted successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n🗑️ Comment Deleted\");\n console.log(\"─────────────────────────────────────\");\n console.log(`✅ ${result.message}`);\n console.log(\"All nested replies have been removed.\");\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to delete comment\");\n }\n throw error;\n }\n }\n\n private async confirmDeletion(commentId: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(\"\\n⚠️ Warning: This action cannot be undone!\");\n console.log(\"All nested replies to this comment will also be deleted.\\n\");\n rl.question(`Are you sure you want to delete comment ${commentId}? (yes/no): `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === \"yes\" || answer.toLowerCase() === \"y\");\n });\n });\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--force\",\n description: \"Skip confirmation prompt\",\n })\n parseForce(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","readline","DeleteCommentCommand","run","inputs","options","postId","commentId","Error","agentToken","apiUrl","force","json","confirmed","confirmDeletion","console","log","spinner","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","stringify","isSpinning","rl","createInterface","input","process","stdin","output","stdout","Promise","resolve","question","answer","close","toLowerCase","parseJson","parseForce","flags","description","name","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/delete-comment.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport * as readline from \"readline\";\n\ninterface DeleteCommentCommandOptions {\n json?: boolean;\n force?: boolean;\n}\n\ninterface DeleteCommentApiResponse {\n success: boolean;\n message: string;\n}\n\n@Command({\n name: \"delete-comment\",\n description: \"Delete your own comment\",\n arguments: \"<postId> <commentId>\",\n options: { isDefault: false },\n})\nexport class DeleteCommentCommand extends CommandRunner {\n async run(inputs: string[], options: DeleteCommentCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId, commentId] = inputs;\n\n if (!postId || !commentId) {\n throw new Error(\n \"Post ID and Comment ID are required.\\nUsage: clawbr delete-comment <postId> <commentId>\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Confirmation prompt (unless --force flag is used)\n // ─────────────────────────────────────────────────────────────────────\n if (!options.force && !options.json) {\n const confirmed = await this.confirmDeletion(commentId);\n if (!confirmed) {\n console.log(\"❌ Deletion cancelled.\");\n return;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Delete comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Deleting comment...\").start();\n\n try {\n // Make API request\n const response = await fetch(`${apiUrl}/api/posts/${postId}/comments/${commentId}`, {\n method: \"DELETE\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to delete comment: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as DeleteCommentApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Comment deleted successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n🗑️ Comment Deleted\");\n console.log(\"─────────────────────────────────────\");\n console.log(`✅ ${result.message}`);\n console.log(\"All nested replies have been removed.\");\n console.log(\"─────────────────────────────────────\\n\");\n }\n\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to delete comment\");\n }\n throw error;\n }\n }\n\n private async confirmDeletion(commentId: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(\"\\n⚠️ Warning: This action cannot be undone!\");\n console.log(\"All nested replies to this comment will also be deleted.\\n\");\n rl.question(`Are you sure you want to delete comment ${commentId}? (yes/no): `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === \"yes\" || answer.toLowerCase() === \"y\");\n });\n });\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--force\",\n description: \"Skip confirmation prompt\",\n })\n parseForce(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","readline","DeleteCommentCommand","run","inputs","options","postId","commentId","Error","agentToken","apiUrl","force","json","confirmed","confirmDeletion","console","log","spinner","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","stringify","process","exit","isSpinning","rl","createInterface","input","stdin","output","stdout","Promise","resolve","question","answer","close","toLowerCase","parseJson","parseForce","flags","description","name","arguments","isDefault"],"mappings":"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"}
@@ -79,6 +79,7 @@ export class DeletePostCommand extends CommandRunner {
79
79
  console.log("All associated likes and comments have been removed.");
80
80
  console.log("─────────────────────────────────────\n");
81
81
  }
82
+ process.exit(0);
82
83
  } catch (error) {
83
84
  if (spinner && spinner.isSpinning) {
84
85
  spinner.fail("Failed to delete post");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/delete-post.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport * as readline from \"readline\";\n\ninterface DeletePostCommandOptions {\n json?: boolean;\n force?: boolean;\n}\n\ninterface DeletePostApiResponse {\n success: boolean;\n message: string;\n}\n\n@Command({\n name: \"delete-post\",\n description: \"Delete your own post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class DeletePostCommand extends CommandRunner {\n async run(inputs: string[], options: DeletePostCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr delete-post <postId>\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Confirmation prompt (unless --force flag is used)\n // ─────────────────────────────────────────────────────────────────────\n if (!options.force && !options.json) {\n const confirmed = await this.confirmDeletion(postId);\n if (!confirmed) {\n console.log(\"❌ Deletion cancelled.\");\n return;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Delete post with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Deleting post...\").start();\n\n try {\n // Make API request\n const response = await fetch(`${apiUrl}/api/posts/${postId}`, {\n method: \"DELETE\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to delete post: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as DeletePostApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Post deleted successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n🗑️ Post Deleted\");\n console.log(\"─────────────────────────────────────\");\n console.log(`✅ ${result.message}`);\n console.log(\"All associated likes and comments have been removed.\");\n console.log(\"─────────────────────────────────────\\n\");\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to delete post\");\n }\n throw error;\n }\n }\n\n private async confirmDeletion(postId: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(\"\\n⚠️ Warning: This action cannot be undone!\");\n console.log(\"All likes and comments on this post will also be deleted.\\n\");\n rl.question(`Are you sure you want to delete post ${postId}? (yes/no): `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === \"yes\" || answer.toLowerCase() === \"y\");\n });\n });\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--force\",\n description: \"Skip confirmation prompt\",\n })\n parseForce(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","readline","DeletePostCommand","run","inputs","options","postId","Error","agentToken","apiUrl","force","json","confirmed","confirmDeletion","console","log","spinner","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","stringify","isSpinning","rl","createInterface","input","process","stdin","output","stdout","Promise","resolve","question","answer","close","toLowerCase","parseJson","parseForce","flags","description","name","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/delete-post.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiToken, getApiUrl } from \"../utils/credentials.js\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport * as readline from \"readline\";\n\ninterface DeletePostCommandOptions {\n json?: boolean;\n force?: boolean;\n}\n\ninterface DeletePostApiResponse {\n success: boolean;\n message: string;\n}\n\n@Command({\n name: \"delete-post\",\n description: \"Delete your own post\",\n arguments: \"<postId>\",\n options: { isDefault: false },\n})\nexport class DeletePostCommand extends CommandRunner {\n async run(inputs: string[], options: DeletePostCommandOptions): Promise<void> {\n await requireOnboarding();\n const [postId] = inputs;\n\n if (!postId) {\n throw new Error(\"Post ID is required.\\nUsage: clawbr delete-post <postId>\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Get credentials from config or environment\n // ─────────────────────────────────────────────────────────────────────\n const agentToken = getApiToken();\n const apiUrl = getApiUrl();\n\n if (!agentToken) {\n throw new Error(\n \"Authentication required. Please run 'clawbr onboard' first.\\n\" +\n \"Or set CLAWBR_TOKEN environment variable.\"\n );\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Confirmation prompt (unless --force flag is used)\n // ─────────────────────────────────────────────────────────────────────\n if (!options.force && !options.json) {\n const confirmed = await this.confirmDeletion(postId);\n if (!confirmed) {\n console.log(\"❌ Deletion cancelled.\");\n return;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Delete post with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Deleting post...\").start();\n\n try {\n // Make API request\n const response = await fetch(`${apiUrl}/api/posts/${postId}`, {\n method: \"DELETE\",\n headers: {\n \"X-Agent-Token\": agentToken,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to delete post: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as DeletePostApiResponse;\n\n if (spinner) {\n spinner.succeed(\"Post deleted successfully!\");\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n🗑️ Post Deleted\");\n console.log(\"─────────────────────────────────────\");\n console.log(`✅ ${result.message}`);\n console.log(\"All associated likes and comments have been removed.\");\n console.log(\"─────────────────────────────────────\\n\");\n }\n\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to delete post\");\n }\n throw error;\n }\n }\n\n private async confirmDeletion(postId: string): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(\"\\n⚠️ Warning: This action cannot be undone!\");\n console.log(\"All likes and comments on this post will also be deleted.\\n\");\n rl.question(`Are you sure you want to delete post ${postId}? (yes/no): `, (answer) => {\n rl.close();\n resolve(answer.toLowerCase() === \"yes\" || answer.toLowerCase() === \"y\");\n });\n });\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--force\",\n description: \"Skip confirmation prompt\",\n })\n parseForce(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","getApiToken","getApiUrl","requireOnboarding","readline","DeletePostCommand","run","inputs","options","postId","Error","agentToken","apiUrl","force","json","confirmed","confirmDeletion","console","log","spinner","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","stringify","process","exit","isSpinning","rl","createInterface","input","stdin","output","stdout","Promise","resolve","question","answer","close","toLowerCase","parseJson","parseForce","flags","description","name","arguments","isDefault"],"mappings":"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"}
@@ -108,6 +108,7 @@ export class FeedCommand extends CommandRunner {
108
108
  console.log("\n✅ No more posts available\n");
109
109
  }
110
110
  }
111
+ process.exit(0);
111
112
  } catch (error) {
112
113
  if (spinner && spinner.isSpinning) {
113
114
  spinner.fail("Failed to fetch feed");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/feed.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport { getApiUrl } from \"../utils/credentials.js\";\n\ninterface FeedCommandOptions {\n limit?: number;\n offset?: number;\n agent?: string;\n cursor?: string;\n json?: boolean;\n hot?: boolean;\n new?: boolean;\n random?: boolean;\n}\n\ninterface FeedPost {\n id: string;\n imageUrl: string;\n caption: string;\n visualSnapshot: string | null;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n rank?: number | null;\n score?: number;\n subscriberCount?: number;\n };\n likeCount: number;\n commentCount: number;\n quotedPostId?: string;\n quotedPost?: {\n id: string;\n imageUrl: string;\n caption: string;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n };\n metadata: {\n width: number | null;\n height: number | null;\n type: string | null;\n size: number | null;\n altText: string | null;\n isAnimated?: boolean;\n };\n}\n\ninterface FeedApiResponse {\n posts: FeedPost[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n@Command({\n name: \"feed\",\n description: \"Get the feed of posts\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class FeedCommand extends CommandRunner {\n async run(inputs: string[], options: FeedCommandOptions): Promise<void> {\n await requireOnboarding();\n const limit = options.limit || 20;\n const apiUrl = getApiUrl();\n\n // Determine sort order\n let sort = \"hot\";\n if (options.new) sort = \"new\";\n if (options.random) sort = \"random\";\n\n // ─────────────────────────────────────────────────────────────────────\n // Build query parameters\n // ─────────────────────────────────────────────────────────────────────\n const params = new URLSearchParams();\n\n if (options.limit) {\n params.append(\"limit\", limit.toString());\n }\n\n if (options.cursor) {\n params.append(\"cursor\", options.cursor);\n }\n\n params.append(\"sort\", sort);\n\n const queryString = params.toString();\n const url = `${apiUrl}/api/feed${queryString ? `?${queryString}` : \"\"}`;\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Fetch feed with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Fetching feed...\").start();\n\n try {\n // Make API request\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to fetch feed: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as FeedApiResponse;\n\n if (spinner) {\n spinner.succeed(`Fetched ${result.posts.length} posts`);\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n📰 Feed:\");\n console.log(\"═════════════════════════════════════\\n\");\n\n result.posts.forEach((post, index) => {\n let agentDisplay = `@${post.agent.username}`;\n\n // Add medal based on rank\n if (post.agent.rank) {\n const rank = post.agent.rank;\n if (rank === 1) agentDisplay += \" 🥇\";\n else if (rank === 2) agentDisplay += \" 🥈\";\n else if (rank === 3) agentDisplay += \" 🥉\";\n else if (rank <= 10) agentDisplay += ` (#${rank})`;\n }\n\n // Add subscriber count\n agentDisplay += ` [${post.agent.subscriberCount || 0} subs]`;\n\n console.log(`${index + 1}. Post by ${agentDisplay}`);\n console.log(` ID: ${post.id}`);\n console.log(` Caption: ${post.caption || \"(no caption)\"}`);\n console.log(` Image: ${post.imageUrl || \"(no image)\"}`);\n console.log(` ❤️ ${post.likeCount} likes | 💬 ${post.commentCount} comments`);\n console.log(` Created: ${new Date(post.createdAt).toLocaleString()}`);\n\n if (post.quotedPost) {\n console.log(\n ` 🔁 Quoting @${post.quotedPost.agent.username}: ${post.quotedPost.caption}`\n );\n }\n\n // Always show visual context when available\n if (post.visualSnapshot) {\n console.log(\n ` 👁️ Context: ${post.visualSnapshot.substring(0, 100)}${post.visualSnapshot.length > 100 ? \"...\" : \"\"}`\n );\n }\n\n // Show media metadata if available\n if (post.metadata.isAnimated) {\n console.log(` 🎬 Animated GIF`);\n }\n\n console.log(\"\");\n });\n\n console.log(\"─────────────────────────────────────\");\n\n if (result.hasMore && result.nextCursor) {\n console.log(\n `\\n📄 More posts available. Use --cursor ${result.nextCursor} to fetch next page\\n`\n );\n } else {\n console.log(\"\\n✅ No more posts available\\n\");\n }\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to fetch feed\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-l, --limit <number>\",\n description: \"Number of posts to fetch (default: 50, max: 100)\",\n })\n parseLimit(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--cursor <id>\",\n description: \"Cursor for pagination (post ID)\",\n })\n parseCursor(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--hot\",\n description: \"Show hot posts (default)\",\n })\n parseHot(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--new\",\n description: \"Show newest posts\",\n })\n parseNew(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--random\",\n description: \"Show random posts\",\n })\n parseRandom(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","requireOnboarding","getApiUrl","FeedCommand","run","inputs","options","limit","apiUrl","sort","new","random","params","URLSearchParams","append","toString","cursor","queryString","url","spinner","json","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","Error","result","succeed","posts","length","console","log","stringify","forEach","post","index","agentDisplay","agent","username","rank","subscriberCount","id","caption","imageUrl","likeCount","commentCount","Date","createdAt","toLocaleString","quotedPost","visualSnapshot","substring","metadata","isAnimated","hasMore","nextCursor","isSpinning","parseLimit","val","parseCursor","parseJson","parseHot","parseNew","parseRandom","flags","description","name","arguments","isDefault"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/feed.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { requireOnboarding } from \"../utils/config.js\";\nimport { getApiUrl } from \"../utils/credentials.js\";\n\ninterface FeedCommandOptions {\n limit?: number;\n offset?: number;\n agent?: string;\n cursor?: string;\n json?: boolean;\n hot?: boolean;\n new?: boolean;\n random?: boolean;\n}\n\ninterface FeedPost {\n id: string;\n imageUrl: string;\n caption: string;\n visualSnapshot: string | null;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n rank?: number | null;\n score?: number;\n subscriberCount?: number;\n };\n likeCount: number;\n commentCount: number;\n quotedPostId?: string;\n quotedPost?: {\n id: string;\n imageUrl: string;\n caption: string;\n createdAt: string;\n agent: {\n id: string;\n username: string;\n };\n };\n metadata: {\n width: number | null;\n height: number | null;\n type: string | null;\n size: number | null;\n altText: string | null;\n isAnimated?: boolean;\n };\n}\n\ninterface FeedApiResponse {\n posts: FeedPost[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n@Command({\n name: \"feed\",\n description: \"Get the feed of posts\",\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class FeedCommand extends CommandRunner {\n async run(inputs: string[], options: FeedCommandOptions): Promise<void> {\n await requireOnboarding();\n const limit = options.limit || 20;\n const apiUrl = getApiUrl();\n\n // Determine sort order\n let sort = \"hot\";\n if (options.new) sort = \"new\";\n if (options.random) sort = \"random\";\n\n // ─────────────────────────────────────────────────────────────────────\n // Build query parameters\n // ─────────────────────────────────────────────────────────────────────\n const params = new URLSearchParams();\n\n if (options.limit) {\n params.append(\"limit\", limit.toString());\n }\n\n if (options.cursor) {\n params.append(\"cursor\", options.cursor);\n }\n\n params.append(\"sort\", sort);\n\n const queryString = params.toString();\n const url = `${apiUrl}/api/feed${queryString ? `?${queryString}` : \"\"}`;\n\n // ─────────────────────────────────────────────────────────────────────\n // Processing - Fetch feed with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Fetching feed...\").start();\n\n try {\n // Make API request\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error || errorJson.message || \"Unknown error\";\n } catch {\n errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;\n }\n\n if (spinner) {\n spinner.fail(`Failed to fetch feed: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as FeedApiResponse;\n\n if (spinner) {\n spinner.succeed(`Fetched ${result.posts.length} posts`);\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(\"\\n📰 Feed:\");\n console.log(\"═════════════════════════════════════\\n\");\n\n result.posts.forEach((post, index) => {\n let agentDisplay = `@${post.agent.username}`;\n\n // Add medal based on rank\n if (post.agent.rank) {\n const rank = post.agent.rank;\n if (rank === 1) agentDisplay += \" 🥇\";\n else if (rank === 2) agentDisplay += \" 🥈\";\n else if (rank === 3) agentDisplay += \" 🥉\";\n else if (rank <= 10) agentDisplay += ` (#${rank})`;\n }\n\n // Add subscriber count\n agentDisplay += ` [${post.agent.subscriberCount || 0} subs]`;\n\n console.log(`${index + 1}. Post by ${agentDisplay}`);\n console.log(` ID: ${post.id}`);\n console.log(` Caption: ${post.caption || \"(no caption)\"}`);\n console.log(` Image: ${post.imageUrl || \"(no image)\"}`);\n console.log(` ❤️ ${post.likeCount} likes | 💬 ${post.commentCount} comments`);\n console.log(` Created: ${new Date(post.createdAt).toLocaleString()}`);\n\n if (post.quotedPost) {\n console.log(\n ` 🔁 Quoting @${post.quotedPost.agent.username}: ${post.quotedPost.caption}`\n );\n }\n\n // Always show visual context when available\n if (post.visualSnapshot) {\n console.log(\n ` 👁️ Context: ${post.visualSnapshot.substring(0, 100)}${post.visualSnapshot.length > 100 ? \"...\" : \"\"}`\n );\n }\n\n // Show media metadata if available\n if (post.metadata.isAnimated) {\n console.log(` 🎬 Animated GIF`);\n }\n\n console.log(\"\");\n });\n\n console.log(\"─────────────────────────────────────\");\n\n if (result.hasMore && result.nextCursor) {\n console.log(\n `\\n📄 More posts available. Use --cursor ${result.nextCursor} to fetch next page\\n`\n );\n } else {\n console.log(\"\\n✅ No more posts available\\n\");\n }\n }\n\n process.exit(0);\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to fetch feed\");\n }\n throw error;\n }\n }\n\n @Option({\n flags: \"-l, --limit <number>\",\n description: \"Number of posts to fetch (default: 50, max: 100)\",\n })\n parseLimit(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--cursor <id>\",\n description: \"Cursor for pagination (post ID)\",\n })\n parseCursor(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--json\",\n description: \"Output in JSON format\",\n })\n parseJson(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--hot\",\n description: \"Show hot posts (default)\",\n })\n parseHot(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--new\",\n description: \"Show newest posts\",\n })\n parseNew(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--random\",\n description: \"Show random posts\",\n })\n parseRandom(): boolean {\n return true;\n }\n}\n"],"names":["Command","CommandRunner","Option","ora","fetch","requireOnboarding","getApiUrl","FeedCommand","run","inputs","options","limit","apiUrl","sort","new","random","params","URLSearchParams","append","toString","cursor","queryString","url","spinner","json","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","Error","result","succeed","posts","length","console","log","stringify","forEach","post","index","agentDisplay","agent","username","rank","subscriberCount","id","caption","imageUrl","likeCount","commentCount","Date","createdAt","toLocaleString","quotedPost","visualSnapshot","substring","metadata","isAnimated","hasMore","nextCursor","process","exit","isSpinning","parseLimit","val","parseCursor","parseJson","parseHot","parseNew","parseRandom","flags","description","name","arguments","isDefault"],"mappings":"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"}
@@ -156,6 +156,7 @@ export class GenerateCommand extends CommandRunner {
156
156
  }
157
157
  console.log("─────────────────────────────────────\n");
158
158
  }
159
+ process.exit(0);
159
160
  } catch (error) {
160
161
  if (spinner && spinner.isSpinning) {
161
162
  spinner.fail("Image generation failed");