calabasas 0.23.0 → 0.23.1
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/dist/index.js +177 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7992,6 +7992,182 @@ async function webhookRevoke(token, _options) {
|
|
|
7992
7992
|
console.log(pc4.green("Webhook revoked."));
|
|
7993
7993
|
}
|
|
7994
7994
|
|
|
7995
|
+
// src/commands/webhook-skill.ts
|
|
7996
|
+
import * as fs9 from "fs";
|
|
7997
|
+
import * as path9 from "path";
|
|
7998
|
+
import pc5 from "picocolors";
|
|
7999
|
+
var DEFAULT_SKILL_PATH = ".claude/skills/calabasas-webhook/SKILL.md";
|
|
8000
|
+
var SKILL_CONTENT = `---
|
|
8001
|
+
name: calabasas-webhook
|
|
8002
|
+
description: Use when the user wants to fire a single Discord action (DM a user, post to a channel) from a non-Discord-aware system — Zapier, n8n, cron jobs, GitHub Actions, an LLM tool, a no-code form, a webhook from another SaaS. The Calabasas one-off webhook turns a pre-bound action into a plain POST URL with no Discord SDK or auth on the caller side. Trigger when the user says things like "send a DM from a cron", "fire a Discord message from Zapier", "give me a URL that DMs user X", "I need a webhook to post in #channel", or asks how to bridge an external tool to Discord without writing a bot integration.
|
|
8003
|
+
---
|
|
8004
|
+
|
|
8005
|
+
# Calabasas one-off webhooks
|
|
8006
|
+
|
|
8007
|
+
A Calabasas webhook is a URL that fires **one** pre-bound Discord action when POSTed to. The action, the bot, and the target (user or channel) are all baked into the URL at create time. The body only carries the message payload (\`content\` / \`embeds\`).
|
|
8008
|
+
|
|
8009
|
+
This is the right tool when:
|
|
8010
|
+
- A non-Discord system needs to send a Discord message (Zapier, n8n, cron, external SaaS webhooks, GitHub Actions, monitoring alerts).
|
|
8011
|
+
- The caller cannot or should not hold a bot token.
|
|
8012
|
+
- The action is narrow and known up front — "DM this exact user", "post to this exact channel".
|
|
8013
|
+
|
|
8014
|
+
**Not** the right tool when:
|
|
8015
|
+
- The caller needs to choose the target at fire time (use the Calabasas SDK or generated Discord actions instead).
|
|
8016
|
+
- The action is more complex than \`sendDM\` / \`sendChannelMessage\` (kick, ban, role assignment — use the SDK).
|
|
8017
|
+
- The caller is the user's own Convex backend (use generated Discord actions; no HTTP roundtrip needed).
|
|
8018
|
+
|
|
8019
|
+
## Supported actions (v1)
|
|
8020
|
+
|
|
8021
|
+
| Action | Bound param | Body fields |
|
|
8022
|
+
|--------|-------------|-------------|
|
|
8023
|
+
| \`sendDM\` | \`--user-id <discordUserId>\` | \`content\` and/or \`embeds\` |
|
|
8024
|
+
| \`sendChannelMessage\` | \`--channel-id <discordChannelId>\` | \`content\` and/or \`embeds\` |
|
|
8025
|
+
|
|
8026
|
+
## CLI commands (non-interactive, scriptable)
|
|
8027
|
+
|
|
8028
|
+
All flags are required-or-fail; no prompts. Safe to drive from an LLM or shell script.
|
|
8029
|
+
|
|
8030
|
+
### Create
|
|
8031
|
+
|
|
8032
|
+
\`\`\`bash
|
|
8033
|
+
calabasas webhook create \\
|
|
8034
|
+
--bot <botId> \\
|
|
8035
|
+
--action <sendDM|sendChannelMessage> \\
|
|
8036
|
+
[--user-id <discordUserId> | --channel-id <discordChannelId>] \\
|
|
8037
|
+
[--label <label>] \\
|
|
8038
|
+
[--max-uses <number>] \\
|
|
8039
|
+
[--expires <duration>]
|
|
8040
|
+
\`\`\`
|
|
8041
|
+
|
|
8042
|
+
| Flag | Notes |
|
|
8043
|
+
|------|-------|
|
|
8044
|
+
| \`--bot\` | Calabasas bot ID. Use \`calabasas bot list --once\` to find one. |
|
|
8045
|
+
| \`--action\` | \`sendDM\` or \`sendChannelMessage\`. |
|
|
8046
|
+
| \`--user-id\` | Required for \`sendDM\`. Discord user snowflake. |
|
|
8047
|
+
| \`--channel-id\` | Required for \`sendChannelMessage\`. Discord channel snowflake. |
|
|
8048
|
+
| \`--label\` | Free-form label shown in \`webhook list\`. |
|
|
8049
|
+
| \`--max-uses\` | Hard cap. Both successful and failed fires count toward the cap. |
|
|
8050
|
+
| \`--expires\` | Auto-expire after duration: \`30m\`, \`24h\`, \`7d\`, etc. (\`s\\|m\\|h\\|d\`). |
|
|
8051
|
+
|
|
8052
|
+
Output (key=value lines, easy to grep):
|
|
8053
|
+
|
|
8054
|
+
\`\`\`
|
|
8055
|
+
Webhook created.
|
|
8056
|
+
|
|
8057
|
+
URL: https://calabasas-production.up.railway.app/api/hooks/whk_xxxxx
|
|
8058
|
+
token: whk_xxxxx
|
|
8059
|
+
webhookId: <id>
|
|
8060
|
+
action: sendDM
|
|
8061
|
+
params: {"userId":"123456789012345678"}
|
|
8062
|
+
\`\`\`
|
|
8063
|
+
|
|
8064
|
+
### Fire
|
|
8065
|
+
|
|
8066
|
+
\`\`\`bash
|
|
8067
|
+
curl -X POST \\
|
|
8068
|
+
-H 'Content-Type: application/json' \\
|
|
8069
|
+
-d '{"content":"Hello!"}' \\
|
|
8070
|
+
https://calabasas-production.up.railway.app/api/hooks/whk_xxxxx
|
|
8071
|
+
\`\`\`
|
|
8072
|
+
|
|
8073
|
+
Body fields:
|
|
8074
|
+
|
|
8075
|
+
| Field | Type | Notes |
|
|
8076
|
+
|-------|------|-------|
|
|
8077
|
+
| \`content\` | string | Message text. At least one of \`content\` or \`embeds\` is required. |
|
|
8078
|
+
| \`embeds\` | array | Discord embed objects. |
|
|
8079
|
+
| \`tts\` | boolean | Text-to-speech. |
|
|
8080
|
+
| \`allowedMentions\` | object | Discord allowed-mentions object (camelCase). |
|
|
8081
|
+
|
|
8082
|
+
Response shape (always JSON):
|
|
8083
|
+
|
|
8084
|
+
- Success → \`{ "ok": true, "messageId": "..." }\` (HTTP 200)
|
|
8085
|
+
- Failure → \`{ "ok": false, "error": "..." }\` (HTTP 4xx/5xx)
|
|
8086
|
+
|
|
8087
|
+
Status codes:
|
|
8088
|
+
|
|
8089
|
+
| Code | Meaning |
|
|
8090
|
+
|------|---------|
|
|
8091
|
+
| 200 | Action fired |
|
|
8092
|
+
| 400 | Invalid body (missing \`content\`/\`embeds\`, malformed JSON) |
|
|
8093
|
+
| 404 | Token not found or revoked |
|
|
8094
|
+
| 410 | Token expired or \`maxUses\` reached |
|
|
8095
|
+
| 502 | Discord rejected the request |
|
|
8096
|
+
| 503 | Bot is currently offline — retry shortly |
|
|
8097
|
+
|
|
8098
|
+
### List
|
|
8099
|
+
|
|
8100
|
+
\`\`\`bash
|
|
8101
|
+
calabasas webhook list # human-friendly table
|
|
8102
|
+
calabasas webhook list --json # raw JSON for tooling/LLM use
|
|
8103
|
+
\`\`\`
|
|
8104
|
+
|
|
8105
|
+
Status column shows \`active\`, \`expired\`, or \`exhausted\`. Revoked rows are filtered out.
|
|
8106
|
+
|
|
8107
|
+
### Revoke
|
|
8108
|
+
|
|
8109
|
+
\`\`\`bash
|
|
8110
|
+
calabasas webhook revoke <token>
|
|
8111
|
+
\`\`\`
|
|
8112
|
+
|
|
8113
|
+
Soft delete — URL stops working immediately, row stays for audit. To rotate a leaked token, revoke and create a fresh one (the URL changes; consumers must update).
|
|
8114
|
+
|
|
8115
|
+
## Choosing limits
|
|
8116
|
+
|
|
8117
|
+
Webhooks are public — anyone with the URL can fire. Treat the URL like a one-shot capability token. Defaults to keep things safe:
|
|
8118
|
+
|
|
8119
|
+
- **Set \`--max-uses\`** unless the integration genuinely needs unlimited fires. Even \`--max-uses 1000\` is far better than uncapped.
|
|
8120
|
+
- **Set \`--expires\`** for any webhook tied to a campaign / deploy / time-bound flow.
|
|
8121
|
+
- **Use \`--label\`** so you can identify it in \`webhook list\` later.
|
|
8122
|
+
|
|
8123
|
+
## Common patterns
|
|
8124
|
+
|
|
8125
|
+
**Cron alert to a channel:**
|
|
8126
|
+
\`\`\`bash
|
|
8127
|
+
calabasas webhook create --bot <id> --action sendChannelMessage \\
|
|
8128
|
+
--channel-id 123 --label "nightly-report" --max-uses 365 --expires 365d
|
|
8129
|
+
# Then in your cron: curl -X POST -d '{"content":"Nightly report ready"}' <url>
|
|
8130
|
+
\`\`\`
|
|
8131
|
+
|
|
8132
|
+
**One-shot welcome DM from a sign-up form:**
|
|
8133
|
+
\`\`\`bash
|
|
8134
|
+
calabasas webhook create --bot <id> --action sendDM \\
|
|
8135
|
+
--user-id <id> --max-uses 1 --expires 1h
|
|
8136
|
+
\`\`\`
|
|
8137
|
+
|
|
8138
|
+
**Zapier "post to Discord" step:** create a \`sendChannelMessage\` webhook, paste URL into Zapier's webhooks-by-Zapier action with body \`{"content": "{{trigger field}}"}\`.
|
|
8139
|
+
|
|
8140
|
+
## Authentication
|
|
8141
|
+
|
|
8142
|
+
CLI commands resolve credentials in this order:
|
|
8143
|
+
1. \`CALABASAS_PLATFORM_API_KEY\` in \`.env.local\` (preferred — \`cpk_\` prefix).
|
|
8144
|
+
2. User API key from \`~/.calabasas/config.json\` (fallback — \`clb_\` prefix).
|
|
8145
|
+
|
|
8146
|
+
Run \`calabasas login\` (user key) or \`calabasas platform create\` / \`calabasas platform connect\` (platform key) if neither is set.
|
|
8147
|
+
|
|
8148
|
+
## Anti-patterns
|
|
8149
|
+
|
|
8150
|
+
- **Don't bake secrets into the URL beyond the token** — the token *is* the credential.
|
|
8151
|
+
- **Don't share one webhook across many services** — one URL per integration so revoke kills exactly one consumer.
|
|
8152
|
+
- **Don't substitute webhooks for the SDK** when the caller is your own Convex backend; the generated \`discord.actions.ts\` is faster and richer.
|
|
8153
|
+
`;
|
|
8154
|
+
async function webhookSkill(options) {
|
|
8155
|
+
const target = options.output ?? DEFAULT_SKILL_PATH;
|
|
8156
|
+
const fullPath = path9.resolve(process.cwd(), target);
|
|
8157
|
+
const dir = path9.dirname(fullPath);
|
|
8158
|
+
if (fs9.existsSync(fullPath) && !options.force) {
|
|
8159
|
+
console.error(pc5.red("Error:") + ` ${target} already exists.
|
|
8160
|
+
` + " Re-run with --force to overwrite, or pass --output <path> to write elsewhere.");
|
|
8161
|
+
process.exit(1);
|
|
8162
|
+
}
|
|
8163
|
+
if (!fs9.existsSync(dir)) {
|
|
8164
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
8165
|
+
}
|
|
8166
|
+
fs9.writeFileSync(fullPath, SKILL_CONTENT);
|
|
8167
|
+
console.log(pc5.green("Installed calabasas-webhook skill at ") + pc5.cyan(target));
|
|
8168
|
+
console.log(pc5.dim("Claude Code will pick it up on next start. The skill triggers when the user wants to fire a single Discord action from an external service."));
|
|
8169
|
+
}
|
|
8170
|
+
|
|
7995
8171
|
// src/index.ts
|
|
7996
8172
|
var dashboard = async () => {
|
|
7997
8173
|
const mod = await import("./dashboard-a862sabz.js");
|
|
@@ -8032,4 +8208,5 @@ var webhookCmd = program2.command("webhook").description("Manage one-off webhook
|
|
|
8032
8208
|
webhookCmd.command("create").description("Create a webhook URL bound to a single bot, action, and target").requiredOption("-b, --bot <botId>", "Bot ID that will perform the action").requiredOption("-a, --action <action>", "Action to fire: sendDM | sendChannelMessage").option("--user-id <discordUserId>", "Target user ID (required for sendDM)").option("--channel-id <discordChannelId>", "Target channel ID (required for sendChannelMessage)").option("--label <label>", "Human-readable label for listing").option("--max-uses <number>", "Max times this URL can be fired before it stops working").option("--expires <duration>", "Auto-expire after duration: e.g. 30m, 24h, 7d").option("--platform-id <id>", "Platform ID (only needed with user key + multiple platforms)").action(webhookCreate);
|
|
8033
8209
|
webhookCmd.command("list").alias("ls").description("List all non-revoked webhooks for the current platform").option("--json", "Output raw JSON instead of a table").action(webhookList);
|
|
8034
8210
|
webhookCmd.command("revoke <token>").description("Revoke a webhook by token (soft delete)").option("-y, --yes", "Skip confirmation prompt (currently a no-op)").action(webhookRevoke);
|
|
8211
|
+
webhookCmd.command("skill").description("Install the calabasas-webhook Claude Code skill in this project").option("-o, --output <path>", "Output path", ".claude/skills/calabasas-webhook/SKILL.md").option("-f, --force", "Overwrite if the file already exists").action(webhookSkill);
|
|
8035
8212
|
program2.parse();
|