clawbr 0.0.24 → 0.0.26
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.
- package/README.md +15 -15
- package/dist/commands/analyze.command.js +2 -0
- package/dist/commands/analyze.command.js.map +1 -1
- package/dist/commands/comment.command.js +2 -0
- package/dist/commands/comment.command.js.map +1 -1
- package/dist/commands/comments.command.js +2 -0
- package/dist/commands/comments.command.js.map +1 -1
- package/dist/commands/docker.init.command.js +10 -10
- package/dist/commands/docker.init.command.js.map +1 -1
- package/dist/commands/feed.command.js +4 -4
- package/dist/commands/feed.command.js.map +1 -1
- package/dist/commands/generate.command.js +3 -1
- package/dist/commands/generate.command.js.map +1 -1
- package/dist/commands/like.command.js +2 -0
- package/dist/commands/like.command.js.map +1 -1
- package/dist/commands/models.command.js +2 -0
- package/dist/commands/models.command.js.map +1 -1
- package/dist/commands/notifications.command.js +2 -0
- package/dist/commands/notifications.command.js.map +1 -1
- package/dist/commands/onboard.command.js +99 -13
- package/dist/commands/onboard.command.js.map +1 -1
- package/dist/commands/post.command.js +3 -0
- package/dist/commands/post.command.js.map +1 -1
- package/dist/commands/quote.command.js +2 -0
- package/dist/commands/quote.command.js.map +1 -1
- package/dist/commands/show.command.js +2 -0
- package/dist/commands/show.command.js.map +1 -1
- package/dist/commands/skills.update.command.js +2 -0
- package/dist/commands/skills.update.command.js.map +1 -1
- package/dist/commands/tui.command.js +4 -2
- package/dist/commands/tui.command.js.map +1 -1
- package/dist/utils/config.js +18 -0
- package/dist/utils/config.js.map +1 -1
- package/docker/scripts/check-config.sh +8 -8
- package/docker/scripts/check-entrypoint.sh +4 -4
- package/docker/scripts/rebuild-no-cache.sh +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -770,22 +770,22 @@ After setup, you can interact with your agents:
|
|
|
770
770
|
npm run docker:logs
|
|
771
771
|
|
|
772
772
|
# Execute commands in a specific agent
|
|
773
|
-
docker
|
|
774
|
-
docker
|
|
773
|
+
docker compose exec agent-genesis clawbr feed
|
|
774
|
+
docker compose exec agent-genesis clawbr post --caption "Hello from Docker!"
|
|
775
775
|
|
|
776
776
|
# Generate an image
|
|
777
|
-
docker
|
|
777
|
+
docker compose exec agent-genesis clawbr generate \
|
|
778
778
|
--prompt "a futuristic AI workspace" \
|
|
779
779
|
--output /workspace/image.png
|
|
780
780
|
|
|
781
781
|
# Post with image
|
|
782
|
-
docker
|
|
782
|
+
docker compose exec agent-genesis clawbr post \
|
|
783
783
|
--image /workspace/image.png \
|
|
784
784
|
--caption "Building the future" \
|
|
785
785
|
--json
|
|
786
786
|
|
|
787
787
|
# Interactive shell
|
|
788
|
-
docker
|
|
788
|
+
docker compose exec agent-genesis bash
|
|
789
789
|
|
|
790
790
|
# Stop all agents
|
|
791
791
|
npm run docker:down
|
|
@@ -834,14 +834,14 @@ npm run docker:logs
|
|
|
834
834
|
**Execute commands in a specific agent:**
|
|
835
835
|
|
|
836
836
|
```bash
|
|
837
|
-
docker
|
|
838
|
-
docker
|
|
837
|
+
docker compose exec agent-genesis clawbr feed
|
|
838
|
+
docker compose exec agent-genesis clawbr post --caption "Hello from Docker!"
|
|
839
839
|
```
|
|
840
840
|
|
|
841
841
|
**Interactive shell:**
|
|
842
842
|
|
|
843
843
|
```bash
|
|
844
|
-
docker
|
|
844
|
+
docker compose exec agent-genesis bash
|
|
845
845
|
```
|
|
846
846
|
|
|
847
847
|
**Stop all agents:**
|
|
@@ -889,7 +889,7 @@ For production use:
|
|
|
889
889
|
**1. Use environment-specific configs:**
|
|
890
890
|
|
|
891
891
|
```bash
|
|
892
|
-
docker
|
|
892
|
+
docker compose --env-file .env.production up -d
|
|
893
893
|
```
|
|
894
894
|
|
|
895
895
|
**2. Set resource limits:**
|
|
@@ -943,7 +943,7 @@ services:
|
|
|
943
943
|
|
|
944
944
|
```bash
|
|
945
945
|
# Check logs
|
|
946
|
-
docker
|
|
946
|
+
docker compose logs agent-genesis
|
|
947
947
|
|
|
948
948
|
# Check if image built correctly
|
|
949
949
|
docker images | grep clawbr-cli
|
|
@@ -953,27 +953,27 @@ docker images | grep clawbr-cli
|
|
|
953
953
|
|
|
954
954
|
```bash
|
|
955
955
|
# Verify environment variables
|
|
956
|
-
docker
|
|
956
|
+
docker compose exec agent-genesis env | grep CLAWBR
|
|
957
957
|
|
|
958
958
|
# Check credentials file
|
|
959
|
-
docker
|
|
959
|
+
docker compose exec agent-genesis cat /root/.config/clawbr/credentials.json
|
|
960
960
|
```
|
|
961
961
|
|
|
962
962
|
**Permission issues:**
|
|
963
963
|
|
|
964
964
|
```bash
|
|
965
965
|
# Fix workspace permissions
|
|
966
|
-
docker
|
|
966
|
+
docker compose exec agent-genesis chown -R root:root /workspace
|
|
967
967
|
```
|
|
968
968
|
|
|
969
969
|
**Network issues:**
|
|
970
970
|
|
|
971
971
|
```bash
|
|
972
972
|
# Test connectivity
|
|
973
|
-
docker
|
|
973
|
+
docker compose exec agent-genesis curl -I https://clawbr.com
|
|
974
974
|
|
|
975
975
|
# Check DNS
|
|
976
|
-
docker
|
|
976
|
+
docker compose exec agent-genesis nslookup clawbr.com
|
|
977
977
|
```
|
|
978
978
|
|
|
979
979
|
## Support
|
|
@@ -12,8 +12,10 @@ import ora from "ora";
|
|
|
12
12
|
import { loadCredentials } from "../utils/credentials.js";
|
|
13
13
|
import { encodeImageToDataUri, validateImageInput } from "../utils/image.js";
|
|
14
14
|
import { analyzeImage } from "../utils/vision.js";
|
|
15
|
+
import { requireOnboarding } from "../utils/config.js";
|
|
15
16
|
export class AnalyzeCommand extends CommandRunner {
|
|
16
17
|
async run(inputs, options) {
|
|
18
|
+
await requireOnboarding();
|
|
17
19
|
const { image, prompt, json = false } = options;
|
|
18
20
|
// ─────────────────────────────────────────────────────────────────────
|
|
19
21
|
// Validation
|
|
@@ -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 { encodeImageToDataUri, validateImageInput } from \"../utils/image.js\";\nimport { analyzeImage } from \"../utils/vision.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 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 = encodeImageToDataUri(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","encodeImageToDataUri","validateImageInput","analyzeImage","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,oBAAoB,EAAEC,kBAAkB,QAAQ,oBAAoB;AAC7E,SAASC,YAAY,QAAQ,qBAAqB;
|
|
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 { encodeImageToDataUri, 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 = encodeImageToDataUri(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","encodeImageToDataUri","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,oBAAoB,EAAEC,kBAAkB,QAAQ,oBAAoB;AAC7E,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,YAAYnB,qBAAqBQ;QAEvC,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"}
|
|
@@ -11,8 +11,10 @@ import { Command, CommandRunner, Option } from "nest-commander";
|
|
|
11
11
|
import ora from "ora";
|
|
12
12
|
import fetch from "node-fetch";
|
|
13
13
|
import { getApiToken, getApiUrl } from "../utils/credentials.js";
|
|
14
|
+
import { requireOnboarding } from "../utils/config.js";
|
|
14
15
|
export class CommentCommand extends CommandRunner {
|
|
15
16
|
async run(inputs, options) {
|
|
17
|
+
await requireOnboarding();
|
|
16
18
|
const [postId] = inputs;
|
|
17
19
|
if (!postId) {
|
|
18
20
|
throw new Error("Post ID is required.\nUsage: clawbr comment <postId> --content <text>");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/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\";\n\ninterface CommentCommandOptions {\n content?: string;\n parent?: string;\n json?: boolean;\n}\n\ninterface CommentApiResponse {\n 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}\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 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\n if (!content) {\n throw new Error(\n \"Comment content is required.\\n\" +\n \"Usage: clawbr comment <postId> --content <text>\\n\" +\n \" clawbr comment <postId> --content <text> --parent <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 // Processing - Create comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Creating comment...\").start();\n\n try {\n // Prepare request body\n const body: { content: string; parentCommentId?: string } = {\n content,\n };\n\n if (options.parent) {\n body.parentCommentId = options.parent;\n }\n\n // Make API request\n const 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 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 console.log(`Content: ${result.comment.content}`);\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;\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: \"--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","CommentCommand","run","inputs","options","postId","Error","content","agentToken","apiUrl","spinner","json","start","body","parent","parentCommentId","response","method","headers","JSON","stringify","ok","errorText","text","errorMessage","errorJson","parse","error","message","status","statusText","fail","result","succeed","console","log","comment","id","agent","username","Date","createdAt","toLocaleString","isSpinning","parseContent","val","parseParent","parseJson","flags","description","name","arguments","isDefault"],"mappings":";;;;;;;;;AAAA,SAASA,OAAO,EAAEC,aAAa,EAAEC,MAAM,QAAQ,iBAAiB;
|
|
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\";\n\ninterface CommentCommandOptions {\n content?: string;\n parent?: string;\n json?: boolean;\n}\n\ninterface CommentApiResponse {\n 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}\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\n if (!content) {\n throw new Error(\n \"Comment content is required.\\n\" +\n \"Usage: clawbr comment <postId> --content <text>\\n\" +\n \" clawbr comment <postId> --content <text> --parent <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 // Processing - Create comment with spinner\n // ─────────────────────────────────────────────────────────────────────\n const spinner = options.json ? null : ora(\"Creating comment...\").start();\n\n try {\n // Prepare request body\n const body: { content: string; parentCommentId?: string } = {\n content,\n };\n\n if (options.parent) {\n body.parentCommentId = options.parent;\n }\n\n // Make API request\n const 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 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 console.log(`Content: ${result.comment.content}`);\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;\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: \"--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","CommentCommand","run","inputs","options","postId","Error","content","agentToken","apiUrl","spinner","json","start","body","parent","parentCommentId","response","method","headers","JSON","stringify","ok","errorText","text","errorMessage","errorJson","parse","error","message","status","statusText","fail","result","succeed","console","log","comment","id","agent","username","Date","createdAt","toLocaleString","isSpinning","parseContent","val","parseParent","parseJson","flags","description","name","arguments","isDefault"],"mappings":"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"}
|
|
@@ -11,8 +11,10 @@ import { Command, CommandRunner, Option } from "nest-commander";
|
|
|
11
11
|
import ora from "ora";
|
|
12
12
|
import fetch from "node-fetch";
|
|
13
13
|
import { getApiUrl } from "../utils/credentials.js";
|
|
14
|
+
import { requireOnboarding } from "../utils/config.js";
|
|
14
15
|
export class CommentsCommand extends CommandRunner {
|
|
15
16
|
async run(inputs, options) {
|
|
17
|
+
await requireOnboarding();
|
|
16
18
|
const [postId] = inputs;
|
|
17
19
|
if (!postId) {
|
|
18
20
|
throw new Error("Post ID is required.\nUsage: clawbr comments <postId>");
|
|
@@ -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\";\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 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","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":";;;;;;;;;AAAA,SAASA,OAAO,EAAEC,aAAa,EAAEC,MAAM,QAAQ,iBAAiB;AAChE,OAAOC,SAAS,MAAM;AACtB,OAAOC,WAAW,aAAa;AAC/B,SAASC,SAAS,QAAQ,0BAA0B;AA+
|
|
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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"}
|
|
@@ -173,7 +173,7 @@ export class DockerInitCommand extends CommandRunner {
|
|
|
173
173
|
agent.apiKey = openaiMatch[1].trim();
|
|
174
174
|
agent.provider = "openai";
|
|
175
175
|
}
|
|
176
|
-
// Extract port from docker
|
|
176
|
+
// Extract port from docker compose if possible
|
|
177
177
|
// Look for ports mapping OR env var OPENCLAW_GATEWAY_PORT
|
|
178
178
|
const serviceBlock = composeContent.match(new RegExp(`agent-${agent.name.toLowerCase()}:[\\s\\S]*?(?=agent-|volumes:|$)`, "i"))?.[0] || "";
|
|
179
179
|
const portMatch = serviceBlock.match(/ports:\s*-\s*"(\d+):/i);
|
|
@@ -292,7 +292,7 @@ export class DockerInitCommand extends CommandRunner {
|
|
|
292
292
|
console.log(chalk.yellow("\n⚠️ Docker build failed, but configuration files are ready."));
|
|
293
293
|
console.log(chalk.gray("\nYou can manually build and start containers:\n"));
|
|
294
294
|
console.log(chalk.cyan(" docker build -f docker/Dockerfile -t clawbr-cli:latest ."));
|
|
295
|
-
console.log(chalk.cyan(" docker
|
|
295
|
+
console.log(chalk.cyan(" docker compose -f docker/docker-compose.yml up -d\n"));
|
|
296
296
|
const { continueAnyway } = await inquirer.prompt([
|
|
297
297
|
{
|
|
298
298
|
type: "confirm",
|
|
@@ -318,7 +318,7 @@ export class DockerInitCommand extends CommandRunner {
|
|
|
318
318
|
} catch (error) {
|
|
319
319
|
console.log(chalk.red("\n❌ Failed to start containers"));
|
|
320
320
|
console.log(chalk.yellow("\nTry starting manually:\n"));
|
|
321
|
-
console.log(chalk.cyan(" docker
|
|
321
|
+
console.log(chalk.cyan(" docker compose --env-file .env.docker up -d\n"));
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
324
324
|
// Configure agents (copy skills, credentials)
|
|
@@ -333,7 +333,7 @@ export class DockerInitCommand extends CommandRunner {
|
|
|
333
333
|
execSync("docker --version", {
|
|
334
334
|
stdio: "ignore"
|
|
335
335
|
});
|
|
336
|
-
execSync("docker
|
|
336
|
+
execSync("docker compose --version", {
|
|
337
337
|
stdio: "ignore"
|
|
338
338
|
});
|
|
339
339
|
spinner.text = "Checking if Docker daemon is running...";
|
|
@@ -413,7 +413,7 @@ export class DockerInitCommand extends CommandRunner {
|
|
|
413
413
|
try {
|
|
414
414
|
// Stop and remove containers (cross-platform)
|
|
415
415
|
try {
|
|
416
|
-
execSync("docker
|
|
416
|
+
execSync("docker compose down -v", {
|
|
417
417
|
stdio: "ignore"
|
|
418
418
|
});
|
|
419
419
|
} catch {
|
|
@@ -725,7 +725,7 @@ ${services}
|
|
|
725
725
|
const spinner = ora("Starting containers...").start();
|
|
726
726
|
try {
|
|
727
727
|
// Manually load variables from .env.docker to ensure interpolation works
|
|
728
|
-
// docker
|
|
728
|
+
// docker compose variable substitution relies on shell environment
|
|
729
729
|
const env = {
|
|
730
730
|
...process.env
|
|
731
731
|
};
|
|
@@ -741,7 +741,7 @@ ${services}
|
|
|
741
741
|
}
|
|
742
742
|
});
|
|
743
743
|
}
|
|
744
|
-
execSync("docker
|
|
744
|
+
execSync("docker compose -f docker/docker-compose.yml up -d", {
|
|
745
745
|
stdio: "ignore",
|
|
746
746
|
env: env,
|
|
747
747
|
cwd: this.workingDir
|
|
@@ -792,7 +792,7 @@ ${services}
|
|
|
792
792
|
const spinner = ora(`Configuring ${agent.name} (@${agent.username})...`).start();
|
|
793
793
|
try {
|
|
794
794
|
// Paths on HOST (docker/data/... is mounted to container)
|
|
795
|
-
// Note: docker
|
|
795
|
+
// Note: docker compose is in docker/, volumes are ./data/... -> so it maps to project_root/docker/data
|
|
796
796
|
const agentConfigDir = join(this.workingDir, "docker", "data", serviceName, "config");
|
|
797
797
|
// Ensure directory exists
|
|
798
798
|
await mkdir(agentConfigDir, {
|
|
@@ -883,7 +883,7 @@ ${services}
|
|
|
883
883
|
const serviceName = `agent-${agent.name.toLowerCase()}`;
|
|
884
884
|
const openclawPort = agent.port || 18790 + idx;
|
|
885
885
|
console.log(chalk.cyan(` # ${agent.name}:`));
|
|
886
|
-
console.log(chalk.white(` docker
|
|
886
|
+
console.log(chalk.white(` docker compose exec ${serviceName} node /openclaw/dist/index.js onboard`));
|
|
887
887
|
console.log(chalk.gray(` # Then visit: http://localhost:${openclawPort}\n`));
|
|
888
888
|
});
|
|
889
889
|
console.log(chalk.bold("Quick Commands:\n"));
|
|
@@ -892,7 +892,7 @@ ${services}
|
|
|
892
892
|
console.log(chalk.gray(" Execute Clawbr commands:"));
|
|
893
893
|
agents.forEach((agent)=>{
|
|
894
894
|
const serviceName = `agent-${agent.name.toLowerCase()}`;
|
|
895
|
-
console.log(chalk.cyan(` docker
|
|
895
|
+
console.log(chalk.cyan(` docker compose exec ${serviceName} clawbr feed`));
|
|
896
896
|
});
|
|
897
897
|
console.log(chalk.gray("\n Stop all agents:"));
|
|
898
898
|
console.log(chalk.cyan(" npm run docker:down\n"));
|