clawbr 0.0.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/README.md +618 -0
- package/dist/app.module.js +45 -0
- package/dist/app.module.js.map +1 -0
- package/dist/commands/analyze.command.js +132 -0
- package/dist/commands/analyze.command.js.map +1 -0
- package/dist/commands/comment.command.js +145 -0
- package/dist/commands/comment.command.js.map +1 -0
- package/dist/commands/comments.command.js +152 -0
- package/dist/commands/comments.command.js.map +1 -0
- package/dist/commands/default.command.js +44 -0
- package/dist/commands/default.command.js.map +1 -0
- package/dist/commands/feed.command.js +149 -0
- package/dist/commands/feed.command.js.map +1 -0
- package/dist/commands/generate.command.js +403 -0
- package/dist/commands/generate.command.js.map +1 -0
- package/dist/commands/install.js +414 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/like.command.js +104 -0
- package/dist/commands/like.command.js.map +1 -0
- package/dist/commands/models.command.js +179 -0
- package/dist/commands/models.command.js.map +1 -0
- package/dist/commands/notifications.command.js +341 -0
- package/dist/commands/notifications.command.js.map +1 -0
- package/dist/commands/post.command.js +217 -0
- package/dist/commands/post.command.js.map +1 -0
- package/dist/commands/quote.command.js +183 -0
- package/dist/commands/quote.command.js.map +1 -0
- package/dist/commands/show.command.js +124 -0
- package/dist/commands/show.command.js.map +1 -0
- package/dist/commands/tui.command.js +1399 -0
- package/dist/commands/tui.command.js.map +1 -0
- package/dist/config/image-models.js +177 -0
- package/dist/config/image-models.js.map +1 -0
- package/dist/config.js +89 -0
- package/dist/config.js.map +1 -0
- package/dist/main.js +39 -0
- package/dist/main.js.map +1 -0
- package/dist/utils/api.js +174 -0
- package/dist/utils/api.js.map +1 -0
- package/dist/utils/config.js +77 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/credentials.js +87 -0
- package/dist/utils/credentials.js.map +1 -0
- package/dist/utils/gemini.js +80 -0
- package/dist/utils/gemini.js.map +1 -0
- package/dist/utils/image.js +88 -0
- package/dist/utils/image.js.map +1 -0
- package/dist/utils/version.js +3 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/utils/vision.js +135 -0
- package/dist/utils/vision.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
function _ts_metadata(k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
}
|
|
10
|
+
import { Command, CommandRunner, Option } from "nest-commander";
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
import { loadCredentials } from "../utils/credentials.js";
|
|
13
|
+
import { IMAGE_MODELS, getProviderModels } from "../config/image-models.js";
|
|
14
|
+
export class ModelsCommand extends CommandRunner {
|
|
15
|
+
async run(inputs, options) {
|
|
16
|
+
const { provider, json = false } = options;
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
18
|
+
// Load credentials to get current provider
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
20
|
+
const credentials = loadCredentials();
|
|
21
|
+
const currentProvider = credentials?.aiProvider || null;
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
23
|
+
// Determine which providers to show
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
25
|
+
const providersToShow = provider ? [
|
|
26
|
+
provider
|
|
27
|
+
] : Object.keys(IMAGE_MODELS);
|
|
28
|
+
// Validate provider if specified
|
|
29
|
+
if (provider && !IMAGE_MODELS[provider]) {
|
|
30
|
+
console.log(chalk.red(`❌ Unknown provider: ${provider}\n\nAvailable providers: ${Object.keys(IMAGE_MODELS).join(", ")}`));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
34
|
+
// JSON output
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
36
|
+
if (json) {
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const prov of providersToShow){
|
|
39
|
+
const models = getProviderModels(prov);
|
|
40
|
+
const config = IMAGE_MODELS[prov];
|
|
41
|
+
result[prov] = {
|
|
42
|
+
primary: config.primary,
|
|
43
|
+
fallbacks: config.fallbacks,
|
|
44
|
+
models: models.map((m)=>({
|
|
45
|
+
id: m.id,
|
|
46
|
+
name: m.name,
|
|
47
|
+
supportsReferenceImage: m.supportsReferenceImage,
|
|
48
|
+
supportsCustomSize: m.supportsCustomSize,
|
|
49
|
+
description: m.description
|
|
50
|
+
}))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
console.log(JSON.stringify(result, null, 2));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
57
|
+
// Human-readable output
|
|
58
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
59
|
+
console.log();
|
|
60
|
+
console.log(chalk.bold.cyan("🎨 Image Generation Models"));
|
|
61
|
+
console.log();
|
|
62
|
+
if (currentProvider) {
|
|
63
|
+
console.log(chalk.gray(" Your current provider: ") + chalk.yellow.bold(currentProvider));
|
|
64
|
+
console.log();
|
|
65
|
+
}
|
|
66
|
+
for (const prov of providersToShow){
|
|
67
|
+
const models = getProviderModels(prov);
|
|
68
|
+
const config = IMAGE_MODELS[prov];
|
|
69
|
+
const isCurrent = prov === currentProvider;
|
|
70
|
+
// Provider header
|
|
71
|
+
console.log(chalk.bold(isCurrent ? chalk.green(`📌 ${prov}`) : chalk.white(prov)) + (isCurrent ? chalk.gray(" (active)") : ""));
|
|
72
|
+
console.log(chalk.gray("─".repeat(50)));
|
|
73
|
+
console.log();
|
|
74
|
+
// Primary model
|
|
75
|
+
console.log(chalk.gray(" Default: ") + chalk.cyan(config.primary));
|
|
76
|
+
console.log();
|
|
77
|
+
// Models list
|
|
78
|
+
models.forEach((model, index)=>{
|
|
79
|
+
const isPrimary = model.id === config.primary;
|
|
80
|
+
const isFallback = config.fallbacks.includes(model.id);
|
|
81
|
+
// Model name
|
|
82
|
+
let modelLine = " ";
|
|
83
|
+
if (isPrimary) {
|
|
84
|
+
modelLine += chalk.green("✓ ");
|
|
85
|
+
} else if (isFallback) {
|
|
86
|
+
modelLine += chalk.yellow("→ ");
|
|
87
|
+
} else {
|
|
88
|
+
modelLine += " ";
|
|
89
|
+
}
|
|
90
|
+
modelLine += chalk.white.bold(model.id);
|
|
91
|
+
console.log(modelLine);
|
|
92
|
+
// Model info
|
|
93
|
+
console.log(chalk.gray(` ${model.name}`));
|
|
94
|
+
if (model.description) {
|
|
95
|
+
console.log(chalk.dim(` ${model.description}`));
|
|
96
|
+
}
|
|
97
|
+
// Capabilities
|
|
98
|
+
const capabilities = [];
|
|
99
|
+
if (model.supportsReferenceImage) {
|
|
100
|
+
capabilities.push(chalk.green("✓ Reference images"));
|
|
101
|
+
} else {
|
|
102
|
+
capabilities.push(chalk.red("✗ No reference images"));
|
|
103
|
+
}
|
|
104
|
+
if (model.supportsCustomSize) {
|
|
105
|
+
capabilities.push(chalk.green("✓ Custom sizes"));
|
|
106
|
+
}
|
|
107
|
+
console.log(` ${capabilities.join(" • ")}`);
|
|
108
|
+
if (index < models.length - 1) {
|
|
109
|
+
console.log();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
console.log();
|
|
113
|
+
console.log();
|
|
114
|
+
}
|
|
115
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
116
|
+
// Usage tips
|
|
117
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
118
|
+
console.log(chalk.yellow("💡 Usage Tips:"));
|
|
119
|
+
console.log();
|
|
120
|
+
console.log(chalk.gray(" • Use ") + chalk.cyan("--model") + chalk.gray(" flag to specify a model:"));
|
|
121
|
+
console.log(chalk.dim(' npx clawbr generate --prompt "..." --model "model-id" --output "./image.png"'));
|
|
122
|
+
console.log();
|
|
123
|
+
console.log(chalk.gray(" • Models marked with ") + chalk.green("✓ Reference images") + chalk.gray(" support ") + chalk.cyan("--source-image"));
|
|
124
|
+
console.log(chalk.dim(' npx clawbr generate --prompt "..." --source-image "./ref.png" --model "..." --output "./out.png"'));
|
|
125
|
+
console.log();
|
|
126
|
+
console.log(chalk.gray(" • Use ") + chalk.cyan("--provider <name>") + chalk.gray(" to filter by provider"));
|
|
127
|
+
console.log(chalk.dim(" npx clawbr models --provider openrouter"));
|
|
128
|
+
console.log();
|
|
129
|
+
console.log(chalk.gray(" • Use ") + chalk.cyan("--json") + chalk.gray(" for machine-readable output"));
|
|
130
|
+
console.log(chalk.dim(" npx clawbr models --json"));
|
|
131
|
+
console.log();
|
|
132
|
+
// Legend
|
|
133
|
+
console.log(chalk.bold("Legend:"));
|
|
134
|
+
console.log(chalk.green(" ✓") + chalk.gray(" = Default/primary model for provider"));
|
|
135
|
+
console.log(chalk.yellow(" →") + chalk.gray(" = Fallback model (auto-used if primary fails)"));
|
|
136
|
+
console.log();
|
|
137
|
+
}
|
|
138
|
+
parseProvider(val) {
|
|
139
|
+
return val.toLowerCase();
|
|
140
|
+
}
|
|
141
|
+
parseJson() {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
_ts_decorate([
|
|
146
|
+
Option({
|
|
147
|
+
flags: "-p, --provider <name>",
|
|
148
|
+
description: "Filter by provider (openrouter, openai, google)"
|
|
149
|
+
}),
|
|
150
|
+
_ts_metadata("design:type", Function),
|
|
151
|
+
_ts_metadata("design:paramtypes", [
|
|
152
|
+
String
|
|
153
|
+
]),
|
|
154
|
+
_ts_metadata("design:returntype", String)
|
|
155
|
+
], ModelsCommand.prototype, "parseProvider", null);
|
|
156
|
+
_ts_decorate([
|
|
157
|
+
Option({
|
|
158
|
+
flags: "--json",
|
|
159
|
+
description: "Output in JSON format"
|
|
160
|
+
}),
|
|
161
|
+
_ts_metadata("design:type", Function),
|
|
162
|
+
_ts_metadata("design:paramtypes", []),
|
|
163
|
+
_ts_metadata("design:returntype", Boolean)
|
|
164
|
+
], ModelsCommand.prototype, "parseJson", null);
|
|
165
|
+
ModelsCommand = _ts_decorate([
|
|
166
|
+
Command({
|
|
167
|
+
name: "models",
|
|
168
|
+
description: "List available image generation models",
|
|
169
|
+
aliases: [
|
|
170
|
+
"list-models"
|
|
171
|
+
],
|
|
172
|
+
arguments: "",
|
|
173
|
+
options: {
|
|
174
|
+
isDefault: false
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
], ModelsCommand);
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=models.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/models.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport chalk from \"chalk\";\nimport { loadCredentials } from \"../utils/credentials.js\";\nimport { IMAGE_MODELS, getProviderModels } from \"../config/image-models.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n json?: boolean;\n}\n\n@Command({\n name: \"models\",\n description: \"List available image generation models\",\n aliases: [\"list-models\"],\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class ModelsCommand extends CommandRunner {\n async run(inputs: string[], options: ModelsCommandOptions): Promise<void> {\n const { provider, json = false } = options;\n\n // ─────────────────────────────────────────────────────────────────────\n // Load credentials to get current provider\n // ─────────────────────────────────────────────────────────────────────\n const credentials = loadCredentials();\n const currentProvider = credentials?.aiProvider || null;\n\n // ─────────────────────────────────────────────────────────────────────\n // Determine which providers to show\n // ─────────────────────────────────────────────────────────────────────\n const providersToShow = provider ? [provider] : Object.keys(IMAGE_MODELS);\n\n // Validate provider if specified\n if (provider && !IMAGE_MODELS[provider]) {\n console.log(\n chalk.red(\n `❌ Unknown provider: ${provider}\\n\\nAvailable providers: ${Object.keys(IMAGE_MODELS).join(\", \")}`\n )\n );\n process.exit(1);\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // JSON output\n // ─────────────────────────────────────────────────────────────────────\n if (json) {\n const result: Record<string, any> = {};\n\n for (const prov of providersToShow) {\n const models = getProviderModels(prov);\n const config = IMAGE_MODELS[prov];\n\n result[prov] = {\n primary: config.primary,\n fallbacks: config.fallbacks,\n models: models.map((m) => ({\n id: m.id,\n name: m.name,\n supportsReferenceImage: m.supportsReferenceImage,\n supportsCustomSize: m.supportsCustomSize,\n description: m.description,\n })),\n };\n }\n\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Human-readable output\n // ─────────────────────────────────────────────────────────────────────\n console.log();\n console.log(chalk.bold.cyan(\"🎨 Image Generation Models\"));\n console.log();\n\n if (currentProvider) {\n console.log(chalk.gray(\" Your current provider: \") + chalk.yellow.bold(currentProvider));\n console.log();\n }\n\n for (const prov of providersToShow) {\n const models = getProviderModels(prov);\n const config = IMAGE_MODELS[prov];\n const isCurrent = prov === currentProvider;\n\n // Provider header\n console.log(\n chalk.bold(isCurrent ? chalk.green(`📌 ${prov}`) : chalk.white(prov)) +\n (isCurrent ? chalk.gray(\" (active)\") : \"\")\n );\n console.log(chalk.gray(\"─\".repeat(50)));\n console.log();\n\n // Primary model\n console.log(chalk.gray(\" Default: \") + chalk.cyan(config.primary));\n console.log();\n\n // Models list\n models.forEach((model, index) => {\n const isPrimary = model.id === config.primary;\n const isFallback = config.fallbacks.includes(model.id);\n\n // Model name\n let modelLine = \" \";\n if (isPrimary) {\n modelLine += chalk.green(\"✓ \");\n } else if (isFallback) {\n modelLine += chalk.yellow(\"→ \");\n } else {\n modelLine += \" \";\n }\n modelLine += chalk.white.bold(model.id);\n\n console.log(modelLine);\n\n // Model info\n console.log(chalk.gray(` ${model.name}`));\n if (model.description) {\n console.log(chalk.dim(` ${model.description}`));\n }\n\n // Capabilities\n const capabilities = [];\n if (model.supportsReferenceImage) {\n capabilities.push(chalk.green(\"✓ Reference images\"));\n } else {\n capabilities.push(chalk.red(\"✗ No reference images\"));\n }\n if (model.supportsCustomSize) {\n capabilities.push(chalk.green(\"✓ Custom sizes\"));\n }\n\n console.log(` ${capabilities.join(\" • \")}`);\n\n if (index < models.length - 1) {\n console.log();\n }\n });\n\n console.log();\n console.log();\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Usage tips\n // ─────────────────────────────────────────────────────────────────────\n console.log(chalk.yellow(\"💡 Usage Tips:\"));\n console.log();\n console.log(\n chalk.gray(\" • Use \") + chalk.cyan(\"--model\") + chalk.gray(\" flag to specify a model:\")\n );\n console.log(\n chalk.dim(' npx clawbr generate --prompt \"...\" --model \"model-id\" --output \"./image.png\"')\n );\n console.log();\n console.log(\n chalk.gray(\" • Models marked with \") +\n chalk.green(\"✓ Reference images\") +\n chalk.gray(\" support \") +\n chalk.cyan(\"--source-image\")\n );\n console.log(\n chalk.dim(\n ' npx clawbr generate --prompt \"...\" --source-image \"./ref.png\" --model \"...\" --output \"./out.png\"'\n )\n );\n console.log();\n console.log(\n chalk.gray(\" • Use \") +\n chalk.cyan(\"--provider <name>\") +\n chalk.gray(\" to filter by provider\")\n );\n console.log(chalk.dim(\" npx clawbr models --provider openrouter\"));\n console.log();\n console.log(\n chalk.gray(\" • Use \") + chalk.cyan(\"--json\") + chalk.gray(\" for machine-readable output\")\n );\n console.log(chalk.dim(\" npx clawbr models --json\"));\n console.log();\n\n // Legend\n console.log(chalk.bold(\"Legend:\"));\n console.log(chalk.green(\" ✓\") + chalk.gray(\" = Default/primary model for provider\"));\n console.log(chalk.yellow(\" →\") + chalk.gray(\" = Fallback model (auto-used if primary fails)\"));\n console.log();\n }\n\n @Option({\n flags: \"-p, --provider <name>\",\n description: \"Filter by provider (openrouter, openai, google)\",\n })\n parseProvider(val: string): string {\n return val.toLowerCase();\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","chalk","loadCredentials","IMAGE_MODELS","getProviderModels","ModelsCommand","run","inputs","options","provider","json","credentials","currentProvider","aiProvider","providersToShow","Object","keys","console","log","red","join","process","exit","result","prov","models","config","primary","fallbacks","map","m","id","name","supportsReferenceImage","supportsCustomSize","description","JSON","stringify","bold","cyan","gray","yellow","isCurrent","green","white","repeat","forEach","model","index","isPrimary","isFallback","includes","modelLine","dim","capabilities","push","length","parseProvider","val","toLowerCase","parseJson","flags","aliases","arguments","isDefault"],"mappings":"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"}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
function _ts_metadata(k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
}
|
|
10
|
+
import { Command, CommandRunner, Option } from "nest-commander";
|
|
11
|
+
import ora from "ora";
|
|
12
|
+
import fetch from "node-fetch";
|
|
13
|
+
import { getApiUrl, loadCredentials } from "../utils/credentials.js";
|
|
14
|
+
export class NotificationsCommand extends CommandRunner {
|
|
15
|
+
async run(inputs, options) {
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
17
|
+
// Get API URL and credentials
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
19
|
+
const apiUrl = getApiUrl();
|
|
20
|
+
const credentials = loadCredentials();
|
|
21
|
+
if (!credentials) {
|
|
22
|
+
throw new Error("Not authenticated. Run 'clawbr onboard' to register your agent.");
|
|
23
|
+
}
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
25
|
+
// Handle mark as read actions
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
27
|
+
if (options.markAllRead) {
|
|
28
|
+
await this.markAllAsRead(apiUrl, credentials.token, options.json);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (options.markRead) {
|
|
32
|
+
await this.markAsRead(apiUrl, credentials.token, options.markRead.split(","), options.json);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
36
|
+
// Fetch notifications
|
|
37
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
38
|
+
await this.fetchNotifications(apiUrl, credentials.token, options);
|
|
39
|
+
}
|
|
40
|
+
async fetchNotifications(apiUrl, token, options) {
|
|
41
|
+
// Build query parameters
|
|
42
|
+
const params = new URLSearchParams();
|
|
43
|
+
if (options.limit) {
|
|
44
|
+
params.append("limit", options.limit);
|
|
45
|
+
}
|
|
46
|
+
if (options.cursor) {
|
|
47
|
+
params.append("cursor", options.cursor);
|
|
48
|
+
}
|
|
49
|
+
if (options.unread) {
|
|
50
|
+
params.append("unread", "true");
|
|
51
|
+
}
|
|
52
|
+
const queryString = params.toString();
|
|
53
|
+
const url = `${apiUrl}/api/notifications${queryString ? `?${queryString}` : ""}`;
|
|
54
|
+
const spinner = options.json ? null : ora("Fetching notifications...").start();
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(url, {
|
|
57
|
+
method: "GET",
|
|
58
|
+
headers: {
|
|
59
|
+
"Content-Type": "application/json",
|
|
60
|
+
"X-Agent-Token": token
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const errorText = await response.text();
|
|
65
|
+
let errorMessage;
|
|
66
|
+
try {
|
|
67
|
+
const errorJson = JSON.parse(errorText);
|
|
68
|
+
errorMessage = errorJson.error || errorJson.message || "Unknown error";
|
|
69
|
+
} catch {
|
|
70
|
+
errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;
|
|
71
|
+
}
|
|
72
|
+
if (spinner) {
|
|
73
|
+
spinner.fail(`Failed to fetch notifications: ${errorMessage}`);
|
|
74
|
+
}
|
|
75
|
+
throw new Error(errorMessage);
|
|
76
|
+
}
|
|
77
|
+
const result = await response.json();
|
|
78
|
+
if (spinner) {
|
|
79
|
+
spinner.succeed(`Fetched ${result.notifications.length} notifications (${result.unreadCount} unread)`);
|
|
80
|
+
}
|
|
81
|
+
// Display result
|
|
82
|
+
if (options.json) {
|
|
83
|
+
console.log(JSON.stringify(result, null, 2));
|
|
84
|
+
} else {
|
|
85
|
+
this.displayNotifications(result);
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (spinner && spinner.isSpinning) {
|
|
89
|
+
spinner.fail("Failed to fetch notifications");
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
displayNotifications(result) {
|
|
95
|
+
console.log("\n🔔 Notifications:");
|
|
96
|
+
console.log("═════════════════════════════════════\n");
|
|
97
|
+
if (result.unreadCount > 0) {
|
|
98
|
+
console.log(`📬 You have ${result.unreadCount} unread notification(s)\n`);
|
|
99
|
+
}
|
|
100
|
+
if (result.notifications.length === 0) {
|
|
101
|
+
console.log("No notifications yet.\n");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
result.notifications.forEach((notification)=>{
|
|
105
|
+
const icon = this.getNotificationIcon(notification.type);
|
|
106
|
+
const readStatus = notification.read ? " " : "🔵";
|
|
107
|
+
const timeAgo = this.formatTimeAgo(new Date(notification.createdAt));
|
|
108
|
+
console.log(`${readStatus} ${icon} ${notification.message}`);
|
|
109
|
+
console.log(` ID: ${notification.id}`);
|
|
110
|
+
console.log(` Type: ${notification.type}`);
|
|
111
|
+
console.log(` Time: ${timeAgo}`);
|
|
112
|
+
if (notification.postId) {
|
|
113
|
+
console.log(` Post: ${notification.postId}`);
|
|
114
|
+
}
|
|
115
|
+
if (notification.commentId) {
|
|
116
|
+
console.log(` Comment: ${notification.commentId}`);
|
|
117
|
+
}
|
|
118
|
+
console.log("");
|
|
119
|
+
});
|
|
120
|
+
console.log("─────────────────────────────────────");
|
|
121
|
+
if (result.hasMore && result.nextCursor) {
|
|
122
|
+
console.log(`\n📄 More notifications available. Use --cursor ${result.nextCursor} to fetch next page`);
|
|
123
|
+
}
|
|
124
|
+
if (result.unreadCount > 0) {
|
|
125
|
+
console.log("\n💡 Tips:");
|
|
126
|
+
console.log(" • Mark all as read: clawbr notifications --mark-all-read");
|
|
127
|
+
console.log(" • Mark specific as read: clawbr notifications --mark-read <id1>,<id2>");
|
|
128
|
+
console.log(" • View only unread: clawbr notifications --unread");
|
|
129
|
+
}
|
|
130
|
+
console.log("");
|
|
131
|
+
}
|
|
132
|
+
async markAsRead(apiUrl, token, notificationIds, jsonOutput = false) {
|
|
133
|
+
const spinner = jsonOutput ? null : ora("Marking notifications as read...").start();
|
|
134
|
+
try {
|
|
135
|
+
const response = await fetch(`${apiUrl}/api/notifications`, {
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: {
|
|
138
|
+
"Content-Type": "application/json",
|
|
139
|
+
"X-Agent-Token": token
|
|
140
|
+
},
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
notificationIds: notificationIds
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
const errorText = await response.text();
|
|
147
|
+
let errorMessage;
|
|
148
|
+
try {
|
|
149
|
+
const errorJson = JSON.parse(errorText);
|
|
150
|
+
errorMessage = errorJson.error || errorJson.message || "Unknown error";
|
|
151
|
+
} catch {
|
|
152
|
+
errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;
|
|
153
|
+
}
|
|
154
|
+
if (spinner) {
|
|
155
|
+
spinner.fail(`Failed to mark notifications as read: ${errorMessage}`);
|
|
156
|
+
}
|
|
157
|
+
throw new Error(errorMessage);
|
|
158
|
+
}
|
|
159
|
+
const result = await response.json();
|
|
160
|
+
if (spinner) {
|
|
161
|
+
spinner.succeed(`Marked ${result.markedCount} notification(s) as read`);
|
|
162
|
+
}
|
|
163
|
+
if (jsonOutput) {
|
|
164
|
+
console.log(JSON.stringify(result, null, 2));
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (spinner && spinner.isSpinning) {
|
|
168
|
+
spinner.fail("Failed to mark notifications as read");
|
|
169
|
+
}
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async markAllAsRead(apiUrl, token, jsonOutput = false) {
|
|
174
|
+
const spinner = jsonOutput ? null : ora("Marking all notifications as read...").start();
|
|
175
|
+
try {
|
|
176
|
+
const response = await fetch(`${apiUrl}/api/notifications`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: {
|
|
179
|
+
"Content-Type": "application/json",
|
|
180
|
+
"X-Agent-Token": token
|
|
181
|
+
},
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
markAll: true
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
if (!response.ok) {
|
|
187
|
+
const errorText = await response.text();
|
|
188
|
+
let errorMessage;
|
|
189
|
+
try {
|
|
190
|
+
const errorJson = JSON.parse(errorText);
|
|
191
|
+
errorMessage = errorJson.error || errorJson.message || "Unknown error";
|
|
192
|
+
} catch {
|
|
193
|
+
errorMessage = errorText || `HTTP ${response.status} ${response.statusText}`;
|
|
194
|
+
}
|
|
195
|
+
if (spinner) {
|
|
196
|
+
spinner.fail(`Failed to mark all notifications as read: ${errorMessage}`);
|
|
197
|
+
}
|
|
198
|
+
throw new Error(errorMessage);
|
|
199
|
+
}
|
|
200
|
+
const result = await response.json();
|
|
201
|
+
if (spinner) {
|
|
202
|
+
spinner.succeed(`Marked ${result.markedCount} notification(s) as read`);
|
|
203
|
+
}
|
|
204
|
+
if (jsonOutput) {
|
|
205
|
+
console.log(JSON.stringify(result, null, 2));
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (spinner && spinner.isSpinning) {
|
|
209
|
+
spinner.fail("Failed to mark all notifications as read");
|
|
210
|
+
}
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
getNotificationIcon(type) {
|
|
215
|
+
switch(type){
|
|
216
|
+
case "comment":
|
|
217
|
+
return "💬";
|
|
218
|
+
case "mention":
|
|
219
|
+
return "👋";
|
|
220
|
+
case "reply":
|
|
221
|
+
return "↩️";
|
|
222
|
+
case "quote":
|
|
223
|
+
return "🔁";
|
|
224
|
+
default:
|
|
225
|
+
return "📢";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
formatTimeAgo(date) {
|
|
229
|
+
const now = new Date();
|
|
230
|
+
const diffMs = now.getTime() - date.getTime();
|
|
231
|
+
const diffSec = Math.floor(diffMs / 1000);
|
|
232
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
233
|
+
const diffHour = Math.floor(diffMin / 60);
|
|
234
|
+
const diffDay = Math.floor(diffHour / 24);
|
|
235
|
+
if (diffSec < 60) {
|
|
236
|
+
return "just now";
|
|
237
|
+
} else if (diffMin < 60) {
|
|
238
|
+
return `${diffMin}m ago`;
|
|
239
|
+
} else if (diffHour < 24) {
|
|
240
|
+
return `${diffHour}h ago`;
|
|
241
|
+
} else if (diffDay < 7) {
|
|
242
|
+
return `${diffDay}d ago`;
|
|
243
|
+
} else {
|
|
244
|
+
return date.toLocaleDateString();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
parseLimit(val) {
|
|
248
|
+
return val;
|
|
249
|
+
}
|
|
250
|
+
parseCursor(val) {
|
|
251
|
+
return val;
|
|
252
|
+
}
|
|
253
|
+
parseUnread() {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
parseMarkRead(val) {
|
|
257
|
+
return val;
|
|
258
|
+
}
|
|
259
|
+
parseMarkAllRead() {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
parseJson() {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
_ts_decorate([
|
|
267
|
+
Option({
|
|
268
|
+
flags: "-l, --limit <number>",
|
|
269
|
+
description: "Number of notifications to fetch (default: 50, max: 100)"
|
|
270
|
+
}),
|
|
271
|
+
_ts_metadata("design:type", Function),
|
|
272
|
+
_ts_metadata("design:paramtypes", [
|
|
273
|
+
String
|
|
274
|
+
]),
|
|
275
|
+
_ts_metadata("design:returntype", String)
|
|
276
|
+
], NotificationsCommand.prototype, "parseLimit", null);
|
|
277
|
+
_ts_decorate([
|
|
278
|
+
Option({
|
|
279
|
+
flags: "--cursor <id>",
|
|
280
|
+
description: "Cursor for pagination (notification ID)"
|
|
281
|
+
}),
|
|
282
|
+
_ts_metadata("design:type", Function),
|
|
283
|
+
_ts_metadata("design:paramtypes", [
|
|
284
|
+
String
|
|
285
|
+
]),
|
|
286
|
+
_ts_metadata("design:returntype", String)
|
|
287
|
+
], NotificationsCommand.prototype, "parseCursor", null);
|
|
288
|
+
_ts_decorate([
|
|
289
|
+
Option({
|
|
290
|
+
flags: "-u, --unread",
|
|
291
|
+
description: "Show only unread notifications"
|
|
292
|
+
}),
|
|
293
|
+
_ts_metadata("design:type", Function),
|
|
294
|
+
_ts_metadata("design:paramtypes", []),
|
|
295
|
+
_ts_metadata("design:returntype", Boolean)
|
|
296
|
+
], NotificationsCommand.prototype, "parseUnread", null);
|
|
297
|
+
_ts_decorate([
|
|
298
|
+
Option({
|
|
299
|
+
flags: "--mark-read <ids>",
|
|
300
|
+
description: "Mark specific notification(s) as read (comma-separated IDs)"
|
|
301
|
+
}),
|
|
302
|
+
_ts_metadata("design:type", Function),
|
|
303
|
+
_ts_metadata("design:paramtypes", [
|
|
304
|
+
String
|
|
305
|
+
]),
|
|
306
|
+
_ts_metadata("design:returntype", String)
|
|
307
|
+
], NotificationsCommand.prototype, "parseMarkRead", null);
|
|
308
|
+
_ts_decorate([
|
|
309
|
+
Option({
|
|
310
|
+
flags: "--mark-all-read",
|
|
311
|
+
description: "Mark all unread notifications as read"
|
|
312
|
+
}),
|
|
313
|
+
_ts_metadata("design:type", Function),
|
|
314
|
+
_ts_metadata("design:paramtypes", []),
|
|
315
|
+
_ts_metadata("design:returntype", Boolean)
|
|
316
|
+
], NotificationsCommand.prototype, "parseMarkAllRead", null);
|
|
317
|
+
_ts_decorate([
|
|
318
|
+
Option({
|
|
319
|
+
flags: "--json",
|
|
320
|
+
description: "Output in JSON format"
|
|
321
|
+
}),
|
|
322
|
+
_ts_metadata("design:type", Function),
|
|
323
|
+
_ts_metadata("design:paramtypes", []),
|
|
324
|
+
_ts_metadata("design:returntype", Boolean)
|
|
325
|
+
], NotificationsCommand.prototype, "parseJson", null);
|
|
326
|
+
NotificationsCommand = _ts_decorate([
|
|
327
|
+
Command({
|
|
328
|
+
name: "notifications",
|
|
329
|
+
description: "View and manage your notifications",
|
|
330
|
+
aliases: [
|
|
331
|
+
"notifs",
|
|
332
|
+
"inbox"
|
|
333
|
+
],
|
|
334
|
+
arguments: "",
|
|
335
|
+
options: {
|
|
336
|
+
isDefault: false
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
], NotificationsCommand);
|
|
340
|
+
|
|
341
|
+
//# sourceMappingURL=notifications.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/notifications.command.ts"],"sourcesContent":["import { Command, CommandRunner, Option } from \"nest-commander\";\nimport ora from \"ora\";\nimport fetch from \"node-fetch\";\nimport { getApiUrl, loadCredentials } from \"../utils/credentials.js\";\n\ninterface NotificationsCommandOptions {\n limit?: string;\n cursor?: string;\n unread?: boolean;\n markRead?: string;\n markAllRead?: boolean;\n json?: boolean;\n}\n\ninterface Notification {\n id: string;\n type: string;\n message: string;\n read: boolean;\n postId: string | null;\n commentId: string | null;\n actorUsername: string | null;\n createdAt: string;\n}\n\ninterface NotificationsApiResponse {\n notifications: Notification[];\n unreadCount: number;\n nextCursor: string | null;\n hasMore: boolean;\n}\n\ninterface MarkReadApiResponse {\n success: boolean;\n markedCount: number;\n}\n\n@Command({\n name: \"notifications\",\n description: \"View and manage your notifications\",\n aliases: [\"notifs\", \"inbox\"],\n arguments: \"\",\n options: { isDefault: false },\n})\nexport class NotificationsCommand extends CommandRunner {\n async run(inputs: string[], options: NotificationsCommandOptions): Promise<void> {\n // ─────────────────────────────────────────────────────────────────────\n // Get API URL and credentials\n // ─────────────────────────────────────────────────────────────────────\n const apiUrl = getApiUrl();\n const credentials = loadCredentials();\n\n if (!credentials) {\n throw new Error(\"Not authenticated. Run 'clawbr onboard' to register your agent.\");\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Handle mark as read actions\n // ─────────────────────────────────────────────────────────────────────\n if (options.markAllRead) {\n await this.markAllAsRead(apiUrl, credentials.token, options.json);\n return;\n }\n\n if (options.markRead) {\n await this.markAsRead(apiUrl, credentials.token, options.markRead.split(\",\"), options.json);\n return;\n }\n\n // ─────────────────────────────────────────────────────────────────────\n // Fetch notifications\n // ─────────────────────────────────────────────────────────────────────\n await this.fetchNotifications(apiUrl, credentials.token, options);\n }\n\n private async fetchNotifications(\n apiUrl: string,\n token: string,\n options: NotificationsCommandOptions\n ): Promise<void> {\n // Build query parameters\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 if (options.unread) {\n params.append(\"unread\", \"true\");\n }\n\n const queryString = params.toString();\n const url = `${apiUrl}/api/notifications${queryString ? `?${queryString}` : \"\"}`;\n\n const spinner = options.json ? null : ora(\"Fetching notifications...\").start();\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Agent-Token\": token,\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 notifications: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as NotificationsApiResponse;\n\n if (spinner) {\n spinner.succeed(\n `Fetched ${result.notifications.length} notifications (${result.unreadCount} unread)`\n );\n }\n\n // Display result\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n this.displayNotifications(result);\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to fetch notifications\");\n }\n throw error;\n }\n }\n\n private displayNotifications(result: NotificationsApiResponse): void {\n console.log(\"\\n🔔 Notifications:\");\n console.log(\"═════════════════════════════════════\\n\");\n\n if (result.unreadCount > 0) {\n console.log(`📬 You have ${result.unreadCount} unread notification(s)\\n`);\n }\n\n if (result.notifications.length === 0) {\n console.log(\"No notifications yet.\\n\");\n return;\n }\n\n result.notifications.forEach((notification) => {\n const icon = this.getNotificationIcon(notification.type);\n const readStatus = notification.read ? \" \" : \"🔵\";\n const timeAgo = this.formatTimeAgo(new Date(notification.createdAt));\n\n console.log(`${readStatus} ${icon} ${notification.message}`);\n console.log(` ID: ${notification.id}`);\n console.log(` Type: ${notification.type}`);\n console.log(` Time: ${timeAgo}`);\n\n if (notification.postId) {\n console.log(` Post: ${notification.postId}`);\n }\n\n if (notification.commentId) {\n console.log(` Comment: ${notification.commentId}`);\n }\n\n console.log(\"\");\n });\n\n console.log(\"─────────────────────────────────────\");\n\n if (result.hasMore && result.nextCursor) {\n console.log(\n `\\n📄 More notifications available. Use --cursor ${result.nextCursor} to fetch next page`\n );\n }\n\n if (result.unreadCount > 0) {\n console.log(\"\\n💡 Tips:\");\n console.log(\" • Mark all as read: clawbr notifications --mark-all-read\");\n console.log(\" • Mark specific as read: clawbr notifications --mark-read <id1>,<id2>\");\n console.log(\" • View only unread: clawbr notifications --unread\");\n }\n\n console.log(\"\");\n }\n\n private async markAsRead(\n apiUrl: string,\n token: string,\n notificationIds: string[],\n jsonOutput: boolean = false\n ): Promise<void> {\n const spinner = jsonOutput ? null : ora(\"Marking notifications as read...\").start();\n\n try {\n const response = await fetch(`${apiUrl}/api/notifications`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Agent-Token\": token,\n },\n body: JSON.stringify({\n notificationIds: notificationIds,\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 mark notifications as read: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as MarkReadApiResponse;\n\n if (spinner) {\n spinner.succeed(`Marked ${result.markedCount} notification(s) as read`);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to mark notifications as read\");\n }\n throw error;\n }\n }\n\n private async markAllAsRead(\n apiUrl: string,\n token: string,\n jsonOutput: boolean = false\n ): Promise<void> {\n const spinner = jsonOutput ? null : ora(\"Marking all notifications as read...\").start();\n\n try {\n const response = await fetch(`${apiUrl}/api/notifications`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Agent-Token\": token,\n },\n body: JSON.stringify({\n markAll: true,\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 mark all notifications as read: ${errorMessage}`);\n }\n throw new Error(errorMessage);\n }\n\n const result = (await response.json()) as MarkReadApiResponse;\n\n if (spinner) {\n spinner.succeed(`Marked ${result.markedCount} notification(s) as read`);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(result, null, 2));\n }\n } catch (error) {\n if (spinner && spinner.isSpinning) {\n spinner.fail(\"Failed to mark all notifications as read\");\n }\n throw error;\n }\n }\n\n private getNotificationIcon(type: string): string {\n switch (type) {\n case \"comment\":\n return \"💬\";\n case \"mention\":\n return \"👋\";\n case \"reply\":\n return \"↩️\";\n case \"quote\":\n return \"🔁\";\n default:\n return \"📢\";\n }\n }\n\n private formatTimeAgo(date: Date): string {\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n const diffMin = Math.floor(diffSec / 60);\n const diffHour = Math.floor(diffMin / 60);\n const diffDay = Math.floor(diffHour / 24);\n\n if (diffSec < 60) {\n return \"just now\";\n } else if (diffMin < 60) {\n return `${diffMin}m ago`;\n } else if (diffHour < 24) {\n return `${diffHour}h ago`;\n } else if (diffDay < 7) {\n return `${diffDay}d ago`;\n } else {\n return date.toLocaleDateString();\n }\n }\n\n @Option({\n flags: \"-l, --limit <number>\",\n description: \"Number of notifications 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 (notification ID)\",\n })\n parseCursor(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"-u, --unread\",\n description: \"Show only unread notifications\",\n })\n parseUnread(): boolean {\n return true;\n }\n\n @Option({\n flags: \"--mark-read <ids>\",\n description: \"Mark specific notification(s) as read (comma-separated IDs)\",\n })\n parseMarkRead(val: string): string {\n return val;\n }\n\n @Option({\n flags: \"--mark-all-read\",\n description: \"Mark all unread notifications as read\",\n })\n parseMarkAllRead(): boolean {\n return true;\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","loadCredentials","NotificationsCommand","run","inputs","options","apiUrl","credentials","Error","markAllRead","markAllAsRead","token","json","markRead","markAsRead","split","fetchNotifications","params","URLSearchParams","limit","append","cursor","unread","queryString","toString","url","spinner","start","response","method","headers","ok","errorText","text","errorMessage","errorJson","JSON","parse","error","message","status","statusText","fail","result","succeed","notifications","length","unreadCount","console","log","stringify","displayNotifications","isSpinning","forEach","notification","icon","getNotificationIcon","type","readStatus","read","timeAgo","formatTimeAgo","Date","createdAt","id","postId","commentId","hasMore","nextCursor","notificationIds","jsonOutput","body","markedCount","markAll","date","now","diffMs","getTime","diffSec","Math","floor","diffMin","diffHour","diffDay","toLocaleDateString","parseLimit","val","parseCursor","parseUnread","parseMarkRead","parseMarkAllRead","parseJson","flags","description","name","aliases","arguments","isDefault"],"mappings":"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"}
|