@knowsuchagency/fulcrum 2.17.2 → 3.0.0
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 +6 -4
- package/bin/fulcrum.js +99 -44
- package/dist/assets/{index-BV5V1ZcI.js → index-BPydksdv.js} +156 -156
- package/dist/assets/index-XD1DMF7S.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/server/index.js +146831 -146696
- package/dist/assets/index-D2c3O5c4.css +0 -1
package/README.md
CHANGED
|
@@ -179,7 +179,9 @@ Chat with the AI assistant from anywhere via your favorite messaging platform.
|
|
|
179
179
|
| **Discord** | Bot token from Developer Portal |
|
|
180
180
|
| **Telegram** | Bot token from @BotFather |
|
|
181
181
|
| **Slack** | Bot + App tokens with Socket Mode |
|
|
182
|
+
| **Gmail** | OAuth2, sends emails to your own address |
|
|
182
183
|
|
|
184
|
+
- **User-only messaging** — Outbound messages restricted to user's own accounts (no third-party messaging)
|
|
183
185
|
- **Persistent sessions** — Conversation context maintained across messages
|
|
184
186
|
- **Email threading** — Each email thread is a separate conversation
|
|
185
187
|
- **Observe-first** — Email and WhatsApp collect all messages but only respond to authorized senders
|
|
@@ -250,14 +252,14 @@ Both plugins include an MCP server with 60+ tools:
|
|
|
250
252
|
| **Apps** | Deploy, stop, and monitor Docker Compose applications |
|
|
251
253
|
| **Filesystem** | Browse directories, read/write files on the Fulcrum server |
|
|
252
254
|
| **Execution** | Run shell commands with persistent session support |
|
|
253
|
-
| **Notifications** | Send notifications to enabled channels |
|
|
255
|
+
| **Notifications** | Send notifications to enabled channels (Slack, Discord, Pushover, WhatsApp, Telegram, Gmail) |
|
|
254
256
|
| **Backup & Restore** | Snapshot database and settings; auto-safety-backup on restore |
|
|
255
257
|
| **Settings** | View and update configuration; manage notification channels |
|
|
256
258
|
| **Search** | Unified full-text search across tasks, projects, messages, events, memories, and conversations |
|
|
257
259
|
| **Memory** | Read/update master memory file; store ephemeral knowledge with tags |
|
|
258
260
|
| **Calendar** | Manage CalDAV accounts, sync calendars, configure event copy rules |
|
|
259
|
-
| **Gmail** | List Google accounts, manage Gmail drafts
|
|
260
|
-
| **Assistant** | Send messages via channels; query sweep history |
|
|
261
|
+
| **Gmail** | List Google accounts, manage Gmail drafts, send emails |
|
|
262
|
+
| **Assistant** | Send messages via channels (WhatsApp, Discord, Telegram, Slack, Gmail); query sweep history |
|
|
261
263
|
|
|
262
264
|
Use `search_tools` to discover available tools by keyword or category.
|
|
263
265
|
|
|
@@ -317,7 +319,7 @@ Settings are stored in `.fulcrum/settings.json`. The fulcrum directory is resolv
|
|
|
317
319
|
| integrations.githubPat | `GITHUB_PAT` | null |
|
|
318
320
|
| appearance.language | — | null (auto-detect) |
|
|
319
321
|
|
|
320
|
-
Notification settings (sound, Slack, Discord, Pushover) are configured via Settings UI or CLI.
|
|
322
|
+
Notification settings (sound, Slack, Discord, Pushover, WhatsApp, Telegram, Gmail) are configured via Settings UI or CLI.
|
|
321
323
|
|
|
322
324
|
### Linear Integration
|
|
323
325
|
|
package/bin/fulcrum.js
CHANGED
|
@@ -1660,6 +1660,12 @@ class FulcrumClient {
|
|
|
1660
1660
|
async deleteGmailDraft(accountId, draftId) {
|
|
1661
1661
|
return this.fetch(`/api/google/accounts/${accountId}/drafts/${draftId}`, { method: "DELETE" });
|
|
1662
1662
|
}
|
|
1663
|
+
async sendGmailMessage(accountId, body, subject) {
|
|
1664
|
+
return this.fetch(`/api/google/accounts/${accountId}/send`, {
|
|
1665
|
+
method: "POST",
|
|
1666
|
+
body: JSON.stringify({ body, subject })
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1663
1669
|
async readMemoryFile() {
|
|
1664
1670
|
return this.fetch("/api/memory-file");
|
|
1665
1671
|
}
|
|
@@ -23838,7 +23844,7 @@ var require_formats = __commonJS((exports) => {
|
|
|
23838
23844
|
}
|
|
23839
23845
|
var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
|
|
23840
23846
|
function getTime(strictTimeZone) {
|
|
23841
|
-
return function
|
|
23847
|
+
return function time3(str) {
|
|
23842
23848
|
const matches = TIME.exec(str);
|
|
23843
23849
|
if (!matches)
|
|
23844
23850
|
return false;
|
|
@@ -43680,7 +43686,7 @@ var init_registry = __esm(() => {
|
|
|
43680
43686
|
name: "send_notification",
|
|
43681
43687
|
description: "Send a notification to all enabled channels",
|
|
43682
43688
|
category: "notifications",
|
|
43683
|
-
keywords: ["notify", "alert", "message", "slack", "discord"],
|
|
43689
|
+
keywords: ["notify", "alert", "message", "slack", "discord", "gmail"],
|
|
43684
43690
|
defer_loading: false
|
|
43685
43691
|
},
|
|
43686
43692
|
{
|
|
@@ -44107,14 +44113,14 @@ var init_registry = __esm(() => {
|
|
|
44107
44113
|
name: "get_notification_settings",
|
|
44108
44114
|
description: "Get notification channel settings",
|
|
44109
44115
|
category: "settings",
|
|
44110
|
-
keywords: ["settings", "notifications", "slack", "discord", "pushover", "sound", "alert"],
|
|
44116
|
+
keywords: ["settings", "notifications", "slack", "discord", "pushover", "gmail", "sound", "alert"],
|
|
44111
44117
|
defer_loading: false
|
|
44112
44118
|
},
|
|
44113
44119
|
{
|
|
44114
44120
|
name: "update_notification_settings",
|
|
44115
44121
|
description: "Update notification channel settings",
|
|
44116
44122
|
category: "settings",
|
|
44117
|
-
keywords: ["settings", "notifications", "slack", "discord", "pushover", "sound", "update", "enable", "disable"],
|
|
44123
|
+
keywords: ["settings", "notifications", "slack", "discord", "pushover", "whatsapp", "telegram", "gmail", "sound", "update", "enable", "disable"],
|
|
44118
44124
|
defer_loading: false
|
|
44119
44125
|
},
|
|
44120
44126
|
{
|
|
@@ -44203,9 +44209,9 @@ var init_registry = __esm(() => {
|
|
|
44203
44209
|
},
|
|
44204
44210
|
{
|
|
44205
44211
|
name: "message",
|
|
44206
|
-
description: "Send a message to a messaging channel (WhatsApp, Discord, Telegram, Slack)",
|
|
44212
|
+
description: "Send a message to a messaging channel (WhatsApp, Discord, Telegram, Slack, Gmail)",
|
|
44207
44213
|
category: "assistant",
|
|
44208
|
-
keywords: ["message", "send", "reply", "whatsapp", "communicate", "respond"],
|
|
44214
|
+
keywords: ["message", "send", "reply", "whatsapp", "gmail", "email", "communicate", "respond"],
|
|
44209
44215
|
defer_loading: false
|
|
44210
44216
|
},
|
|
44211
44217
|
{
|
|
@@ -45596,18 +45602,30 @@ var SENSITIVE_SETTINGS, registerSettingsTools = (server, client) => {
|
|
|
45596
45602
|
})).describe("Sound notification settings"),
|
|
45597
45603
|
slack: exports_external.optional(exports_external.object({
|
|
45598
45604
|
enabled: exports_external.boolean().describe("Enable or disable Slack notifications"),
|
|
45599
|
-
webhookUrl: exports_external.optional(exports_external.string()).describe("Slack webhook URL")
|
|
45605
|
+
webhookUrl: exports_external.optional(exports_external.string()).describe("Slack webhook URL"),
|
|
45606
|
+
useMessagingChannel: exports_external.optional(exports_external.boolean()).describe("Send via messaging channel instead of webhook")
|
|
45600
45607
|
})).describe("Slack notification settings"),
|
|
45601
45608
|
discord: exports_external.optional(exports_external.object({
|
|
45602
45609
|
enabled: exports_external.boolean().describe("Enable or disable Discord notifications"),
|
|
45603
|
-
webhookUrl: exports_external.optional(exports_external.string()).describe("Discord webhook URL")
|
|
45610
|
+
webhookUrl: exports_external.optional(exports_external.string()).describe("Discord webhook URL"),
|
|
45611
|
+
useMessagingChannel: exports_external.optional(exports_external.boolean()).describe("Send via messaging channel instead of webhook")
|
|
45604
45612
|
})).describe("Discord notification settings"),
|
|
45605
45613
|
pushover: exports_external.optional(exports_external.object({
|
|
45606
45614
|
enabled: exports_external.boolean().describe("Enable or disable Pushover notifications"),
|
|
45607
45615
|
appToken: exports_external.optional(exports_external.string()).describe("Pushover app token"),
|
|
45608
45616
|
userKey: exports_external.optional(exports_external.string()).describe("Pushover user key")
|
|
45609
|
-
})).describe("Pushover notification settings")
|
|
45610
|
-
|
|
45617
|
+
})).describe("Pushover notification settings"),
|
|
45618
|
+
whatsapp: exports_external.optional(exports_external.object({
|
|
45619
|
+
enabled: exports_external.boolean().describe("Enable or disable WhatsApp notifications (requires connected messaging channel)")
|
|
45620
|
+
})).describe("WhatsApp notification settings (uses messaging channel)"),
|
|
45621
|
+
telegram: exports_external.optional(exports_external.object({
|
|
45622
|
+
enabled: exports_external.boolean().describe("Enable or disable Telegram notifications (requires connected messaging channel)")
|
|
45623
|
+
})).describe("Telegram notification settings (uses messaging channel)"),
|
|
45624
|
+
gmail: exports_external.optional(exports_external.object({
|
|
45625
|
+
enabled: exports_external.boolean().describe("Enable or disable Gmail notifications (sends email to your own Gmail address)"),
|
|
45626
|
+
googleAccountId: exports_external.optional(exports_external.string()).describe("Google account ID to send notifications from")
|
|
45627
|
+
})).describe("Gmail notification settings (sends email via Gmail API)")
|
|
45628
|
+
}, async ({ enabled, toast, desktop, sound, slack, discord, pushover, whatsapp, telegram, gmail }) => {
|
|
45611
45629
|
try {
|
|
45612
45630
|
const updates = {};
|
|
45613
45631
|
if (enabled !== undefined)
|
|
@@ -45624,6 +45642,12 @@ var SENSITIVE_SETTINGS, registerSettingsTools = (server, client) => {
|
|
|
45624
45642
|
updates.discord = discord;
|
|
45625
45643
|
if (pushover !== undefined)
|
|
45626
45644
|
updates.pushover = pushover;
|
|
45645
|
+
if (whatsapp !== undefined)
|
|
45646
|
+
updates.whatsapp = whatsapp;
|
|
45647
|
+
if (telegram !== undefined)
|
|
45648
|
+
updates.telegram = telegram;
|
|
45649
|
+
if (gmail !== undefined)
|
|
45650
|
+
updates.gmail = gmail;
|
|
45627
45651
|
const result = await client.updateNotifications(updates);
|
|
45628
45652
|
return formatSuccess({
|
|
45629
45653
|
...result,
|
|
@@ -45794,17 +45818,32 @@ var init_email = __esm(() => {
|
|
|
45794
45818
|
// cli/src/mcp/tools/assistant.ts
|
|
45795
45819
|
var ChannelSchema, registerAssistantTools = (server, client) => {
|
|
45796
45820
|
server.tool("message", "Send a message to a messaging channel (WhatsApp, Discord, Telegram, Slack). Use this to reply to messages or send proactive communications. For email, use create_gmail_draft instead.", {
|
|
45797
|
-
channel: ChannelSchema.describe("Target channel: whatsapp, discord, telegram, slack, or
|
|
45798
|
-
to: exports_external.optional(exports_external.string()).describe("Recipient identifier. Optional \u2014 if omitted, auto-resolves to the channel's primary user."),
|
|
45821
|
+
channel: ChannelSchema.describe("Target channel: whatsapp, discord, telegram, slack, or gmail"),
|
|
45799
45822
|
body: exports_external.string().describe("Message content"),
|
|
45800
|
-
subject: exports_external.optional(exports_external.string()).describe("Email subject (for
|
|
45823
|
+
subject: exports_external.optional(exports_external.string()).describe("Email subject (for Gmail channel only)"),
|
|
45801
45824
|
replyToMessageId: exports_external.optional(exports_external.string()).describe("Message ID to reply to (for threading)"),
|
|
45802
|
-
slack_blocks: exports_external.optional(exports_external.array(exports_external.record(exports_external.string(), exports_external.any()))).describe("Slack Block Kit blocks for rich formatting (Slack channel only). Array of block objects.")
|
|
45803
|
-
|
|
45825
|
+
slack_blocks: exports_external.optional(exports_external.array(exports_external.record(exports_external.string(), exports_external.any()))).describe("Slack Block Kit blocks for rich formatting (Slack channel only). Array of block objects."),
|
|
45826
|
+
googleAccountId: exports_external.optional(exports_external.string()).describe("Google account ID for Gmail channel. If omitted, auto-resolves when exactly one Gmail-enabled account exists.")
|
|
45827
|
+
}, async ({ channel, body, subject, replyToMessageId, slack_blocks, googleAccountId }) => {
|
|
45804
45828
|
try {
|
|
45829
|
+
if (channel === "gmail") {
|
|
45830
|
+
let accountId = googleAccountId;
|
|
45831
|
+
if (!accountId) {
|
|
45832
|
+
const accounts = await client.listGoogleAccounts();
|
|
45833
|
+
const gmailAccounts = accounts.filter((a2) => a2.gmailEnabled);
|
|
45834
|
+
if (gmailAccounts.length === 0) {
|
|
45835
|
+
return handleToolError(new Error("No Gmail-enabled Google accounts configured"));
|
|
45836
|
+
}
|
|
45837
|
+
if (gmailAccounts.length > 1) {
|
|
45838
|
+
return handleToolError(new Error(`Multiple Gmail-enabled accounts found. Specify googleAccountId. Accounts: ${gmailAccounts.map((a2) => `${a2.id} (${a2.email})`).join(", ")}`));
|
|
45839
|
+
}
|
|
45840
|
+
accountId = gmailAccounts[0].id;
|
|
45841
|
+
}
|
|
45842
|
+
const result2 = await client.sendGmailMessage(accountId, body, subject);
|
|
45843
|
+
return formatSuccess(result2);
|
|
45844
|
+
}
|
|
45805
45845
|
const result = await client.sendMessage({
|
|
45806
45846
|
channel,
|
|
45807
|
-
to,
|
|
45808
45847
|
body,
|
|
45809
45848
|
subject,
|
|
45810
45849
|
replyToMessageId,
|
|
@@ -45829,7 +45868,7 @@ var ChannelSchema, registerAssistantTools = (server, client) => {
|
|
|
45829
45868
|
var init_assistant = __esm(() => {
|
|
45830
45869
|
init_zod2();
|
|
45831
45870
|
init_utils();
|
|
45832
|
-
ChannelSchema = exports_external.enum(["whatsapp", "discord", "telegram", "slack", "
|
|
45871
|
+
ChannelSchema = exports_external.enum(["whatsapp", "discord", "telegram", "slack", "gmail"]);
|
|
45833
45872
|
});
|
|
45834
45873
|
|
|
45835
45874
|
// cli/src/mcp/tools/caldav.ts
|
|
@@ -46247,7 +46286,7 @@ async function runMcpServer(urlOverride, portOverride) {
|
|
|
46247
46286
|
const client = new FulcrumClient(urlOverride, portOverride);
|
|
46248
46287
|
const server = new McpServer({
|
|
46249
46288
|
name: "fulcrum",
|
|
46250
|
-
version: "
|
|
46289
|
+
version: "3.0.0"
|
|
46251
46290
|
});
|
|
46252
46291
|
registerTools(server, client);
|
|
46253
46292
|
const transport = new StdioServerTransport;
|
|
@@ -48596,7 +48635,7 @@ var marketplace_default = `{
|
|
|
48596
48635
|
"name": "fulcrum",
|
|
48597
48636
|
"source": "./",
|
|
48598
48637
|
"description": "Task orchestration for Claude Code",
|
|
48599
|
-
"version": "
|
|
48638
|
+
"version": "3.0.0",
|
|
48600
48639
|
"skills": [
|
|
48601
48640
|
"./skills/fulcrum"
|
|
48602
48641
|
],
|
|
@@ -49224,8 +49263,33 @@ var claudeCommand = defineCommand({
|
|
|
49224
49263
|
// cli/src/commands/notifications.ts
|
|
49225
49264
|
init_client();
|
|
49226
49265
|
init_errors();
|
|
49227
|
-
var VALID_CHANNELS = ["sound", "slack", "discord", "pushover"];
|
|
49266
|
+
var VALID_CHANNELS = ["sound", "slack", "discord", "pushover", "whatsapp", "telegram", "gmail"];
|
|
49228
49267
|
async function handleNotificationsCommand(action, positional, flags) {
|
|
49268
|
+
if (action === "test") {
|
|
49269
|
+
const [channel] = positional;
|
|
49270
|
+
if (!channel) {
|
|
49271
|
+
throw new CliError("MISSING_CHANNEL", `Channel is required. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49272
|
+
}
|
|
49273
|
+
if (!VALID_CHANNELS.includes(channel)) {
|
|
49274
|
+
throw new CliError("INVALID_CHANNEL", `Invalid channel: ${channel}. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49275
|
+
}
|
|
49276
|
+
} else if (action === "set") {
|
|
49277
|
+
const [channel, key, value] = positional;
|
|
49278
|
+
if (!channel) {
|
|
49279
|
+
throw new CliError("MISSING_CHANNEL", `Channel is required. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49280
|
+
}
|
|
49281
|
+
if (!VALID_CHANNELS.includes(channel)) {
|
|
49282
|
+
throw new CliError("INVALID_CHANNEL", `Invalid channel: ${channel}. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49283
|
+
}
|
|
49284
|
+
if (!key) {
|
|
49285
|
+
throw new CliError("MISSING_KEY", "Setting key is required", ExitCodes.INVALID_ARGS);
|
|
49286
|
+
}
|
|
49287
|
+
if (value === undefined) {
|
|
49288
|
+
throw new CliError("MISSING_VALUE", "Setting value is required", ExitCodes.INVALID_ARGS);
|
|
49289
|
+
}
|
|
49290
|
+
} else if (action !== "status" && action !== "enable" && action !== "disable" && action !== undefined) {
|
|
49291
|
+
throw new CliError("UNKNOWN_ACTION", `Unknown action: ${action}. Valid: status, enable, disable, test, set`, ExitCodes.INVALID_ARGS);
|
|
49292
|
+
}
|
|
49229
49293
|
const client = new FulcrumClient(flags.url, flags.port);
|
|
49230
49294
|
switch (action) {
|
|
49231
49295
|
case "status":
|
|
@@ -49249,6 +49313,17 @@ Channels:`);
|
|
|
49249
49313
|
if (settings.pushover) {
|
|
49250
49314
|
console.log(` pushover: ${settings.pushover.enabled ? "enabled" : "disabled"}`);
|
|
49251
49315
|
}
|
|
49316
|
+
if (settings.whatsapp) {
|
|
49317
|
+
console.log(` whatsapp: ${settings.whatsapp.enabled ? "enabled" : "disabled"} (messaging channel)`);
|
|
49318
|
+
}
|
|
49319
|
+
if (settings.telegram) {
|
|
49320
|
+
console.log(` telegram: ${settings.telegram.enabled ? "enabled" : "disabled"} (messaging channel)`);
|
|
49321
|
+
}
|
|
49322
|
+
if (settings.gmail) {
|
|
49323
|
+
const gmail = settings.gmail;
|
|
49324
|
+
const accountInfo = gmail.googleAccountId ? ` (account: ${gmail.googleAccountId})` : " (auto-resolve)";
|
|
49325
|
+
console.log(` gmail: ${gmail.enabled ? "enabled" : "disabled"}${gmail.enabled ? accountInfo : ""}`);
|
|
49326
|
+
}
|
|
49252
49327
|
}
|
|
49253
49328
|
break;
|
|
49254
49329
|
}
|
|
@@ -49272,12 +49347,6 @@ Channels:`);
|
|
|
49272
49347
|
}
|
|
49273
49348
|
case "test": {
|
|
49274
49349
|
const [channel] = positional;
|
|
49275
|
-
if (!channel) {
|
|
49276
|
-
throw new CliError("MISSING_CHANNEL", `Channel is required. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49277
|
-
}
|
|
49278
|
-
if (!VALID_CHANNELS.includes(channel)) {
|
|
49279
|
-
throw new CliError("INVALID_CHANNEL", `Invalid channel: ${channel}. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49280
|
-
}
|
|
49281
49350
|
const result = await client.testNotification(channel);
|
|
49282
49351
|
if (isJsonOutput()) {
|
|
49283
49352
|
output(result);
|
|
@@ -49292,18 +49361,6 @@ Channels:`);
|
|
|
49292
49361
|
}
|
|
49293
49362
|
case "set": {
|
|
49294
49363
|
const [channel, key, value] = positional;
|
|
49295
|
-
if (!channel) {
|
|
49296
|
-
throw new CliError("MISSING_CHANNEL", `Channel is required. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49297
|
-
}
|
|
49298
|
-
if (!VALID_CHANNELS.includes(channel)) {
|
|
49299
|
-
throw new CliError("INVALID_CHANNEL", `Invalid channel: ${channel}. Valid: ${VALID_CHANNELS.join(", ")}`, ExitCodes.INVALID_ARGS);
|
|
49300
|
-
}
|
|
49301
|
-
if (!key) {
|
|
49302
|
-
throw new CliError("MISSING_KEY", "Setting key is required", ExitCodes.INVALID_ARGS);
|
|
49303
|
-
}
|
|
49304
|
-
if (value === undefined) {
|
|
49305
|
-
throw new CliError("MISSING_VALUE", "Setting value is required", ExitCodes.INVALID_ARGS);
|
|
49306
|
-
}
|
|
49307
49364
|
const update = buildChannelUpdate(channel, key, value);
|
|
49308
49365
|
const updated = await client.updateNotifications(update);
|
|
49309
49366
|
if (isJsonOutput()) {
|
|
@@ -49313,8 +49370,6 @@ Channels:`);
|
|
|
49313
49370
|
}
|
|
49314
49371
|
break;
|
|
49315
49372
|
}
|
|
49316
|
-
default:
|
|
49317
|
-
throw new CliError("UNKNOWN_ACTION", `Unknown action: ${action}. Valid: status, enable, disable, test, set`, ExitCodes.INVALID_ARGS);
|
|
49318
49373
|
}
|
|
49319
49374
|
}
|
|
49320
49375
|
function buildChannelUpdate(channel, key, value) {
|
|
@@ -49350,7 +49405,7 @@ var notificationsTestCommand = defineCommand({
|
|
|
49350
49405
|
meta: { name: "test", description: "Test a notification channel" },
|
|
49351
49406
|
args: {
|
|
49352
49407
|
...globalArgs,
|
|
49353
|
-
channel: { type: "positional", description: "Channel to test (sound, slack, discord, pushover)", required: true }
|
|
49408
|
+
channel: { type: "positional", description: "Channel to test (sound, slack, discord, pushover, whatsapp, telegram)", required: true }
|
|
49354
49409
|
},
|
|
49355
49410
|
async run({ args }) {
|
|
49356
49411
|
setupJsonOutput(args);
|
|
@@ -49361,7 +49416,7 @@ var notificationsSetCommand = defineCommand({
|
|
|
49361
49416
|
meta: { name: "set", description: "Set a notification channel config" },
|
|
49362
49417
|
args: {
|
|
49363
49418
|
...globalArgs,
|
|
49364
|
-
channel: { type: "positional", description: "Channel (sound, slack, discord, pushover)", required: true },
|
|
49419
|
+
channel: { type: "positional", description: "Channel (sound, slack, discord, pushover, whatsapp, telegram)", required: true },
|
|
49365
49420
|
key: { type: "positional", description: "Config key", required: true },
|
|
49366
49421
|
value: { type: "positional", description: "Config value", required: true }
|
|
49367
49422
|
},
|
|
@@ -49390,12 +49445,12 @@ var notificationsCommand = defineCommand({
|
|
|
49390
49445
|
init_client();
|
|
49391
49446
|
init_errors();
|
|
49392
49447
|
async function handleNotifyCommand(positional, flags) {
|
|
49393
|
-
const client = new FulcrumClient(flags.url, flags.port);
|
|
49394
49448
|
const title = flags.title || positional[0];
|
|
49395
49449
|
const message = flags.message || positional.slice(1).join(" ") || positional[0];
|
|
49396
49450
|
if (!title) {
|
|
49397
49451
|
throw new CliError("MISSING_TITLE", "Title is required. Usage: fulcrum notify <title> [message] or --title=<title> --message=<message>", ExitCodes.INVALID_ARGS);
|
|
49398
49452
|
}
|
|
49453
|
+
const client = new FulcrumClient(flags.url, flags.port);
|
|
49399
49454
|
const result = await client.sendNotification(title, message || title);
|
|
49400
49455
|
if (isJsonOutput()) {
|
|
49401
49456
|
output(result);
|
|
@@ -49784,7 +49839,7 @@ function compareVersions(v1, v2) {
|
|
|
49784
49839
|
var package_default = {
|
|
49785
49840
|
name: "@knowsuchagency/fulcrum",
|
|
49786
49841
|
private: true,
|
|
49787
|
-
version: "
|
|
49842
|
+
version: "3.0.0",
|
|
49788
49843
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
49789
49844
|
license: "PolyForm-Perimeter-1.0.0",
|
|
49790
49845
|
type: "module",
|