@circleback/cli 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -24
- package/dist/commands/meetings.js +56 -1
- package/dist/commands/registry.js +15 -4
- package/dist/commands/tags.js +53 -1
- package/dist/helpers/formatter.js +36 -0
- package/dist/types.js +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Circleback CLI
|
|
2
2
|
|
|
3
|
-
Search and access your meetings, transcripts, emails, calendar events, and more from the terminal, and manage your action items.
|
|
3
|
+
Search and access your meetings, transcripts, emails, calendar events, and more from the terminal, and manage your action items, tags, and meeting access.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -22,8 +22,8 @@ cb meetings
|
|
|
22
22
|
# Search by keyword
|
|
23
23
|
cb meetings "product review"
|
|
24
24
|
|
|
25
|
-
# Read by ID (from the meeting URL, e.g. circleback.ai/meetings/
|
|
26
|
-
cb meetings read
|
|
25
|
+
# Read by ID (from the meeting URL, e.g. circleback.ai/meetings/abc123)
|
|
26
|
+
cb meetings read abc123
|
|
27
27
|
|
|
28
28
|
# Search transcripts
|
|
29
29
|
cb transcripts "pricing discussion"
|
|
@@ -40,26 +40,32 @@ cb meetings --json
|
|
|
40
40
|
|
|
41
41
|
## Commands
|
|
42
42
|
|
|
43
|
-
| Command
|
|
44
|
-
|
|
|
45
|
-
| `cb auth login`
|
|
46
|
-
| `cb auth login --api-key`
|
|
47
|
-
| `cb auth logout`
|
|
48
|
-
| `cb update`
|
|
49
|
-
| `cb meetings [search]`
|
|
50
|
-
| `cb meetings read <ids...>`
|
|
51
|
-
| `cb
|
|
52
|
-
| `cb transcripts
|
|
53
|
-
| `cb
|
|
54
|
-
| `cb
|
|
55
|
-
| `cb
|
|
56
|
-
| `cb
|
|
57
|
-
| `cb
|
|
58
|
-
| `cb
|
|
59
|
-
| `cb action-items
|
|
60
|
-
| `cb action-items
|
|
61
|
-
| `cb action-items
|
|
62
|
-
| `cb
|
|
43
|
+
| Command | Description |
|
|
44
|
+
| -------------------------------------- | --------------------------------------------------------------- |
|
|
45
|
+
| `cb auth login` | Log in to Circleback with your browser |
|
|
46
|
+
| `cb auth login --api-key` | Log in with an API key |
|
|
47
|
+
| `cb auth logout` | Sign out on this device |
|
|
48
|
+
| `cb update` | Update CLI to the latest version |
|
|
49
|
+
| `cb meetings [search]` | Search meetings |
|
|
50
|
+
| `cb meetings read <ids...>` | Read detailed meeting info, notes, and action items (max 50) |
|
|
51
|
+
| `cb meetings share <id>` | Share a meeting or remove access |
|
|
52
|
+
| `cb transcripts <search>` | Search transcript content |
|
|
53
|
+
| `cb transcripts read <ids...>` | Read full transcripts (max 50) |
|
|
54
|
+
| `cb calendar` | Search calendar events |
|
|
55
|
+
| `cb people <names...>` | Search people by name |
|
|
56
|
+
| `cb companies <terms...>` | Search companies by name or domain |
|
|
57
|
+
| `cb emails [search]` | Search connected email accounts |
|
|
58
|
+
| `cb support [search]` | Search Circleback support articles |
|
|
59
|
+
| `cb action-items [search]` | Search action items |
|
|
60
|
+
| `cb action-items create <title>` | Create an action item |
|
|
61
|
+
| `cb action-items update <id>` | Update an action item's title, description, status, or assignee |
|
|
62
|
+
| `cb action-items delete <id>` | Delete an action item |
|
|
63
|
+
| `cb tags` | List tags |
|
|
64
|
+
| `cb tags create <name>` | Create a tag |
|
|
65
|
+
| `cb tags update <id>` | Update a tag's name, description, or color |
|
|
66
|
+
| `cb tags delete <id>` | Delete a tag |
|
|
67
|
+
| `cb tags apply <id> <meetingIds...>` | Add a tag to meetings |
|
|
68
|
+
| `cb tags unapply <id> <meetingIds...>` | Remove a tag from meetings |
|
|
63
69
|
|
|
64
70
|
Run `cb --help` or `cb <command> --help` for full usage details.
|
|
65
71
|
|
|
@@ -110,7 +116,7 @@ For stateless automation, set `CIRCLEBACK_API_KEY` instead of logging in:
|
|
|
110
116
|
CIRCLEBACK_API_KEY=cb_your_api_key cb meetings --json
|
|
111
117
|
```
|
|
112
118
|
|
|
113
|
-
|
|
119
|
+
Changing action items, tags, or meeting access needs write access. Browser logins from before v0.5.0 don't include it, so run `cb auth login` again; read-only API keys can't make changes.
|
|
114
120
|
|
|
115
121
|
`CIRCLEBACK_API_KEY` takes precedence over stored credentials. Unset it before running `cb auth login`; `cb auth logout` cannot clear an environment variable from your shell.
|
|
116
122
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.readMeetingsCommand = exports.searchMeetingsCommand = void 0;
|
|
3
|
+
exports.shareMeetingCommand = exports.readMeetingsCommand = exports.searchMeetingsCommand = void 0;
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
6
|
const command_1 = require("../helpers/command");
|
|
@@ -43,3 +43,58 @@ exports.readMeetingsCommand = (0, command_1.defineToolCommand)(new commander_1.C
|
|
|
43
43
|
meetingIds,
|
|
44
44
|
};
|
|
45
45
|
});
|
|
46
|
+
const ACCESS_LEVELS = [...Object.values(types_1.ShareableMeetingAccess), 'none'];
|
|
47
|
+
const getAccess = (access) => access === 'none' ? null : access;
|
|
48
|
+
exports.shareMeetingCommand = (0, command_1.defineToolCommand)(new commander_1.Command('share')
|
|
49
|
+
.description('Share a meeting, or remove access with --access none.')
|
|
50
|
+
.argument('<id>', 'Meeting ID')
|
|
51
|
+
.option('--email <emails>', 'Share with email addresses (comma-separated)')
|
|
52
|
+
.option('--profile <ids>', 'Share with people (comma-separated)')
|
|
53
|
+
.option('--workspace <ids>', 'Share with workspaces (comma-separated)')
|
|
54
|
+
.option('--team <ids>', 'Share with teams (comma-separated)')
|
|
55
|
+
.addOption(new commander_1.Option('--access <access>', 'Set the access level, or none to remove access (required with --email or --profile)').choices(ACCESS_LEVELS))
|
|
56
|
+
.addOption(new commander_1.Option('--link <access>', 'Set the meeting link access, or none to turn it off').choices(ACCESS_LEVELS))
|
|
57
|
+
.option('--send-email', 'Email the people the meeting is shared with'), types_1.ToolName.ShareMeeting, (meetingId, options) => {
|
|
58
|
+
const targets = [
|
|
59
|
+
options.email,
|
|
60
|
+
options.profile,
|
|
61
|
+
options.team,
|
|
62
|
+
options.workspace,
|
|
63
|
+
options.link,
|
|
64
|
+
];
|
|
65
|
+
if (targets.every((target) => target === undefined)) {
|
|
66
|
+
throw new Error('Set at least one of --email, --profile, --team, --workspace, or --link.');
|
|
67
|
+
}
|
|
68
|
+
if ((options.email || options.profile) && !options.access) {
|
|
69
|
+
throw new Error('--access is required with --email or --profile.');
|
|
70
|
+
}
|
|
71
|
+
const access = getAccess(options.access);
|
|
72
|
+
const sendEmail = options.sendEmail;
|
|
73
|
+
const parseIds = (value, label) => value ? (0, parse_1.parseNumericIds)(value, label) : [];
|
|
74
|
+
return {
|
|
75
|
+
meetingId,
|
|
76
|
+
shares: [
|
|
77
|
+
...(options.email?.split(',') ?? []).map((email) => ({
|
|
78
|
+
email: email.trim(),
|
|
79
|
+
access,
|
|
80
|
+
sendEmail,
|
|
81
|
+
})),
|
|
82
|
+
...parseIds(options.profile, 'profile ID').map((profileId) => ({
|
|
83
|
+
profileId,
|
|
84
|
+
access,
|
|
85
|
+
sendEmail,
|
|
86
|
+
})),
|
|
87
|
+
...parseIds(options.team, 'team ID').map((teamId) => ({
|
|
88
|
+
teamId,
|
|
89
|
+
access,
|
|
90
|
+
sendEmail,
|
|
91
|
+
})),
|
|
92
|
+
...parseIds(options.workspace, 'workspace ID').map((workspaceId) => ({
|
|
93
|
+
workspaceId,
|
|
94
|
+
access,
|
|
95
|
+
sendEmail,
|
|
96
|
+
})),
|
|
97
|
+
...(options.link ? [{ linkAccess: getAccess(options.link) }] : []),
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
});
|
|
@@ -17,8 +17,12 @@ const standaloneCommands = [auth_1.authCommand, update_1.updateCommand];
|
|
|
17
17
|
const commandGroups = [
|
|
18
18
|
{
|
|
19
19
|
name: 'meetings',
|
|
20
|
-
description: 'Find
|
|
21
|
-
subcommands: [
|
|
20
|
+
description: 'Find, read, and share meetings.',
|
|
21
|
+
subcommands: [
|
|
22
|
+
meetings_1.searchMeetingsCommand,
|
|
23
|
+
meetings_1.readMeetingsCommand,
|
|
24
|
+
meetings_1.shareMeetingCommand,
|
|
25
|
+
],
|
|
22
26
|
},
|
|
23
27
|
{
|
|
24
28
|
name: 'transcripts',
|
|
@@ -62,8 +66,15 @@ const commandGroups = [
|
|
|
62
66
|
},
|
|
63
67
|
{
|
|
64
68
|
name: 'tags',
|
|
65
|
-
description: 'List tags.',
|
|
66
|
-
subcommands: [
|
|
69
|
+
description: 'List and manage tags.',
|
|
70
|
+
subcommands: [
|
|
71
|
+
tags_1.listTagsCommand,
|
|
72
|
+
tags_1.createTagCommand,
|
|
73
|
+
tags_1.updateTagCommand,
|
|
74
|
+
tags_1.deleteTagCommand,
|
|
75
|
+
tags_1.applyTagCommand,
|
|
76
|
+
tags_1.unapplyTagCommand,
|
|
77
|
+
],
|
|
67
78
|
},
|
|
68
79
|
];
|
|
69
80
|
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));
|
package/dist/commands/tags.js
CHANGED
|
@@ -1,7 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.listTagsCommand = void 0;
|
|
3
|
+
exports.unapplyTagCommand = exports.applyTagCommand = exports.deleteTagCommand = exports.updateTagCommand = exports.createTagCommand = exports.listTagsCommand = void 0;
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const command_1 = require("../helpers/command");
|
|
6
|
+
const parse_1 = require("../helpers/parse");
|
|
6
7
|
const types_1 = require("../types");
|
|
8
|
+
const createColorOption = () => new commander_1.Option('--color <color>', 'Set the display color').choices([
|
|
9
|
+
'neutral',
|
|
10
|
+
'red',
|
|
11
|
+
'rose',
|
|
12
|
+
'orange',
|
|
13
|
+
'amber',
|
|
14
|
+
'emerald',
|
|
15
|
+
'sky',
|
|
16
|
+
'blue',
|
|
17
|
+
'indigo',
|
|
18
|
+
'purple',
|
|
19
|
+
]);
|
|
20
|
+
const getTagColor = (color) => color ? `bg-tag-${color}` : undefined;
|
|
21
|
+
const getTagAssignment = (identifier, meetingIds) => ({
|
|
22
|
+
tagId: (0, parse_1.parseIntOption)(identifier, 'id'),
|
|
23
|
+
meetingIds,
|
|
24
|
+
});
|
|
7
25
|
exports.listTagsCommand = (0, command_1.defineToolCommand)(new commander_1.Command('list').description('List all tags.'), types_1.ToolName.ListTags, () => ({ intent: 'Listing all tags.' }));
|
|
26
|
+
exports.createTagCommand = (0, command_1.defineToolCommand)(new commander_1.Command('create')
|
|
27
|
+
.description('Create a tag.')
|
|
28
|
+
.argument('<name>', 'Tag name')
|
|
29
|
+
.option('--description <description>', 'Set the description')
|
|
30
|
+
.addOption(createColorOption()), types_1.ToolName.CreateTag, (name, options) => ({
|
|
31
|
+
name,
|
|
32
|
+
description: options.description,
|
|
33
|
+
color: getTagColor(options.color),
|
|
34
|
+
}));
|
|
35
|
+
exports.updateTagCommand = (0, command_1.defineToolCommand)(new commander_1.Command('update')
|
|
36
|
+
.description('Update a tag.')
|
|
37
|
+
.argument('<id>', 'Tag ID')
|
|
38
|
+
.option('--name <name>', 'Set the name')
|
|
39
|
+
.option('--description <description>', 'Set the description')
|
|
40
|
+
.addOption(createColorOption()), types_1.ToolName.UpdateTag, (identifier, options) => {
|
|
41
|
+
if (!Object.values(options).some((value) => value !== undefined)) {
|
|
42
|
+
throw new Error('Provide at least one field to update.');
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
tagId: (0, parse_1.parseIntOption)(identifier, 'id'),
|
|
46
|
+
name: options.name,
|
|
47
|
+
description: options.description,
|
|
48
|
+
color: getTagColor(options.color),
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
exports.deleteTagCommand = (0, command_1.defineToolCommand)(new commander_1.Command('delete').description('Delete a tag.').argument('<id>', 'Tag ID'), types_1.ToolName.DeleteTag, (identifier) => ({ tagId: (0, parse_1.parseIntOption)(identifier, 'id') }));
|
|
52
|
+
exports.applyTagCommand = (0, command_1.defineToolCommand)(new commander_1.Command('apply')
|
|
53
|
+
.description('Add a tag to meetings.')
|
|
54
|
+
.argument('<id>', 'Tag ID')
|
|
55
|
+
.argument('<meetingIds...>', 'Meeting IDs'), types_1.ToolName.AddTagToMeetings, getTagAssignment);
|
|
56
|
+
exports.unapplyTagCommand = (0, command_1.defineToolCommand)(new commander_1.Command('unapply')
|
|
57
|
+
.description('Remove a tag from meetings.')
|
|
58
|
+
.argument('<id>', 'Tag ID')
|
|
59
|
+
.argument('<meetingIds...>', 'Meeting IDs'), types_1.ToolName.RemoveTagFromMeetings, getTagAssignment);
|
|
@@ -19,6 +19,31 @@ const formatActionItemChange = (verb, data) => {
|
|
|
19
19
|
const { id, title, status } = result.data;
|
|
20
20
|
return `${verb} action item ${id}: ${title} (${status})`;
|
|
21
21
|
};
|
|
22
|
+
const TagChangeSchema = zod_1.z.object({ id: zod_1.z.number(), name: zod_1.z.string() });
|
|
23
|
+
const formatTagChange = (verb, data) => {
|
|
24
|
+
const result = TagChangeSchema.safeParse(data);
|
|
25
|
+
if (!result.success)
|
|
26
|
+
return;
|
|
27
|
+
const { id, name } = result.data;
|
|
28
|
+
return `${verb} tag ${id}: ${name}`;
|
|
29
|
+
};
|
|
30
|
+
const MeetingShareChangeSchema = zod_1.z.object({
|
|
31
|
+
id: zod_1.z.string(),
|
|
32
|
+
name: zod_1.z.string().nullable(),
|
|
33
|
+
errors: zod_1.z
|
|
34
|
+
.array(zod_1.z.object({ index: zod_1.z.number(), error: zod_1.z.string() }))
|
|
35
|
+
.optional(),
|
|
36
|
+
});
|
|
37
|
+
const formatMeetingShareChange = (data) => {
|
|
38
|
+
const result = MeetingShareChangeSchema.safeParse(data);
|
|
39
|
+
if (!result.success)
|
|
40
|
+
return;
|
|
41
|
+
const { id, name, errors = [] } = result.data;
|
|
42
|
+
return [
|
|
43
|
+
`Updated sharing for meeting ${id}${name ? `: ${name}` : ''}`,
|
|
44
|
+
...errors.map(({ index, error }) => `Could not share target ${index + 1}: ${error}`),
|
|
45
|
+
].join('\n');
|
|
46
|
+
};
|
|
22
47
|
const formatForTool = (toolName, data) => {
|
|
23
48
|
switch (toolName) {
|
|
24
49
|
case types_1.ToolName.CreateActionItem:
|
|
@@ -27,6 +52,14 @@ const formatForTool = (toolName, data) => {
|
|
|
27
52
|
return formatActionItemChange('Updated', data);
|
|
28
53
|
case types_1.ToolName.DeleteActionItem:
|
|
29
54
|
return formatActionItemChange('Deleted', data);
|
|
55
|
+
case types_1.ToolName.CreateTag:
|
|
56
|
+
return formatTagChange('Created', data);
|
|
57
|
+
case types_1.ToolName.UpdateTag:
|
|
58
|
+
return formatTagChange('Updated', data);
|
|
59
|
+
case types_1.ToolName.DeleteTag:
|
|
60
|
+
return formatTagChange('Deleted', data);
|
|
61
|
+
case types_1.ToolName.ShareMeeting:
|
|
62
|
+
return formatMeetingShareChange(data);
|
|
30
63
|
}
|
|
31
64
|
if (!Array.isArray(data))
|
|
32
65
|
return;
|
|
@@ -53,6 +86,9 @@ const formatForTool = (toolName, data) => {
|
|
|
53
86
|
return (0, table_1.formatActionItems)(data);
|
|
54
87
|
case types_1.ToolName.ListTags:
|
|
55
88
|
return (0, table_1.formatTags)(data);
|
|
89
|
+
case types_1.ToolName.AddTagToMeetings:
|
|
90
|
+
case types_1.ToolName.RemoveTagFromMeetings:
|
|
91
|
+
return;
|
|
56
92
|
default: {
|
|
57
93
|
const _absurd = toolName;
|
|
58
94
|
return _absurd;
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isJsonRpcResponse = exports.jsonRpcResultSchema = exports.isOAuthTokenResponse = exports.isStoredApiKey = exports.parseStoredCredentials = exports.ActionItemStatus = exports.ToolName = exports.CredentialSource = exports.CredentialType = void 0;
|
|
3
|
+
exports.isJsonRpcResponse = exports.jsonRpcResultSchema = exports.isOAuthTokenResponse = exports.isStoredApiKey = exports.parseStoredCredentials = exports.ShareableMeetingAccess = exports.ActionItemStatus = exports.ToolName = exports.CredentialSource = exports.CredentialType = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
var CredentialType;
|
|
6
6
|
(function (CredentialType) {
|
|
@@ -28,12 +28,24 @@ var ToolName;
|
|
|
28
28
|
ToolName["CreateActionItem"] = "CreateActionItem";
|
|
29
29
|
ToolName["UpdateActionItem"] = "UpdateActionItem";
|
|
30
30
|
ToolName["DeleteActionItem"] = "DeleteActionItem";
|
|
31
|
+
ToolName["CreateTag"] = "CreateTag";
|
|
32
|
+
ToolName["UpdateTag"] = "UpdateTag";
|
|
33
|
+
ToolName["DeleteTag"] = "DeleteTag";
|
|
34
|
+
ToolName["AddTagToMeetings"] = "AddTagToMeetings";
|
|
35
|
+
ToolName["RemoveTagFromMeetings"] = "RemoveTagFromMeetings";
|
|
36
|
+
ToolName["ShareMeeting"] = "ShareMeeting";
|
|
31
37
|
})(ToolName || (exports.ToolName = ToolName = {}));
|
|
32
38
|
var ActionItemStatus;
|
|
33
39
|
(function (ActionItemStatus) {
|
|
34
40
|
ActionItemStatus["Pending"] = "PENDING";
|
|
35
41
|
ActionItemStatus["Done"] = "DONE";
|
|
36
42
|
})(ActionItemStatus || (exports.ActionItemStatus = ActionItemStatus = {}));
|
|
43
|
+
var ShareableMeetingAccess;
|
|
44
|
+
(function (ShareableMeetingAccess) {
|
|
45
|
+
ShareableMeetingAccess["Editor"] = "Editor";
|
|
46
|
+
ShareableMeetingAccess["Viewer"] = "Viewer";
|
|
47
|
+
ShareableMeetingAccess["LimitedViewer"] = "LimitedViewer";
|
|
48
|
+
})(ShareableMeetingAccess || (exports.ShareableMeetingAccess = ShareableMeetingAccess = {}));
|
|
37
49
|
const storedTokensSchema = zod_1.z.object({
|
|
38
50
|
accessToken: zod_1.z.string(),
|
|
39
51
|
refreshToken: zod_1.z.string(),
|
package/package.json
CHANGED