@circleback/cli 0.1.4 → 0.1.6

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.
@@ -12,6 +12,7 @@ const date_1 = require("../helpers/date");
12
12
  const error_1 = require("../helpers/error");
13
13
  const formatter_1 = require("../helpers/formatter");
14
14
  const parse_1 = require("../helpers/parse");
15
+ const tag_1 = require("../helpers/tag");
15
16
  const DEFAULT_ACTION_ITEMS_SEARCH_LAST_DAYS = 30;
16
17
  exports.searchActionItemsCommand = new commander_1.Command('search')
17
18
  .description('Search action items.')
@@ -21,7 +22,7 @@ exports.searchActionItemsCommand = new commander_1.Command('search')
21
22
  .option('--last <days>', 'Show action items from the last N days')
22
23
  .option('--from <date>', constants_1.START_DATE_OPTION_DESCRIPTION)
23
24
  .option('--to <date>', constants_1.END_DATE_OPTION_DESCRIPTION)
24
- .option('--tags <ids>', constants_1.TAGS_OPTION_DESCRIPTION)
25
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
25
26
  .option('--assignee <id>', 'Filter by assignee profile ID')
26
27
  .action(async (query, options) => {
27
28
  try {
@@ -50,8 +51,9 @@ exports.searchActionItemsCommand = new commander_1.Command('search')
50
51
  }
51
52
  if (options.to)
52
53
  args['endDate'] = options.to;
53
- if (options.tags)
54
- args['tags'] = (0, parse_1.parseNumericIds)(options.tags, 'tag ID');
54
+ if (options.tags) {
55
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
56
+ }
55
57
  if (options.assignee)
56
58
  args['assigneeProfileId'] = (0, parse_1.parseIntOption)(options.assignee, '--assignee');
57
59
  const result = await (0, jsonRpc_1.callTool)('SearchActionItems', args);
@@ -12,6 +12,7 @@ const date_1 = require("../helpers/date");
12
12
  const error_1 = require("../helpers/error");
13
13
  const formatter_1 = require("../helpers/formatter");
14
14
  const parse_1 = require("../helpers/parse");
15
+ const tag_1 = require("../helpers/tag");
15
16
  const DEFAULT_MEETINGS_SEARCH_LAST_DAYS = 7;
16
17
  exports.searchMeetingsCommand = new commander_1.Command('search')
17
18
  .description('Search meetings.')
@@ -20,7 +21,7 @@ exports.searchMeetingsCommand = new commander_1.Command('search')
20
21
  .option('--last <days>', 'Show meetings from the last N days')
21
22
  .option('--from <date>', constants_1.START_DATE_OPTION_DESCRIPTION)
22
23
  .option('--to <date>', constants_1.END_DATE_OPTION_DESCRIPTION)
23
- .option('--tags <ids>', constants_1.TAGS_OPTION_DESCRIPTION)
24
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
24
25
  .option('--profiles <ids>', constants_1.PROFILES_OPTION_DESCRIPTION)
25
26
  .option('--domains <domains>', constants_1.DOMAINS_OPTION_DESCRIPTION)
26
27
  .action(async (query, options) => {
@@ -48,8 +49,9 @@ exports.searchMeetingsCommand = new commander_1.Command('search')
48
49
  }
49
50
  if (options.to)
50
51
  args['endDate'] = options.to;
51
- if (options.tags)
52
- args['tags'] = (0, parse_1.parseNumericIds)(options.tags, 'tag ID');
52
+ if (options.tags) {
53
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
54
+ }
53
55
  if (options.profiles)
54
56
  args['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
55
57
  if (options.domains)
@@ -10,6 +10,7 @@ const emails_1 = require("./emails");
10
10
  const meetings_1 = require("./meetings");
11
11
  const profiles_1 = require("./profiles");
12
12
  const support_1 = require("./support");
13
+ const tags_1 = require("./tags");
13
14
  const transcripts_1 = require("./transcripts");
14
15
  const upgrade_1 = require("./upgrade");
15
16
  exports.standaloneCommands = [
@@ -58,6 +59,11 @@ exports.commandGroups = [
58
59
  description: 'Search action items.',
59
60
  subcommands: [actionItems_1.searchActionItemsCommand],
60
61
  },
62
+ {
63
+ name: 'tags',
64
+ description: 'List tags.',
65
+ subcommands: [tags_1.listTagsCommand],
66
+ },
61
67
  ];
62
68
  const buildCommandGroup = (definition) => definition.subcommands.reduce((group, command, index) => group.addCommand(command, index === 0 ? { isDefault: true } : undefined), new commander_1.Command(definition.name).description(definition.description));
63
69
  const getAllCommands = () => [
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listTagsCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const jsonRpc_1 = require("../client/jsonRpc");
10
+ const error_1 = require("../helpers/error");
11
+ const formatter_1 = require("../helpers/formatter");
12
+ exports.listTagsCommand = new commander_1.Command('list')
13
+ .description('List all tags.')
14
+ .action(async () => {
15
+ try {
16
+ const jsonMode = exports.listTagsCommand.parent?.parent?.opts().json ?? false;
17
+ const result = await (0, jsonRpc_1.callTool)('ListTags', {
18
+ intent: 'Listing all tags.',
19
+ });
20
+ (0, formatter_1.formatOutput)('ListTags', result, jsonMode);
21
+ }
22
+ catch (error) {
23
+ const message = error instanceof Error ? error.message : 'Failed to list tags.';
24
+ console.error(chalk_1.default.red((0, error_1.formatMcpError)(message) ?? message));
25
+ process.exit(1);
26
+ }
27
+ });
@@ -11,10 +11,11 @@ const constants_1 = require("../constants");
11
11
  const error_1 = require("../helpers/error");
12
12
  const formatter_1 = require("../helpers/formatter");
13
13
  const parse_1 = require("../helpers/parse");
14
+ const tag_1 = require("../helpers/tag");
14
15
  exports.searchTranscriptsCommand = new commander_1.Command('search')
15
16
  .description('Search meeting transcripts.')
16
17
  .argument('<search>', 'Search term')
17
- .option('--tags <ids>', constants_1.TAGS_OPTION_DESCRIPTION)
18
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
18
19
  .option('--profiles <ids>', constants_1.PROFILES_OPTION_DESCRIPTION)
19
20
  .option('--domains <domains>', constants_1.DOMAINS_OPTION_DESCRIPTION)
20
21
  .showHelpAfterError(true)
@@ -25,8 +26,9 @@ exports.searchTranscriptsCommand = new commander_1.Command('search')
25
26
  intent: query,
26
27
  searchTerm: query,
27
28
  };
28
- if (options.tags)
29
- args['tags'] = (0, parse_1.parseNumericIds)(options.tags, 'tag ID');
29
+ if (options.tags) {
30
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
31
+ }
30
32
  if (options.profiles)
31
33
  args['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
32
34
  if (options.domains)
package/dist/constants.js CHANGED
@@ -42,7 +42,7 @@ exports.UNASSIGNED_ACTION_ITEM_ASSIGNEE_LABEL = 'Unassigned';
42
42
  exports.PAGE_OPTION_DESCRIPTION = 'Page index (starts at 0)';
43
43
  exports.START_DATE_OPTION_DESCRIPTION = 'Start date (YYYY-MM-DD)';
44
44
  exports.END_DATE_OPTION_DESCRIPTION = 'End date (YYYY-MM-DD)';
45
- exports.TAGS_OPTION_DESCRIPTION = 'Comma-separated tag IDs';
45
+ exports.TAGS_OPTION_DESCRIPTION = 'Comma-separated tag names or IDs';
46
46
  exports.PROFILES_OPTION_DESCRIPTION = 'Comma-separated profile IDs';
47
47
  exports.DOMAINS_OPTION_DESCRIPTION = 'Comma-separated domains';
48
48
  exports.LAST_AND_FROM_CONFLICT_ERROR = 'Cannot use --last and --from together.';
@@ -2,14 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.formatOutput = void 0;
4
4
  const table_1 = require("./table");
5
- const safeParse = (rawText) => {
6
- try {
7
- return JSON.parse(rawText);
8
- }
9
- catch {
10
- return rawText;
11
- }
12
- };
5
+ const parse_1 = require("./parse");
6
+ const zod_1 = require("zod");
13
7
  const stringify = (value) => typeof value === 'string' ? value : JSON.stringify(value, null, 2);
14
8
  const formatForTool = (toolName, data) => {
15
9
  if (!Array.isArray(data))
@@ -35,12 +29,14 @@ const formatForTool = (toolName, data) => {
35
29
  return (0, table_1.formatEmails)(data);
36
30
  case 'SearchActionItems':
37
31
  return (0, table_1.formatActionItems)(data);
32
+ case 'ListTags':
33
+ return (0, table_1.formatTags)(data);
38
34
  default:
39
35
  return;
40
36
  }
41
37
  };
42
38
  const formatOutput = (toolName, rawText, jsonMode) => {
43
- const parsed = safeParse(rawText);
39
+ const parsed = (0, parse_1.extractAndValidateObjectFromString)(rawText, zod_1.z.json());
44
40
  if (jsonMode) {
45
41
  console.log(stringify(parsed));
46
42
  return;
@@ -3,32 +3,49 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.validateNumericIds = exports.parseNumericIds = exports.parseIntOption = void 0;
6
+ exports.validateNumericIds = exports.parseNumericIds = exports.parseIntOption = exports.extractAndValidateObjectFromString = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
+ const zod_1 = require("zod");
9
+ const extractAndValidateObjectFromString = (rawText, schema) => {
10
+ try {
11
+ const json = JSON.parse(rawText);
12
+ const result = schema.safeParse(json);
13
+ if (result.success)
14
+ return result.data;
15
+ console.error(chalk_1.default.red('Failed to parse response.'));
16
+ process.exit(1);
17
+ }
18
+ catch {
19
+ return rawText;
20
+ }
21
+ };
22
+ exports.extractAndValidateObjectFromString = extractAndValidateObjectFromString;
23
+ const intSchema = zod_1.z.coerce.number().int();
24
+ const numericIdsSchema = zod_1.z.array(intSchema);
8
25
  const parseIntOption = (value, flagName) => {
9
- const parsed = parseInt(value, 10);
10
- if (isNaN(parsed)) {
26
+ const result = intSchema.safeParse(value);
27
+ if (!result.success) {
11
28
  console.error(chalk_1.default.red(`Invalid number for ${flagName}.`));
12
29
  process.exit(1);
13
30
  }
14
- return parsed;
31
+ return result.data;
15
32
  };
16
33
  exports.parseIntOption = parseIntOption;
17
34
  const parseNumericIds = (value, label) => {
18
- const ids = value.split(',').map(Number);
19
- if (ids.some(isNaN)) {
35
+ const result = numericIdsSchema.safeParse(value.split(','));
36
+ if (!result.success) {
20
37
  console.error(chalk_1.default.red(`Invalid ${label}. Expected numeric IDs.`));
21
38
  process.exit(1);
22
39
  }
23
- return ids;
40
+ return result.data;
24
41
  };
25
42
  exports.parseNumericIds = parseNumericIds;
26
43
  const validateNumericIds = (values, label) => {
27
- const ids = values.map(Number);
28
- if (ids.some(isNaN)) {
44
+ const result = numericIdsSchema.safeParse(values);
45
+ if (!result.success) {
29
46
  console.error(chalk_1.default.red(`Invalid ${label}. Expected numeric IDs.`));
30
47
  process.exit(1);
31
48
  }
32
- return ids;
49
+ return result.data;
33
50
  };
34
51
  exports.validateNumericIds = validateNumericIds;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.formatEmails = exports.formatActionItems = exports.formatSupportArticles = exports.formatDomains = exports.formatProfiles = exports.formatCalendarEvents = exports.formatTranscriptReadResults = exports.formatTranscriptSearchResults = exports.formatMeetingDetails = exports.formatMeetingsList = void 0;
6
+ exports.formatEmails = exports.formatTags = exports.formatActionItems = exports.formatSupportArticles = exports.formatDomains = exports.formatProfiles = exports.formatCalendarEvents = exports.formatTranscriptReadResults = exports.formatTranscriptSearchResults = exports.formatMeetingDetails = exports.formatMeetingsList = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const cli_table3_1 = __importDefault(require("cli-table3"));
9
9
  const date_1 = require("./date");
@@ -240,6 +240,21 @@ const formatActionItems = (actionItems) => {
240
240
  return `${chalk_1.default.bold(`${(0, string_1.pluralize)(actionItems.length, 'action item', 'action items')} found`)}\n${table.toString()}`;
241
241
  };
242
242
  exports.formatActionItems = formatActionItems;
243
+ const formatTags = (tags) => {
244
+ if (tags.length === 0)
245
+ return chalk_1.default.yellow('No tags found.');
246
+ const idWidth = idColumnWidth(tags.map((tag) => tag.id));
247
+ const nameWidth = 40;
248
+ const table = new cli_table3_1.default({
249
+ head: [style_1.brand.bold('Name'), style_1.brand.bold('ID')],
250
+ colWidths: [nameWidth, idWidth],
251
+ wordWrap: true,
252
+ style: style_1.tableStyle,
253
+ });
254
+ table.push(...tags.map((tag) => [(0, string_1.truncate)(tag.name, nameWidth - 2), tag.id]));
255
+ return `${chalk_1.default.bold(`${(0, string_1.pluralize)(tags.length, 'tag', 'tags')} found`)}\n${table.toString()}`;
256
+ };
257
+ exports.formatTags = formatTags;
243
258
  const formatMessage = (message) => {
244
259
  const header = chalk_1.default.bold.cyan(message.subject ?? 'No subject');
245
260
  const meta = `${chalk_1.default.bold('From:')} ${formatSender(message.sender)} ${chalk_1.default.dim((0, date_1.formatDateTime)(message.receivedOn))}`;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveTagValues = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const zod_1 = require("zod");
9
+ const jsonRpc_1 = require("../client/jsonRpc");
10
+ const parse_1 = require("./parse");
11
+ const tagItemSchema = zod_1.z.object({
12
+ id: zod_1.z.number(),
13
+ name: zod_1.z.string(),
14
+ });
15
+ const tagsSchema = zod_1.z.array(tagItemSchema);
16
+ const fetchUserTags = async () => {
17
+ const rawResult = await (0, jsonRpc_1.callTool)('ListTags', {
18
+ intent: 'Resolving tag values.',
19
+ });
20
+ return (0, parse_1.extractAndValidateObjectFromString)(rawResult, tagsSchema);
21
+ };
22
+ const resolveTagValues = async (value) => {
23
+ const parts = value
24
+ .split(',')
25
+ .map((part) => part.trim())
26
+ .filter((part) => part.length > 0);
27
+ if (parts.length === 0) {
28
+ console.error(chalk_1.default.red('No tag values provided.'));
29
+ process.exit(1);
30
+ }
31
+ const tagList = await fetchUserTags();
32
+ if (typeof tagList === 'string') {
33
+ console.error(chalk_1.default.red('Failed to fetch tags.'));
34
+ process.exit(1);
35
+ }
36
+ return parts.map((part) => {
37
+ const nameMatch = tagList.find((tag) => tag.name.toLowerCase() === part.toLowerCase());
38
+ if (nameMatch)
39
+ return nameMatch.id;
40
+ const numericId = Number(part);
41
+ if (!isNaN(numericId) && tagList.some((tag) => tag.id === numericId)) {
42
+ return numericId;
43
+ }
44
+ console.error(chalk_1.default.red(`Tag "${part}" not found.`));
45
+ process.exit(1);
46
+ });
47
+ };
48
+ exports.resolveTagValues = resolveTagValues;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circleback/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Circleback CLI. Search and access meetings, emails, calendar events, and more.",
5
5
  "license": "MIT",
6
6
  "author": "Circleback <support@circleback.ai> (https://circleback.ai)",
@@ -38,7 +38,8 @@
38
38
  "chalk": "^4.1.2",
39
39
  "cli-table3": "^0.6.5",
40
40
  "commander": "^13.1.0",
41
- "lodash": "^4.17.23"
41
+ "lodash": "^4.17.23",
42
+ "zod": "^4.0.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/lodash": "^4.17.24",