@circleback/cli 0.1.3 → 0.1.5

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.
@@ -0,0 +1,67 @@
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.searchActionItemsCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const jsonRpc_1 = require("../client/jsonRpc");
10
+ const constants_1 = require("../constants");
11
+ const date_1 = require("../helpers/date");
12
+ const error_1 = require("../helpers/error");
13
+ const formatter_1 = require("../helpers/formatter");
14
+ const parse_1 = require("../helpers/parse");
15
+ const tag_1 = require("../helpers/tag");
16
+ const DEFAULT_ACTION_ITEMS_SEARCH_LAST_DAYS = 30;
17
+ exports.searchActionItemsCommand = new commander_1.Command('search')
18
+ .description('Search action items.')
19
+ .argument('[search]', 'Search term')
20
+ .option('-p, --page <index>', constants_1.PAGE_OPTION_DESCRIPTION, '0')
21
+ .option('--status <status>', 'Filter by status (PENDING or DONE)')
22
+ .option('--last <days>', 'Show action items from the last N days')
23
+ .option('--from <date>', constants_1.START_DATE_OPTION_DESCRIPTION)
24
+ .option('--to <date>', constants_1.END_DATE_OPTION_DESCRIPTION)
25
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
26
+ .option('--assignee <id>', 'Filter by assignee profile ID')
27
+ .action(async (query, options) => {
28
+ try {
29
+ if (options.last && options.from) {
30
+ console.error(chalk_1.default.red(constants_1.LAST_AND_FROM_CONFLICT_ERROR));
31
+ process.exit(1);
32
+ }
33
+ const jsonMode = exports.searchActionItemsCommand.parent?.parent?.opts().json ?? false;
34
+ const pageIndex = (0, parse_1.parseIntOption)(options.page, '--page');
35
+ const args = {
36
+ intent: query ?? 'Listing recent action items.',
37
+ pageIndex,
38
+ };
39
+ if (query)
40
+ args['searchTerms'] = [query];
41
+ if (options.status)
42
+ args['status'] = options.status;
43
+ if (options.last) {
44
+ args['startDate'] = (0, date_1.getStartDateFromDaysAgo)((0, parse_1.parseIntOption)(options.last, '--last'));
45
+ }
46
+ else if (options.from) {
47
+ args['startDate'] = options.from;
48
+ }
49
+ else if (!query) {
50
+ args['startDate'] = (0, date_1.getStartDateFromDaysAgo)(DEFAULT_ACTION_ITEMS_SEARCH_LAST_DAYS);
51
+ }
52
+ if (options.to)
53
+ args['endDate'] = options.to;
54
+ if (options.tags) {
55
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
56
+ }
57
+ if (options.assignee)
58
+ args['assigneeProfileId'] = (0, parse_1.parseIntOption)(options.assignee, '--assignee');
59
+ const result = await (0, jsonRpc_1.callTool)('SearchActionItems', args);
60
+ (0, formatter_1.formatOutput)('SearchActionItems', result, jsonMode);
61
+ }
62
+ catch (error) {
63
+ const message = error instanceof Error ? error.message : constants_1.SEARCH_FAILED_ERROR;
64
+ console.error(chalk_1.default.red((0, error_1.formatMcpError)(message) ?? message));
65
+ process.exit(1);
66
+ }
67
+ });
@@ -7,6 +7,7 @@ exports.searchCalendarCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const jsonRpc_1 = require("../client/jsonRpc");
10
+ const constants_1 = require("../constants");
10
11
  const date_1 = require("../helpers/date");
11
12
  const error_1 = require("../helpers/error");
12
13
  const formatter_1 = require("../helpers/formatter");
@@ -14,28 +15,28 @@ const parse_1 = require("../helpers/parse");
14
15
  exports.searchCalendarCommand = new commander_1.Command('search')
15
16
  .description('Search calendar events.')
16
17
  .option('--last <days>', 'Show events from the last N days')
17
- .option('--from <date>', 'Start date (YYYY-MM-DD)')
18
- .option('--to <date>', 'End date (YYYY-MM-DD)')
18
+ .option('--from <date>', constants_1.START_DATE_OPTION_DESCRIPTION)
19
+ .option('--to <date>', constants_1.END_DATE_OPTION_DESCRIPTION)
19
20
  .action(async (options) => {
20
21
  try {
21
22
  if (options.last && options.from) {
22
- console.error(chalk_1.default.red('Cannot use --last and --from together.'));
23
+ console.error(chalk_1.default.red(constants_1.LAST_AND_FROM_CONFLICT_ERROR));
23
24
  process.exit(1);
24
25
  }
25
26
  const jsonMode = exports.searchCalendarCommand.parent?.parent?.opts().json ?? false;
26
- const arguments_ = {
27
+ const args = {
27
28
  intent: 'Listing calendar events.',
28
29
  pageIndex: 0,
29
30
  };
30
31
  if (options.last) {
31
- arguments_['startDate'] = (0, date_1.getStartDateFromDaysAgo)((0, parse_1.parseIntOption)(options.last, '--last'));
32
+ args['startDate'] = (0, date_1.getStartDateFromDaysAgo)((0, parse_1.parseIntOption)(options.last, '--last'));
32
33
  }
33
34
  else if (options.from) {
34
- arguments_['startDate'] = options.from;
35
+ args['startDate'] = options.from;
35
36
  }
36
37
  if (options.to)
37
- arguments_['endDate'] = options.to;
38
- const result = await (0, jsonRpc_1.callTool)('SearchCalendarEvents', arguments_);
38
+ args['endDate'] = options.to;
39
+ const result = await (0, jsonRpc_1.callTool)('SearchCalendarEvents', args);
39
40
  (0, formatter_1.formatOutput)('SearchCalendarEvents', result, jsonMode);
40
41
  }
41
42
  catch (error) {
@@ -7,13 +7,14 @@ exports.searchEmailsCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const jsonRpc_1 = require("../client/jsonRpc");
10
+ const constants_1 = require("../constants");
10
11
  const error_1 = require("../helpers/error");
11
12
  const formatter_1 = require("../helpers/formatter");
12
13
  const parse_1 = require("../helpers/parse");
13
14
  exports.searchEmailsCommand = new commander_1.Command('search')
14
15
  .description('Search connected email accounts. Supports filters: from:email, to:email, participant:email, before:YYYY-MM-DD, after:YYYY-MM-DD.')
15
16
  .argument('[search]', 'Search term')
16
- .option('-p, --page <index>', 'Page index (starts at 0)', '0')
17
+ .option('-p, --page <index>', constants_1.PAGE_OPTION_DESCRIPTION, '0')
17
18
  .action(async (query, options) => {
18
19
  try {
19
20
  if (query !== undefined && query.trim() === '') {
@@ -22,12 +23,12 @@ exports.searchEmailsCommand = new commander_1.Command('search')
22
23
  }
23
24
  const jsonMode = exports.searchEmailsCommand.parent?.parent?.opts().json ?? false;
24
25
  const pageIndex = (0, parse_1.parseIntOption)(options.page, '--page');
25
- const arguments_ = {
26
+ const args = {
26
27
  intent: query ?? 'Listing recent emails.',
27
28
  pageIndex,
28
29
  };
29
- arguments_['searchTerm'] = query ?? '';
30
- const result = await (0, jsonRpc_1.callTool)('SearchEmails', arguments_);
30
+ args['searchTerm'] = query ?? '';
31
+ const result = await (0, jsonRpc_1.callTool)('SearchEmails', args);
31
32
  (0, formatter_1.formatOutput)('SearchEmails', result, jsonMode);
32
33
  }
33
34
  catch (error) {
@@ -7,63 +7,66 @@ exports.readMeetingsCommand = exports.searchMeetingsCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const jsonRpc_1 = require("../client/jsonRpc");
10
+ const constants_1 = require("../constants");
10
11
  const date_1 = require("../helpers/date");
11
12
  const error_1 = require("../helpers/error");
12
13
  const formatter_1 = require("../helpers/formatter");
13
14
  const parse_1 = require("../helpers/parse");
15
+ const tag_1 = require("../helpers/tag");
14
16
  const DEFAULT_MEETINGS_SEARCH_LAST_DAYS = 7;
15
17
  exports.searchMeetingsCommand = new commander_1.Command('search')
16
- .description('Search for meetings.')
18
+ .description('Search meetings.')
17
19
  .argument('[search]', 'Search term')
18
- .option('-p, --page <index>', 'Page index (starts at 0)', '0')
20
+ .option('-p, --page <index>', constants_1.PAGE_OPTION_DESCRIPTION, '0')
19
21
  .option('--last <days>', 'Show meetings from the last N days')
20
- .option('--from <date>', 'Start date (YYYY-MM-DD)')
21
- .option('--to <date>', 'End date (YYYY-MM-DD)')
22
- .option('--tags <ids>', 'Comma-separated tag IDs')
23
- .option('--profiles <ids>', 'Comma-separated profile IDs')
24
- .option('--domains <domains>', 'Comma-separated domains')
22
+ .option('--from <date>', constants_1.START_DATE_OPTION_DESCRIPTION)
23
+ .option('--to <date>', constants_1.END_DATE_OPTION_DESCRIPTION)
24
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
25
+ .option('--profiles <ids>', constants_1.PROFILES_OPTION_DESCRIPTION)
26
+ .option('--domains <domains>', constants_1.DOMAINS_OPTION_DESCRIPTION)
25
27
  .action(async (query, options) => {
26
28
  try {
27
29
  if (options.last && options.from) {
28
- console.error(chalk_1.default.red('Cannot use --last and --from together.'));
30
+ console.error(chalk_1.default.red(constants_1.LAST_AND_FROM_CONFLICT_ERROR));
29
31
  process.exit(1);
30
32
  }
31
33
  const jsonMode = exports.searchMeetingsCommand.parent?.parent?.opts().json ?? false;
32
34
  const pageIndex = (0, parse_1.parseIntOption)(options.page, '--page');
33
- const arguments_ = {
35
+ const args = {
34
36
  intent: query ?? 'Listing recent meetings.',
35
37
  pageIndex,
36
38
  };
37
39
  if (query)
38
- arguments_['searchTerm'] = query;
40
+ args['searchTerm'] = query;
39
41
  if (options.last) {
40
- arguments_['startDate'] = (0, date_1.getStartDateFromDaysAgo)((0, parse_1.parseIntOption)(options.last, '--last'));
42
+ args['startDate'] = (0, date_1.getStartDateFromDaysAgo)((0, parse_1.parseIntOption)(options.last, '--last'));
41
43
  }
42
44
  else if (options.from) {
43
- arguments_['startDate'] = options.from;
45
+ args['startDate'] = options.from;
44
46
  }
45
47
  else if (!query) {
46
- arguments_['startDate'] = (0, date_1.getStartDateFromDaysAgo)(DEFAULT_MEETINGS_SEARCH_LAST_DAYS);
48
+ args['startDate'] = (0, date_1.getStartDateFromDaysAgo)(DEFAULT_MEETINGS_SEARCH_LAST_DAYS);
47
49
  }
48
50
  if (options.to)
49
- arguments_['endDate'] = options.to;
50
- if (options.tags)
51
- arguments_['tags'] = (0, parse_1.parseNumericIds)(options.tags, 'tag ID');
51
+ args['endDate'] = options.to;
52
+ if (options.tags) {
53
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
54
+ }
52
55
  if (options.profiles)
53
- arguments_['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
56
+ args['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
54
57
  if (options.domains)
55
- arguments_['domains'] = options.domains.split(',');
56
- const result = await (0, jsonRpc_1.callTool)('SearchMeetings', arguments_);
58
+ args['domains'] = options.domains.split(',');
59
+ const result = await (0, jsonRpc_1.callTool)('SearchMeetings', args);
57
60
  (0, formatter_1.formatOutput)('SearchMeetings', result, jsonMode);
58
61
  }
59
62
  catch (error) {
60
- const message = error instanceof Error ? error.message : 'Search failed.';
63
+ const message = error instanceof Error ? error.message : constants_1.SEARCH_FAILED_ERROR;
61
64
  console.error(chalk_1.default.red((0, error_1.formatMcpError)(message) ?? message));
62
65
  process.exit(1);
63
66
  }
64
67
  });
65
68
  exports.readMeetingsCommand = new commander_1.Command('read')
66
- .description('Get detailed information for meetings.')
69
+ .description('Get detailed meeting information.')
67
70
  .argument('<ids...>', 'Meeting IDs')
68
71
  .action(async (ids) => {
69
72
  try {
@@ -76,7 +79,7 @@ exports.readMeetingsCommand = new commander_1.Command('read')
76
79
  (0, formatter_1.formatOutput)('ReadMeetings', result, jsonMode);
77
80
  }
78
81
  catch (error) {
79
- const message = error instanceof Error ? error.message : 'Read failed.';
82
+ const message = error instanceof Error ? error.message : constants_1.READ_FAILED_ERROR;
80
83
  console.error(chalk_1.default.red((0, error_1.formatMcpError)(message) ?? message));
81
84
  process.exit(1);
82
85
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAllCommands = exports.commandGroups = exports.standaloneCommands = void 0;
4
4
  const commander_1 = require("commander");
5
+ const actionItems_1 = require("./actionItems");
5
6
  const auth_1 = require("./auth");
6
7
  const calendar_1 = require("./calendar");
7
8
  const domains_1 = require("./domains");
@@ -9,6 +10,7 @@ const emails_1 = require("./emails");
9
10
  const meetings_1 = require("./meetings");
10
11
  const profiles_1 = require("./profiles");
11
12
  const support_1 = require("./support");
13
+ const tags_1 = require("./tags");
12
14
  const transcripts_1 = require("./transcripts");
13
15
  const upgrade_1 = require("./upgrade");
14
16
  exports.standaloneCommands = [
@@ -52,6 +54,16 @@ exports.commandGroups = [
52
54
  description: 'Search emails.',
53
55
  subcommands: [emails_1.searchEmailsCommand],
54
56
  },
57
+ {
58
+ name: 'action-items',
59
+ description: 'Search action items.',
60
+ subcommands: [actionItems_1.searchActionItemsCommand],
61
+ },
62
+ {
63
+ name: 'tags',
64
+ description: 'List tags.',
65
+ subcommands: [tags_1.listTagsCommand],
66
+ },
55
67
  ];
56
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));
57
69
  const getAllCommands = () => [
@@ -15,11 +15,11 @@ exports.searchSupportCommand = new commander_1.Command('search')
15
15
  .action(async (query) => {
16
16
  try {
17
17
  const jsonMode = exports.searchSupportCommand.parent?.parent?.opts().json ?? false;
18
- const arguments_ = {
18
+ const args = {
19
19
  intent: query ?? 'Listing support articles.',
20
20
  };
21
- arguments_['searchTerm'] = query ?? '';
22
- const result = await (0, jsonRpc_1.callTool)('SearchSupportArticles', arguments_);
21
+ args['searchTerm'] = query ?? '';
22
+ const result = await (0, jsonRpc_1.callTool)('SearchSupportArticles', args);
23
23
  (0, formatter_1.formatOutput)('SearchSupportArticles', result, jsonMode);
24
24
  }
25
25
  catch (error) {
@@ -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
+ });
@@ -7,30 +7,33 @@ exports.getTranscriptsCommand = exports.searchTranscriptsCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const jsonRpc_1 = require("../client/jsonRpc");
10
+ const constants_1 = require("../constants");
10
11
  const error_1 = require("../helpers/error");
11
12
  const formatter_1 = require("../helpers/formatter");
12
13
  const parse_1 = require("../helpers/parse");
14
+ const tag_1 = require("../helpers/tag");
13
15
  exports.searchTranscriptsCommand = new commander_1.Command('search')
14
16
  .description('Search meeting transcripts.')
15
17
  .argument('<search>', 'Search term')
16
- .option('--tags <ids>', 'Comma-separated tag IDs')
17
- .option('--profiles <ids>', 'Comma-separated profile IDs')
18
- .option('--domains <domains>', 'Comma-separated domains')
18
+ .option('--tags <tags>', constants_1.TAGS_OPTION_DESCRIPTION)
19
+ .option('--profiles <ids>', constants_1.PROFILES_OPTION_DESCRIPTION)
20
+ .option('--domains <domains>', constants_1.DOMAINS_OPTION_DESCRIPTION)
19
21
  .showHelpAfterError(true)
20
22
  .action(async (query, options) => {
21
23
  try {
22
24
  const jsonMode = exports.searchTranscriptsCommand.parent?.parent?.opts().json ?? false;
23
- const arguments_ = {
25
+ const args = {
24
26
  intent: query,
25
27
  searchTerm: query,
26
28
  };
27
- if (options.tags)
28
- arguments_['tags'] = (0, parse_1.parseNumericIds)(options.tags, 'tag ID');
29
+ if (options.tags) {
30
+ args['tags'] = await (0, tag_1.resolveTagValues)(options.tags);
31
+ }
29
32
  if (options.profiles)
30
- arguments_['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
33
+ args['profiles'] = (0, parse_1.parseNumericIds)(options.profiles, 'profile ID');
31
34
  if (options.domains)
32
- arguments_['domains'] = options.domains.split(',');
33
- const result = await (0, jsonRpc_1.callTool)('SearchTranscripts', arguments_);
35
+ args['domains'] = options.domains.split(',');
36
+ const result = await (0, jsonRpc_1.callTool)('SearchTranscripts', args);
34
37
  (0, formatter_1.formatOutput)('SearchTranscripts', result, jsonMode);
35
38
  }
36
39
  catch (error) {
@@ -40,7 +43,7 @@ exports.searchTranscriptsCommand = new commander_1.Command('search')
40
43
  }
41
44
  });
42
45
  exports.getTranscriptsCommand = new commander_1.Command('read')
43
- .description('Get full transcripts for meetings.')
46
+ .description('Get full meeting transcripts.')
44
47
  .argument('<meetingId...>', 'Meeting IDs (max 50)')
45
48
  .showHelpAfterError(true)
46
49
  .action(async (ids) => {
package/dist/constants.js CHANGED
@@ -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.CALLBACK_TIMEOUT_MILLISECONDS = exports.OAUTH_SCOPE = exports.TOKENS_FILE = exports.CONFIG_DIRECTORY = exports.ASCII_LOGO = exports.SECONDARY_COLOR = exports.BRAND_COLOR = exports.CLIENT_VERSION = exports.CLIENT_PACKAGE_NAME = exports.CLIENT_NAME = exports.BASE_URL = void 0;
6
+ exports.READ_FAILED_ERROR = exports.SEARCH_FAILED_ERROR = exports.LAST_AND_FROM_CONFLICT_ERROR = exports.DOMAINS_OPTION_DESCRIPTION = exports.PROFILES_OPTION_DESCRIPTION = exports.TAGS_OPTION_DESCRIPTION = exports.END_DATE_OPTION_DESCRIPTION = exports.START_DATE_OPTION_DESCRIPTION = exports.PAGE_OPTION_DESCRIPTION = exports.UNASSIGNED_ACTION_ITEM_ASSIGNEE_LABEL = exports.DEFAULT_MEETING_NAME = exports.CALLBACK_TIMEOUT_MILLISECONDS = exports.OAUTH_SCOPE = exports.TOKENS_FILE = exports.CONFIG_DIRECTORY = exports.ASCII_LOGO = exports.SECONDARY_COLOR = exports.BRAND_COLOR = exports.CLIENT_VERSION = exports.CLIENT_PACKAGE_NAME = exports.CLIENT_NAME = exports.BASE_URL = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_os_1 = __importDefault(require("node:os"));
@@ -37,3 +37,14 @@ exports.CONFIG_DIRECTORY = node_path_1.default.join(node_os_1.default.homedir(),
37
37
  exports.TOKENS_FILE = node_path_1.default.join(exports.CONFIG_DIRECTORY, 'tokens.json');
38
38
  exports.OAUTH_SCOPE = 'user';
39
39
  exports.CALLBACK_TIMEOUT_MILLISECONDS = 120_000;
40
+ exports.DEFAULT_MEETING_NAME = 'New meeting';
41
+ exports.UNASSIGNED_ACTION_ITEM_ASSIGNEE_LABEL = 'Unassigned';
42
+ exports.PAGE_OPTION_DESCRIPTION = 'Page index (starts at 0)';
43
+ exports.START_DATE_OPTION_DESCRIPTION = 'Start date (YYYY-MM-DD)';
44
+ exports.END_DATE_OPTION_DESCRIPTION = 'End date (YYYY-MM-DD)';
45
+ exports.TAGS_OPTION_DESCRIPTION = 'Comma-separated tag names or IDs';
46
+ exports.PROFILES_OPTION_DESCRIPTION = 'Comma-separated profile IDs';
47
+ exports.DOMAINS_OPTION_DESCRIPTION = 'Comma-separated domains';
48
+ exports.LAST_AND_FROM_CONFLICT_ERROR = 'Cannot use --last and --from together.';
49
+ exports.SEARCH_FAILED_ERROR = 'Search failed.';
50
+ exports.READ_FAILED_ERROR = 'Read failed.';
@@ -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))
@@ -33,12 +27,16 @@ const formatForTool = (toolName, data) => {
33
27
  return (0, table_1.formatSupportArticles)(data);
34
28
  case 'SearchEmails':
35
29
  return (0, table_1.formatEmails)(data);
30
+ case 'SearchActionItems':
31
+ return (0, table_1.formatActionItems)(data);
32
+ case 'ListTags':
33
+ return (0, table_1.formatTags)(data);
36
34
  default:
37
35
  return;
38
36
  }
39
37
  };
40
38
  const formatOutput = (toolName, rawText, jsonMode) => {
41
- const parsed = safeParse(rawText);
39
+ const parsed = (0, parse_1.extractAndValidateObjectFromString)(rawText, zod_1.z.json());
42
40
  if (jsonMode) {
43
41
  console.log(stringify(parsed));
44
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,13 +3,14 @@ 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.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");
10
10
  const string_1 = require("./string");
11
11
  const style_1 = require("./style");
12
12
  const lodash_1 = require("lodash");
13
+ const constants_1 = require("../constants");
13
14
  const idColumnWidth = (ids) => {
14
15
  const maxLength = ids.reduce((max, id) => Math.max(max, String(id).length), 2);
15
16
  return maxLength + 2;
@@ -53,14 +54,12 @@ const formatMeetingsList = (meetings) => {
53
54
  wordWrap: true,
54
55
  style: style_1.tableStyle,
55
56
  });
56
- meetings.forEach((meeting) => {
57
- table.push([
58
- (0, string_1.truncate)(meeting.name, nameWidth - 2),
59
- meeting.id,
60
- (0, date_1.formatDate)(meeting.createdAt),
61
- meeting.attendees.map(formatAttendee).join('\n'),
62
- ]);
63
- });
57
+ table.push(...meetings.map((meeting) => [
58
+ (0, string_1.truncate)(meeting.name, nameWidth - 2),
59
+ meeting.id,
60
+ (0, date_1.formatDate)(meeting.createdAt),
61
+ meeting.attendees.map(formatAttendee).join('\n'),
62
+ ]));
64
63
  return `${chalk_1.default.bold(`${(0, string_1.pluralize)(meetings.length, 'meeting', 'meetings')} found`)}\n${table.toString()}`;
65
64
  };
66
65
  exports.formatMeetingsList = formatMeetingsList;
@@ -106,13 +105,11 @@ const formatTranscriptSearchResults = (results) => {
106
105
  wordWrap: true,
107
106
  style: style_1.tableStyle,
108
107
  });
109
- results.forEach((result) => {
110
- table.push([
111
- (0, string_1.truncate)(result.meetingName || 'New meeting', meetingWidth - 2),
112
- result.meetingId,
113
- (0, string_1.truncate)(result.text, contentWidth - 2),
114
- ]);
115
- });
108
+ table.push(...results.map((result) => [
109
+ (0, string_1.truncate)(result.meetingName || constants_1.DEFAULT_MEETING_NAME, meetingWidth - 2),
110
+ result.meetingId,
111
+ (0, string_1.truncate)(result.text, contentWidth - 2),
112
+ ]));
116
113
  return `${chalk_1.default.bold(`${(0, string_1.pluralize)(results.length, 'match', 'matches')} found`)}\n${table.toString()}`;
117
114
  };
118
115
  exports.formatTranscriptSearchResults = formatTranscriptSearchResults;
@@ -149,15 +146,13 @@ const formatCalendarEvents = (events) => {
149
146
  wordWrap: true,
150
147
  style: style_1.tableStyle,
151
148
  });
152
- events.forEach((event) => {
153
- table.push([
154
- (0, string_1.truncate)(event.title, 28),
155
- (0, date_1.formatDateTime)(event.startTime),
156
- (0, date_1.formatDateTime)(event.endTime),
157
- event.platform ?? '-',
158
- event.attendees?.map(formatAttendee).join('\n') ?? '-',
159
- ]);
160
- });
149
+ table.push(...events.map((event) => [
150
+ (0, string_1.truncate)(event.title, 28),
151
+ (0, date_1.formatDateTime)(event.startTime),
152
+ (0, date_1.formatDateTime)(event.endTime),
153
+ event.platform ?? '-',
154
+ event.attendees?.map(formatAttendee).join('\n') ?? '-',
155
+ ]));
161
156
  return `${chalk_1.default.bold((0, string_1.pluralize)(events.length, 'event', 'events'))}\n${table.toString()}`;
162
157
  };
163
158
  exports.formatCalendarEvents = formatCalendarEvents;
@@ -181,15 +176,13 @@ const formatProfiles = (profiles) => {
181
176
  wordWrap: true,
182
177
  style: style_1.tableStyle,
183
178
  });
184
- profiles.forEach((profile) => {
185
- table.push([
186
- [profile.firstName, profile.lastName].filter(Boolean).join(' ') || '-',
187
- profile.id,
188
- profile.email ?? '-',
189
- profile.title ?? '-',
190
- profile.company ?? '-',
191
- ]);
192
- });
179
+ table.push(...profiles.map((profile) => [
180
+ [profile.firstName, profile.lastName].filter(Boolean).join(' ') || '-',
181
+ profile.id,
182
+ profile.email ?? '-',
183
+ profile.title ?? '-',
184
+ profile.company ?? '-',
185
+ ]));
193
186
  return `${chalk_1.default.bold(`${(0, string_1.pluralize)(profiles.length, 'person', 'people')} found`)}\n${table.toString()}`;
194
187
  };
195
188
  exports.formatProfiles = formatProfiles;
@@ -207,6 +200,61 @@ const formatSupportArticles = (articles) => {
207
200
  .join('\n\n');
208
201
  };
209
202
  exports.formatSupportArticles = formatSupportArticles;
203
+ const formatActionItems = (actionItems) => {
204
+ if (actionItems.length === 0)
205
+ return chalk_1.default.yellow('No action items found.');
206
+ const idWidth = idColumnWidth(actionItems.map((item) => item.id));
207
+ const titleWidth = 35;
208
+ const statusWidth = 10;
209
+ const assigneeWidth = 20;
210
+ const meetingWidth = 25;
211
+ const dateWidth = 14;
212
+ const table = new cli_table3_1.default({
213
+ head: [
214
+ style_1.brand.bold('Title'),
215
+ style_1.brand.bold('ID'),
216
+ style_1.brand.bold('Status'),
217
+ style_1.brand.bold('Assignee'),
218
+ style_1.brand.bold('Meeting'),
219
+ style_1.brand.bold('Date'),
220
+ ],
221
+ colWidths: [
222
+ titleWidth,
223
+ idWidth,
224
+ statusWidth,
225
+ assigneeWidth,
226
+ meetingWidth,
227
+ dateWidth,
228
+ ],
229
+ wordWrap: true,
230
+ style: style_1.tableStyle,
231
+ });
232
+ table.push(...actionItems.map((item) => [
233
+ (0, string_1.truncate)(item.title, titleWidth - 2),
234
+ item.id,
235
+ item.status,
236
+ item.assignee?.name ?? constants_1.UNASSIGNED_ACTION_ITEM_ASSIGNEE_LABEL,
237
+ (0, string_1.truncate)(item.meeting.name || constants_1.DEFAULT_MEETING_NAME, meetingWidth - 2),
238
+ (0, date_1.formatDate)(item.createdAt),
239
+ ]));
240
+ return `${chalk_1.default.bold(`${(0, string_1.pluralize)(actionItems.length, 'action item', 'action items')} found`)}\n${table.toString()}`;
241
+ };
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;
210
258
  const formatMessage = (message) => {
211
259
  const header = chalk_1.default.bold.cyan(message.subject ?? 'No subject');
212
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.3",
3
+ "version": "0.1.5",
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": "^3.25.76"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/lodash": "^4.17.24",