@circleback/cli 0.2.2 → 0.3.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 +17 -5
- package/dist/auth/apiKey.js +77 -0
- package/dist/auth/credentials.js +56 -0
- package/dist/auth/oauth.js +9 -20
- package/dist/auth/tokenStorage.js +34 -15
- package/dist/client/jsonRpc.js +16 -14
- package/dist/commands/actionItems.js +3 -6
- package/dist/commands/auth.js +50 -19
- package/dist/commands/calendar.js +3 -6
- package/dist/commands/companies.js +2 -5
- package/dist/commands/emails.js +3 -6
- package/dist/commands/meetings.js +4 -7
- package/dist/commands/profiles.js +2 -5
- package/dist/commands/registry.js +1 -5
- package/dist/commands/support.js +2 -5
- package/dist/commands/tags.js +2 -5
- package/dist/commands/transcripts.js +3 -6
- package/dist/commands/update.js +8 -8
- package/dist/constants.js +5 -1
- package/dist/helpers/formatter.js +5 -2
- package/dist/helpers/output.js +34 -0
- package/dist/helpers/parse.js +5 -8
- package/dist/helpers/table.js +11 -11
- package/dist/helpers/tag.js +4 -7
- package/dist/helpers/update.js +4 -5
- package/dist/index.js +12 -6
- package/dist/types.js +34 -14
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Requires Node.js 18 or later. The package installs two binaries: `circleback` an
|
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
# Authenticate via browser
|
|
17
|
-
cb login
|
|
17
|
+
cb auth login
|
|
18
18
|
|
|
19
19
|
# Search recent meetings
|
|
20
20
|
cb meetings
|
|
@@ -39,8 +39,9 @@ cb meetings --json
|
|
|
39
39
|
|
|
40
40
|
| Command | Description |
|
|
41
41
|
| ------------------------------ | ------------------------------------------------------------ |
|
|
42
|
-
| `cb login`
|
|
43
|
-
| `cb
|
|
42
|
+
| `cb auth login` | Login with Circleback via browser |
|
|
43
|
+
| `cb auth login --api-key` | Authenticate with a Public API key |
|
|
44
|
+
| `cb auth logout` | Clear stored login credentials |
|
|
44
45
|
| `cb update` | Update CLI to the latest version |
|
|
45
46
|
| `cb meetings [search]` | Search meetings |
|
|
46
47
|
| `cb meetings read <ids...>` | Read detailed meeting info, notes, and action items (max 50) |
|
|
@@ -88,10 +89,21 @@ cb meetings "standup" --json | jq '.[].name'
|
|
|
88
89
|
## Authentication
|
|
89
90
|
|
|
90
91
|
```bash
|
|
91
|
-
cb login
|
|
92
|
-
cb
|
|
92
|
+
cb auth login # Opens the browser for OAuth
|
|
93
|
+
cb auth login --api-key # Prompts securely for a Public API key
|
|
94
|
+
cb auth logout # Clears stored credentials
|
|
93
95
|
```
|
|
94
96
|
|
|
97
|
+
API-key login links to [Circleback API key settings](https://circleback.ai/settings?tab=api-access), verifies the key, and stores it locally on your device.
|
|
98
|
+
|
|
99
|
+
For stateless automation, set `CIRCLEBACK_API_KEY` instead of logging in:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
CIRCLEBACK_API_KEY=cb_your_api_key cb meetings --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`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.
|
|
106
|
+
|
|
95
107
|
## Agents
|
|
96
108
|
|
|
97
109
|
The CLI is designed to work well with AI agents and tool-use systems:
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateApiKey = exports.promptForApiKey = void 0;
|
|
4
|
+
const node_readline_1 = require("node:readline");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const promptForApiKey = async () => {
|
|
7
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
8
|
+
throw new Error(`API key login requires an interactive terminal. Set ${constants_1.API_KEY_ENVIRONMENT_VARIABLE} for automation.`);
|
|
9
|
+
}
|
|
10
|
+
process.stdout.write('API key: ');
|
|
11
|
+
(0, node_readline_1.emitKeypressEvents)(process.stdin);
|
|
12
|
+
process.stdin.setRawMode(true);
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
const characters = [];
|
|
15
|
+
const finish = (result) => {
|
|
16
|
+
process.stdin.off('keypress', handleKeypress);
|
|
17
|
+
process.stdin.setRawMode(false);
|
|
18
|
+
process.stdin.pause();
|
|
19
|
+
process.stdout.write('\n');
|
|
20
|
+
if (result instanceof Error)
|
|
21
|
+
reject(result);
|
|
22
|
+
else
|
|
23
|
+
resolve(result);
|
|
24
|
+
};
|
|
25
|
+
const handleKeypress = (input, key) => {
|
|
26
|
+
if (key.ctrl && key.name === 'c') {
|
|
27
|
+
finish(new Error('API key login canceled.'));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
31
|
+
const apiKey = characters.join('').trim();
|
|
32
|
+
finish(apiKey || new Error('API key is required.'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (key.name === 'backspace' ||
|
|
36
|
+
key.name === 'delete' ||
|
|
37
|
+
input === '\b' ||
|
|
38
|
+
input === '\x7f') {
|
|
39
|
+
if (characters.pop())
|
|
40
|
+
process.stdout.write('\b \b');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!input || key.ctrl || key.meta || /[\u0000-\u001f\u007f]/.test(input))
|
|
44
|
+
return;
|
|
45
|
+
characters.push(...input);
|
|
46
|
+
process.stdout.write('*'.repeat([...input].length));
|
|
47
|
+
};
|
|
48
|
+
process.stdin.on('keypress', handleKeypress);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
exports.promptForApiKey = promptForApiKey;
|
|
52
|
+
const validateApiKey = async (apiKey) => {
|
|
53
|
+
if (!apiKey.startsWith(constants_1.API_KEY_PREFIX)) {
|
|
54
|
+
throw new Error('The provided API key is invalid or has been revoked.');
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(`${constants_1.BASE_URL}/api/meetings?page=0`, {
|
|
58
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
59
|
+
});
|
|
60
|
+
if (response.ok)
|
|
61
|
+
return;
|
|
62
|
+
if (response.status === 401) {
|
|
63
|
+
throw new Error('The provided API key is invalid or has been revoked.');
|
|
64
|
+
}
|
|
65
|
+
if (response.status === 403) {
|
|
66
|
+
throw new Error('The provided API key does not have read access.');
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`API key verification failed with status ${response.status}.`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error instanceof TypeError && error.message.includes('fetch failed')) {
|
|
72
|
+
throw new Error('Unable to verify the API key. Check your internet connection and try again.');
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
exports.validateApiKey = validateApiKey;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCredentialSnapshot = exports.getEnvironmentApiKey = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const types_1 = require("../types");
|
|
6
|
+
const oauth_1 = require("./oauth");
|
|
7
|
+
const tokenStorage_1 = require("./tokenStorage");
|
|
8
|
+
const getEnvironmentApiKey = () => {
|
|
9
|
+
const apiKey = process.env[constants_1.API_KEY_ENVIRONMENT_VARIABLE]?.trim();
|
|
10
|
+
return apiKey || undefined;
|
|
11
|
+
};
|
|
12
|
+
exports.getEnvironmentApiKey = getEnvironmentApiKey;
|
|
13
|
+
const requireCredentials = () => {
|
|
14
|
+
const environmentApiKey = (0, exports.getEnvironmentApiKey)();
|
|
15
|
+
if (environmentApiKey) {
|
|
16
|
+
if (!environmentApiKey.startsWith(constants_1.API_KEY_PREFIX)) {
|
|
17
|
+
throw new Error(`${constants_1.API_KEY_ENVIRONMENT_VARIABLE} must start with ${constants_1.API_KEY_PREFIX}.`);
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
type: types_1.CredentialType.ApiKey,
|
|
21
|
+
apiKey: environmentApiKey,
|
|
22
|
+
source: types_1.CredentialSource.Environment,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const storedCredentials = (0, tokenStorage_1.loadCredentials)();
|
|
26
|
+
if (!storedCredentials) {
|
|
27
|
+
throw new Error(`Not authenticated. Run \`circleback auth login\` or set ${constants_1.API_KEY_ENVIRONMENT_VARIABLE}.`);
|
|
28
|
+
}
|
|
29
|
+
if ((0, types_1.isStoredApiKey)(storedCredentials)) {
|
|
30
|
+
return {
|
|
31
|
+
...storedCredentials,
|
|
32
|
+
source: types_1.CredentialSource.Stored,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { type: types_1.CredentialType.OAuth, tokens: storedCredentials };
|
|
36
|
+
};
|
|
37
|
+
const getCredentialSnapshot = async () => {
|
|
38
|
+
const credentials = requireCredentials();
|
|
39
|
+
if (credentials.type === types_1.CredentialType.OAuth) {
|
|
40
|
+
const tokens = await (0, oauth_1.getValidOAuthTokens)(credentials.tokens);
|
|
41
|
+
return {
|
|
42
|
+
bearerCredential: tokens.accessToken,
|
|
43
|
+
refresh: () => (0, oauth_1.forceRefreshOAuthToken)(tokens),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const source = credentials.source === types_1.CredentialSource.Environment
|
|
47
|
+
? constants_1.API_KEY_ENVIRONMENT_VARIABLE
|
|
48
|
+
: 'The stored API key';
|
|
49
|
+
return {
|
|
50
|
+
bearerCredential: credentials.apiKey,
|
|
51
|
+
refresh: () => {
|
|
52
|
+
throw new Error(`${source} is invalid or has been revoked.`);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
exports.getCredentialSnapshot = getCredentialSnapshot;
|
package/dist/auth/oauth.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.
|
|
6
|
+
exports.forceRefreshOAuthToken = exports.getValidOAuthTokens = exports.login = void 0;
|
|
7
7
|
const node_child_process_1 = require("node:child_process");
|
|
8
8
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
9
9
|
const constants_1 = require("../constants");
|
|
@@ -125,7 +125,7 @@ const login = async (options = {}) => {
|
|
|
125
125
|
codeVerifier: verifier,
|
|
126
126
|
});
|
|
127
127
|
const tokens = (0, tokenStorage_1.buildStoredTokens)(tokenResponse, clientId);
|
|
128
|
-
(0, tokenStorage_1.
|
|
128
|
+
(0, tokenStorage_1.saveCredentials)(tokens);
|
|
129
129
|
return tokens;
|
|
130
130
|
}
|
|
131
131
|
catch (error) {
|
|
@@ -134,30 +134,19 @@ const login = async (options = {}) => {
|
|
|
134
134
|
}
|
|
135
135
|
};
|
|
136
136
|
exports.login = login;
|
|
137
|
-
const requireTokens = () => {
|
|
138
|
-
const tokens = (0, tokenStorage_1.loadTokens)();
|
|
139
|
-
if (!tokens) {
|
|
140
|
-
throw new Error('Not authenticated. Run `circleback login` to authenticate.');
|
|
141
|
-
}
|
|
142
|
-
return tokens;
|
|
143
|
-
};
|
|
144
137
|
const refreshAndSave = async (tokens) => {
|
|
145
138
|
const refreshed = await refreshAccessToken(tokens.refreshToken, tokens.clientId);
|
|
146
139
|
const updatedTokens = (0, tokenStorage_1.buildStoredTokens)(refreshed, tokens.clientId);
|
|
147
|
-
(0, tokenStorage_1.
|
|
148
|
-
return updatedTokens
|
|
140
|
+
(0, tokenStorage_1.saveCredentials)(updatedTokens);
|
|
141
|
+
return updatedTokens;
|
|
149
142
|
};
|
|
150
|
-
const
|
|
151
|
-
const tokens = requireTokens();
|
|
143
|
+
const getValidOAuthTokens = async (tokens) => {
|
|
152
144
|
const bufferSeconds = 60;
|
|
153
145
|
const isExpired = Math.floor(Date.now() / 1000) >= tokens.expiresAt - bufferSeconds;
|
|
154
146
|
if (!isExpired)
|
|
155
|
-
return tokens
|
|
156
|
-
return refreshAndSave(tokens);
|
|
157
|
-
};
|
|
158
|
-
exports.getValidAccessToken = getValidAccessToken;
|
|
159
|
-
const forceRefreshToken = async () => {
|
|
160
|
-
const tokens = requireTokens();
|
|
147
|
+
return tokens;
|
|
161
148
|
return refreshAndSave(tokens);
|
|
162
149
|
};
|
|
163
|
-
exports.
|
|
150
|
+
exports.getValidOAuthTokens = getValidOAuthTokens;
|
|
151
|
+
const forceRefreshOAuthToken = async (tokens) => (await refreshAndSave(tokens)).accessToken;
|
|
152
|
+
exports.forceRefreshOAuthToken = forceRefreshOAuthToken;
|
|
@@ -3,12 +3,23 @@ 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.
|
|
6
|
+
exports.clearCredentials = exports.saveCredentials = exports.loadCredentials = exports.buildStoredTokens = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const constants_1 = require("../constants");
|
|
9
9
|
const types_1 = require("../types");
|
|
10
10
|
const DIRECTORY_PERMISSIONS_MODE = 0o700;
|
|
11
11
|
const FILE_PERMISSIONS_MODE = 0o600;
|
|
12
|
+
const isFileNotFoundError = (error) => error instanceof Error && 'code' in error && error.code === 'ENOENT';
|
|
13
|
+
const openCredentialsFile = () => {
|
|
14
|
+
try {
|
|
15
|
+
return node_fs_1.default.openSync(constants_1.TOKENS_FILE, 'r+');
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (!isFileNotFoundError(error))
|
|
19
|
+
throw error;
|
|
20
|
+
return node_fs_1.default.openSync(constants_1.TOKENS_FILE, 'wx+', FILE_PERMISSIONS_MODE);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
12
23
|
const buildStoredTokens = (response, clientId) => ({
|
|
13
24
|
accessToken: response.access_token,
|
|
14
25
|
refreshToken: response.refresh_token,
|
|
@@ -17,35 +28,43 @@ const buildStoredTokens = (response, clientId) => ({
|
|
|
17
28
|
scope: response.scope,
|
|
18
29
|
});
|
|
19
30
|
exports.buildStoredTokens = buildStoredTokens;
|
|
20
|
-
const
|
|
31
|
+
const loadCredentials = () => {
|
|
21
32
|
try {
|
|
22
33
|
const content = node_fs_1.default.readFileSync(constants_1.TOKENS_FILE, 'utf-8');
|
|
23
34
|
const parsed = JSON.parse(content);
|
|
24
|
-
|
|
25
|
-
return;
|
|
26
|
-
return parsed;
|
|
35
|
+
return (0, types_1.parseStoredCredentials)(parsed);
|
|
27
36
|
}
|
|
28
37
|
catch {
|
|
29
38
|
return;
|
|
30
39
|
}
|
|
31
40
|
};
|
|
32
|
-
exports.
|
|
33
|
-
const
|
|
41
|
+
exports.loadCredentials = loadCredentials;
|
|
42
|
+
const saveCredentials = (credentials) => {
|
|
34
43
|
node_fs_1.default.mkdirSync(constants_1.CONFIG_DIRECTORY, {
|
|
35
44
|
recursive: true,
|
|
36
45
|
mode: DIRECTORY_PERMISSIONS_MODE,
|
|
37
46
|
});
|
|
38
|
-
node_fs_1.default.
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
node_fs_1.default.chmodSync(constants_1.CONFIG_DIRECTORY, DIRECTORY_PERMISSIONS_MODE);
|
|
48
|
+
const fileDescriptor = openCredentialsFile();
|
|
49
|
+
try {
|
|
50
|
+
node_fs_1.default.fchmodSync(fileDescriptor, FILE_PERMISSIONS_MODE);
|
|
51
|
+
node_fs_1.default.ftruncateSync(fileDescriptor);
|
|
52
|
+
node_fs_1.default.writeFileSync(fileDescriptor, JSON.stringify(credentials, null, 2));
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
node_fs_1.default.closeSync(fileDescriptor);
|
|
56
|
+
}
|
|
41
57
|
};
|
|
42
|
-
exports.
|
|
43
|
-
const
|
|
58
|
+
exports.saveCredentials = saveCredentials;
|
|
59
|
+
const clearCredentials = () => {
|
|
44
60
|
try {
|
|
45
61
|
node_fs_1.default.unlinkSync(constants_1.TOKENS_FILE);
|
|
62
|
+
return true;
|
|
46
63
|
}
|
|
47
|
-
catch {
|
|
48
|
-
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (isFileNotFoundError(error))
|
|
66
|
+
return false;
|
|
67
|
+
throw error;
|
|
49
68
|
}
|
|
50
69
|
};
|
|
51
|
-
exports.
|
|
70
|
+
exports.clearCredentials = clearCredentials;
|
package/dist/client/jsonRpc.js
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.callTool = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
4
5
|
const constants_1 = require("../constants");
|
|
5
6
|
const types_1 = require("../types");
|
|
6
|
-
const
|
|
7
|
+
const credentials_1 = require("../auth/credentials");
|
|
7
8
|
const TOOLS_CALL_METHOD = 'tools/call';
|
|
9
|
+
const errorResponseSchema = zod_1.z.object({
|
|
10
|
+
error: zod_1.z.string().optional(),
|
|
11
|
+
message: zod_1.z.string().optional(),
|
|
12
|
+
});
|
|
8
13
|
let requestId = 0;
|
|
9
14
|
const nextId = () => ++requestId;
|
|
10
15
|
const extractErrorMessage = async (response) => {
|
|
11
16
|
const text = await response.text();
|
|
12
17
|
try {
|
|
13
18
|
const body = JSON.parse(text);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
? body.message
|
|
19
|
-
: undefined;
|
|
20
|
-
return error ?? message ?? text;
|
|
19
|
+
const result = errorResponseSchema.safeParse(body);
|
|
20
|
+
return result.success
|
|
21
|
+
? (result.data.error ?? result.data.message ?? text)
|
|
22
|
+
: text;
|
|
21
23
|
}
|
|
22
24
|
catch {
|
|
23
25
|
return text;
|
|
24
26
|
}
|
|
25
27
|
};
|
|
26
28
|
const HTTP_ERROR_MESSAGES = {
|
|
27
|
-
401: 'Authentication expired. Run `circleback login` to re-authenticate.',
|
|
29
|
+
401: 'Authentication expired. Run `circleback auth login` to re-authenticate.',
|
|
28
30
|
403: 'Permission denied.',
|
|
29
31
|
404: 'Resource not found.',
|
|
30
32
|
429: 'Rate limit exceeded. Please try again later.',
|
|
@@ -101,8 +103,8 @@ const sendRequestWithNetworkError = async (method, params, accessToken) => {
|
|
|
101
103
|
throw error;
|
|
102
104
|
}
|
|
103
105
|
};
|
|
104
|
-
const retryWithRefresh = async (method, params) => {
|
|
105
|
-
const accessToken = await (
|
|
106
|
+
const retryWithRefresh = async (method, params, refresh) => {
|
|
107
|
+
const accessToken = await refresh();
|
|
106
108
|
const response = await sendRequestWithNetworkError(method, params, accessToken);
|
|
107
109
|
if (!response.ok) {
|
|
108
110
|
const message = await extractErrorMessage(response);
|
|
@@ -111,11 +113,11 @@ const retryWithRefresh = async (method, params) => {
|
|
|
111
113
|
return parseResponse(response);
|
|
112
114
|
};
|
|
113
115
|
const callTool = async (toolName, toolArguments) => {
|
|
114
|
-
const
|
|
116
|
+
const credentialSnapshot = await (0, credentials_1.getCredentialSnapshot)();
|
|
115
117
|
const params = { name: toolName, arguments: toolArguments };
|
|
116
|
-
const response = await sendRequestWithNetworkError(TOOLS_CALL_METHOD, params,
|
|
118
|
+
const response = await sendRequestWithNetworkError(TOOLS_CALL_METHOD, params, credentialSnapshot.bearerCredential);
|
|
117
119
|
if (response.status === 401) {
|
|
118
|
-
return retryWithRefresh(TOOLS_CALL_METHOD, params);
|
|
120
|
+
return retryWithRefresh(TOOLS_CALL_METHOD, params, credentialSnapshot.refresh);
|
|
119
121
|
}
|
|
120
122
|
if (!response.ok) {
|
|
121
123
|
const fallback = HTTP_ERROR_MESSAGES[response.status];
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchActionItemsCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const constants_1 = require("../constants");
|
|
11
7
|
const date_1 = require("../helpers/date");
|
|
12
8
|
const error_1 = require("../helpers/error");
|
|
9
|
+
const output_1 = require("../helpers/output");
|
|
13
10
|
const formatter_1 = require("../helpers/formatter");
|
|
14
11
|
const parse_1 = require("../helpers/parse");
|
|
15
12
|
const tag_1 = require("../helpers/tag");
|
|
@@ -27,7 +24,7 @@ exports.searchActionItemsCommand = new commander_1.Command('search')
|
|
|
27
24
|
.action(async (query, options) => {
|
|
28
25
|
try {
|
|
29
26
|
if (options.last && options.from) {
|
|
30
|
-
|
|
27
|
+
(0, output_1.printText)(constants_1.LAST_AND_FROM_CONFLICT_ERROR, output_1.TextType.Error);
|
|
31
28
|
process.exit(1);
|
|
32
29
|
}
|
|
33
30
|
const jsonMode = exports.searchActionItemsCommand.parent?.parent?.opts().json ?? false;
|
|
@@ -61,7 +58,7 @@ exports.searchActionItemsCommand = new commander_1.Command('search')
|
|
|
61
58
|
}
|
|
62
59
|
catch (error) {
|
|
63
60
|
const message = error instanceof Error ? error.message : constants_1.SEARCH_FAILED_ERROR;
|
|
64
|
-
|
|
61
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
65
62
|
process.exit(1);
|
|
66
63
|
}
|
|
67
64
|
});
|
package/dist/commands/auth.js
CHANGED
|
@@ -3,11 +3,16 @@ 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.
|
|
6
|
+
exports.authCommand = void 0;
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const apiKey_1 = require("../auth/apiKey");
|
|
10
|
+
const credentials_1 = require("../auth/credentials");
|
|
9
11
|
const oauth_1 = require("../auth/oauth");
|
|
10
12
|
const tokenStorage_1 = require("../auth/tokenStorage");
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
|
+
const output_1 = require("../helpers/output");
|
|
15
|
+
const types_1 = require("../types");
|
|
11
16
|
const AUTHORIZATION_URL_FALLBACK_DELAY_MILLISECONDS = 500;
|
|
12
17
|
const getOpenUrlInstruction = () => process.platform === 'darwin' ? '⌘-click' : 'Ctrl-click';
|
|
13
18
|
const createAuthorizationUrlFallback = () => {
|
|
@@ -16,8 +21,8 @@ const createAuthorizationUrlFallback = () => {
|
|
|
16
21
|
const timeout = setTimeout(() => {
|
|
17
22
|
if (abortController.signal.aborted)
|
|
18
23
|
return;
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
(0, output_1.printText)(`Browser didn't open? ${getOpenUrlInstruction()} the URL below to log in.\n`, output_1.TextType.Default);
|
|
25
|
+
(0, output_1.printText)(chalk_1.default.cyan(url), output_1.TextType.Default);
|
|
21
26
|
}, AUTHORIZATION_URL_FALLBACK_DELAY_MILLISECONDS);
|
|
22
27
|
abortController.signal.addEventListener('abort', () => clearTimeout(timeout), { once: true });
|
|
23
28
|
};
|
|
@@ -26,16 +31,30 @@ const createAuthorizationUrlFallback = () => {
|
|
|
26
31
|
cleanup: () => abortController.abort(),
|
|
27
32
|
};
|
|
28
33
|
};
|
|
29
|
-
|
|
30
|
-
.description('Authenticate with Circleback
|
|
31
|
-
.
|
|
34
|
+
const loginCommand = new commander_1.Command('login')
|
|
35
|
+
.description('Authenticate with Circleback.')
|
|
36
|
+
.option('--api-key', 'Authenticate with a Public API key')
|
|
37
|
+
.action(async (options) => {
|
|
32
38
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.log(chalk_1.default.yellow('Already authenticated. Run `circleback logout` first to re-authenticate.'));
|
|
39
|
+
if ((0, credentials_1.getEnvironmentApiKey)()) {
|
|
40
|
+
(0, output_1.printText)(`${constants_1.API_KEY_ENVIRONMENT_VARIABLE} is active. Unset it before changing stored authentication.`, output_1.TextType.Warning);
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
38
|
-
|
|
43
|
+
if ((0, tokenStorage_1.loadCredentials)()) {
|
|
44
|
+
(0, output_1.printText)('Already authenticated. Run `circleback auth logout` first to re-authenticate.', output_1.TextType.Warning);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (options.apiKey) {
|
|
48
|
+
(0, output_1.printText)('Create an API key at:\n', output_1.TextType.Default);
|
|
49
|
+
(0, output_1.printText)(chalk_1.default.cyan(constants_1.API_KEY_SETTINGS_URL), output_1.TextType.Default);
|
|
50
|
+
(0, output_1.printText)('', output_1.TextType.Default);
|
|
51
|
+
const apiKey = await (0, apiKey_1.promptForApiKey)();
|
|
52
|
+
await (0, apiKey_1.validateApiKey)(apiKey);
|
|
53
|
+
(0, tokenStorage_1.saveCredentials)({ type: types_1.CredentialType.ApiKey, apiKey });
|
|
54
|
+
(0, output_1.printText)('API key authentication successful.', output_1.TextType.Success);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
(0, output_1.printText)('Opening your browser for authentication…\n', output_1.TextType.Default);
|
|
39
58
|
const authorizationUrlFallback = createAuthorizationUrlFallback();
|
|
40
59
|
try {
|
|
41
60
|
await (0, oauth_1.login)({
|
|
@@ -45,22 +64,34 @@ exports.loginCommand = new commander_1.Command('login')
|
|
|
45
64
|
finally {
|
|
46
65
|
authorizationUrlFallback.cleanup();
|
|
47
66
|
}
|
|
48
|
-
|
|
67
|
+
(0, output_1.printText)('Authentication successful.', output_1.TextType.Success);
|
|
49
68
|
}
|
|
50
69
|
catch (error) {
|
|
51
70
|
const message = error instanceof Error ? error.message : 'Authentication failed.';
|
|
52
|
-
|
|
71
|
+
(0, output_1.printText)(message, output_1.TextType.Error);
|
|
53
72
|
process.exit(1);
|
|
54
73
|
}
|
|
55
74
|
});
|
|
56
|
-
|
|
57
|
-
.description('Clear stored authentication
|
|
75
|
+
const logoutCommand = new commander_1.Command('logout')
|
|
76
|
+
.description('Clear stored authentication credentials.')
|
|
58
77
|
.action(() => {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
const environmentApiKey = (0, credentials_1.getEnvironmentApiKey)();
|
|
79
|
+
const didClearCredentials = (0, tokenStorage_1.clearCredentials)();
|
|
80
|
+
if (!didClearCredentials) {
|
|
81
|
+
if (environmentApiKey) {
|
|
82
|
+
(0, output_1.printText)(`No stored credentials to clear. ${constants_1.API_KEY_ENVIRONMENT_VARIABLE} is still active.`, output_1.TextType.Warning);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
(0, output_1.printText)('Not currently authenticated.', output_1.TextType.Warning);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (environmentApiKey) {
|
|
89
|
+
(0, output_1.printText)(`Stored credentials cleared. ${constants_1.API_KEY_ENVIRONMENT_VARIABLE} is still active.`, output_1.TextType.Warning);
|
|
62
90
|
return;
|
|
63
91
|
}
|
|
64
|
-
(0,
|
|
65
|
-
console.log(chalk_1.default.green('Logged out successfully.'));
|
|
92
|
+
(0, output_1.printText)('Logged out successfully.', output_1.TextType.Success);
|
|
66
93
|
});
|
|
94
|
+
exports.authCommand = new commander_1.Command('auth')
|
|
95
|
+
.description('Manage authentication.')
|
|
96
|
+
.addCommand(loginCommand)
|
|
97
|
+
.addCommand(logoutCommand);
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchCalendarCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const constants_1 = require("../constants");
|
|
11
7
|
const date_1 = require("../helpers/date");
|
|
12
8
|
const error_1 = require("../helpers/error");
|
|
9
|
+
const output_1 = require("../helpers/output");
|
|
13
10
|
const formatter_1 = require("../helpers/formatter");
|
|
14
11
|
const parse_1 = require("../helpers/parse");
|
|
15
12
|
exports.searchCalendarCommand = new commander_1.Command('search')
|
|
@@ -20,7 +17,7 @@ exports.searchCalendarCommand = new commander_1.Command('search')
|
|
|
20
17
|
.action(async (options) => {
|
|
21
18
|
try {
|
|
22
19
|
if (options.last && options.from) {
|
|
23
|
-
|
|
20
|
+
(0, output_1.printText)(constants_1.LAST_AND_FROM_CONFLICT_ERROR, output_1.TextType.Error);
|
|
24
21
|
process.exit(1);
|
|
25
22
|
}
|
|
26
23
|
const jsonMode = exports.searchCalendarCommand.parent?.parent?.opts().json ?? false;
|
|
@@ -41,7 +38,7 @@ exports.searchCalendarCommand = new commander_1.Command('search')
|
|
|
41
38
|
}
|
|
42
39
|
catch (error) {
|
|
43
40
|
const message = error instanceof Error ? error.message : 'Calendar search failed.';
|
|
44
|
-
|
|
41
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
45
42
|
process.exit(1);
|
|
46
43
|
}
|
|
47
44
|
});
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchCompaniesCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const error_1 = require("../helpers/error");
|
|
7
|
+
const output_1 = require("../helpers/output");
|
|
11
8
|
const formatter_1 = require("../helpers/formatter");
|
|
12
9
|
exports.searchCompaniesCommand = new commander_1.Command('search')
|
|
13
10
|
.description('Search companies.')
|
|
@@ -22,7 +19,7 @@ exports.searchCompaniesCommand = new commander_1.Command('search')
|
|
|
22
19
|
}
|
|
23
20
|
catch (error) {
|
|
24
21
|
const message = error instanceof Error ? error.message : 'Company search failed.';
|
|
25
|
-
|
|
22
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
26
23
|
process.exit(1);
|
|
27
24
|
}
|
|
28
25
|
});
|
package/dist/commands/emails.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchEmailsCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const constants_1 = require("../constants");
|
|
11
7
|
const error_1 = require("../helpers/error");
|
|
8
|
+
const output_1 = require("../helpers/output");
|
|
12
9
|
const formatter_1 = require("../helpers/formatter");
|
|
13
10
|
const parse_1 = require("../helpers/parse");
|
|
14
11
|
exports.searchEmailsCommand = new commander_1.Command('search')
|
|
@@ -18,7 +15,7 @@ exports.searchEmailsCommand = new commander_1.Command('search')
|
|
|
18
15
|
.action(async (query, options) => {
|
|
19
16
|
try {
|
|
20
17
|
if (query !== undefined && query.trim() === '') {
|
|
21
|
-
|
|
18
|
+
(0, output_1.printText)('Search term cannot be empty.', output_1.TextType.Error);
|
|
22
19
|
process.exit(1);
|
|
23
20
|
}
|
|
24
21
|
const jsonMode = exports.searchEmailsCommand.parent?.parent?.opts().json ?? false;
|
|
@@ -33,7 +30,7 @@ exports.searchEmailsCommand = new commander_1.Command('search')
|
|
|
33
30
|
}
|
|
34
31
|
catch (error) {
|
|
35
32
|
const message = error instanceof Error ? error.message : 'Email search failed.';
|
|
36
|
-
|
|
33
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
37
34
|
process.exit(1);
|
|
38
35
|
}
|
|
39
36
|
});
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.readMeetingsCommand = exports.searchMeetingsCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const constants_1 = require("../constants");
|
|
11
7
|
const date_1 = require("../helpers/date");
|
|
12
8
|
const error_1 = require("../helpers/error");
|
|
9
|
+
const output_1 = require("../helpers/output");
|
|
13
10
|
const formatter_1 = require("../helpers/formatter");
|
|
14
11
|
const parse_1 = require("../helpers/parse");
|
|
15
12
|
const tag_1 = require("../helpers/tag");
|
|
@@ -27,7 +24,7 @@ exports.searchMeetingsCommand = new commander_1.Command('search')
|
|
|
27
24
|
.action(async (query, options) => {
|
|
28
25
|
try {
|
|
29
26
|
if (options.last && options.from) {
|
|
30
|
-
|
|
27
|
+
(0, output_1.printText)(constants_1.LAST_AND_FROM_CONFLICT_ERROR, output_1.TextType.Error);
|
|
31
28
|
process.exit(1);
|
|
32
29
|
}
|
|
33
30
|
const jsonMode = exports.searchMeetingsCommand.parent?.parent?.opts().json ?? false;
|
|
@@ -61,7 +58,7 @@ exports.searchMeetingsCommand = new commander_1.Command('search')
|
|
|
61
58
|
}
|
|
62
59
|
catch (error) {
|
|
63
60
|
const message = error instanceof Error ? error.message : constants_1.SEARCH_FAILED_ERROR;
|
|
64
|
-
|
|
61
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
65
62
|
process.exit(1);
|
|
66
63
|
}
|
|
67
64
|
});
|
|
@@ -80,7 +77,7 @@ exports.readMeetingsCommand = new commander_1.Command('read')
|
|
|
80
77
|
}
|
|
81
78
|
catch (error) {
|
|
82
79
|
const message = error instanceof Error ? error.message : constants_1.READ_FAILED_ERROR;
|
|
83
|
-
|
|
80
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
84
81
|
process.exit(1);
|
|
85
82
|
}
|
|
86
83
|
});
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchProfilesCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const error_1 = require("../helpers/error");
|
|
7
|
+
const output_1 = require("../helpers/output");
|
|
11
8
|
const formatter_1 = require("../helpers/formatter");
|
|
12
9
|
exports.searchProfilesCommand = new commander_1.Command('search')
|
|
13
10
|
.description('Search people by name.')
|
|
@@ -22,7 +19,7 @@ exports.searchProfilesCommand = new commander_1.Command('search')
|
|
|
22
19
|
}
|
|
23
20
|
catch (error) {
|
|
24
21
|
const message = error instanceof Error ? error.message : 'People search failed.';
|
|
25
|
-
|
|
22
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
26
23
|
process.exit(1);
|
|
27
24
|
}
|
|
28
25
|
});
|
|
@@ -13,11 +13,7 @@ const support_1 = require("./support");
|
|
|
13
13
|
const tags_1 = require("./tags");
|
|
14
14
|
const transcripts_1 = require("./transcripts");
|
|
15
15
|
const update_1 = require("./update");
|
|
16
|
-
const standaloneCommands = [
|
|
17
|
-
auth_1.loginCommand,
|
|
18
|
-
auth_1.logoutCommand,
|
|
19
|
-
update_1.updateCommand,
|
|
20
|
-
];
|
|
16
|
+
const standaloneCommands = [auth_1.authCommand, update_1.updateCommand];
|
|
21
17
|
const commandGroups = [
|
|
22
18
|
{
|
|
23
19
|
name: 'meetings',
|
package/dist/commands/support.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.searchSupportCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const error_1 = require("../helpers/error");
|
|
7
|
+
const output_1 = require("../helpers/output");
|
|
11
8
|
const formatter_1 = require("../helpers/formatter");
|
|
12
9
|
exports.searchSupportCommand = new commander_1.Command('search')
|
|
13
10
|
.description('Search Circleback support articles.')
|
|
@@ -24,7 +21,7 @@ exports.searchSupportCommand = new commander_1.Command('search')
|
|
|
24
21
|
}
|
|
25
22
|
catch (error) {
|
|
26
23
|
const message = error instanceof Error ? error.message : 'Support search failed.';
|
|
27
|
-
|
|
24
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
28
25
|
process.exit(1);
|
|
29
26
|
}
|
|
30
27
|
});
|
package/dist/commands/tags.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listTagsCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const error_1 = require("../helpers/error");
|
|
7
|
+
const output_1 = require("../helpers/output");
|
|
11
8
|
const formatter_1 = require("../helpers/formatter");
|
|
12
9
|
exports.listTagsCommand = new commander_1.Command('list')
|
|
13
10
|
.description('List all tags.')
|
|
@@ -21,7 +18,7 @@ exports.listTagsCommand = new commander_1.Command('list')
|
|
|
21
18
|
}
|
|
22
19
|
catch (error) {
|
|
23
20
|
const message = error instanceof Error ? error.message : 'Failed to list tags.';
|
|
24
|
-
|
|
21
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
25
22
|
process.exit(1);
|
|
26
23
|
}
|
|
27
24
|
});
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getTranscriptsCommand = exports.searchTranscriptsCommand = void 0;
|
|
7
4
|
const commander_1 = require("commander");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
10
6
|
const constants_1 = require("../constants");
|
|
11
7
|
const error_1 = require("../helpers/error");
|
|
8
|
+
const output_1 = require("../helpers/output");
|
|
12
9
|
const formatter_1 = require("../helpers/formatter");
|
|
13
10
|
const parse_1 = require("../helpers/parse");
|
|
14
11
|
const tag_1 = require("../helpers/tag");
|
|
@@ -38,7 +35,7 @@ exports.searchTranscriptsCommand = new commander_1.Command('search')
|
|
|
38
35
|
}
|
|
39
36
|
catch (error) {
|
|
40
37
|
const message = error instanceof Error ? error.message : 'Transcript search failed.';
|
|
41
|
-
|
|
38
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
42
39
|
process.exit(1);
|
|
43
40
|
}
|
|
44
41
|
});
|
|
@@ -58,7 +55,7 @@ exports.getTranscriptsCommand = new commander_1.Command('read')
|
|
|
58
55
|
}
|
|
59
56
|
catch (error) {
|
|
60
57
|
const message = error instanceof Error ? error.message : 'Transcript retrieval failed.';
|
|
61
|
-
|
|
58
|
+
(0, output_1.printText)((0, error_1.formatMcpError)(message) ?? message, output_1.TextType.Error);
|
|
62
59
|
process.exit(1);
|
|
63
60
|
}
|
|
64
61
|
});
|
package/dist/commands/update.js
CHANGED
|
@@ -8,28 +8,28 @@ const commander_1 = require("commander");
|
|
|
8
8
|
const node_child_process_1 = require("node:child_process");
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const constants_1 = require("../constants");
|
|
11
|
+
const output_1 = require("../helpers/output");
|
|
11
12
|
const update_1 = require("../helpers/update");
|
|
12
13
|
exports.updateCommand = new commander_1.Command('update')
|
|
13
14
|
.description('Update Circleback CLI to the latest version.')
|
|
14
15
|
.action(async () => {
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
(0, output_1.printText)(chalk_1.default.dim(`Current version: ${constants_1.CLIENT_VERSION}`), output_1.TextType.Default);
|
|
17
|
+
(0, output_1.printText)(chalk_1.default.dim('Checking for updates…'), output_1.TextType.Default);
|
|
17
18
|
const result = await (0, update_1.getUpdateCheckResult)(constants_1.CLIENT_PACKAGE_NAME);
|
|
18
19
|
if (!result.updateAvailable) {
|
|
19
|
-
|
|
20
|
+
(0, output_1.printText)('Already on the latest version.', output_1.TextType.Success);
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
(0, output_1.printText)(`New version available: ${result.currentVersion} → ${result.latestVersion}`, output_1.TextType.Warning);
|
|
24
|
+
(0, output_1.printText)(chalk_1.default.dim(`Running: npm install -g ${constants_1.CLIENT_PACKAGE_NAME}@latest`), output_1.TextType.Default);
|
|
24
25
|
try {
|
|
25
26
|
(0, node_child_process_1.execSync)(`npm install -g ${constants_1.CLIENT_PACKAGE_NAME}@latest`, {
|
|
26
27
|
stdio: 'inherit',
|
|
27
28
|
});
|
|
28
|
-
|
|
29
|
+
(0, output_1.printText)(`Successfully updated to ${result.latestVersion}.`, output_1.TextType.Success);
|
|
29
30
|
}
|
|
30
31
|
catch {
|
|
31
|
-
|
|
32
|
-
console.error(chalk_1.default.cyan(` sudo npm install -g ${constants_1.CLIENT_PACKAGE_NAME}@latest`));
|
|
32
|
+
(0, output_1.printText)(`Update failed. Try running manually with sudo:\n sudo npm install -g ${constants_1.CLIENT_PACKAGE_NAME}@latest`, output_1.TextType.Error);
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
});
|
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.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_HEADER = 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.API_KEY_SETTINGS_URL = exports.API_KEY_ENVIRONMENT_VARIABLE = exports.API_KEY_PREFIX = exports.CLIENT_VERSION_HEADER = 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"));
|
|
@@ -16,6 +16,10 @@ exports.CLIENT_PACKAGE_NAME = '@circleback/cli';
|
|
|
16
16
|
exports.CLIENT_VERSION = packageJson.version;
|
|
17
17
|
// Must match CIRCLEBACK_CLI_VERSION_HEADER in apps/web/helpers/api/mcp/version.ts.
|
|
18
18
|
exports.CLIENT_VERSION_HEADER = 'x-circleback-cli-version';
|
|
19
|
+
// Must match API_KEY_PREFIX in packages/constants/auth.ts.
|
|
20
|
+
exports.API_KEY_PREFIX = 'cb_';
|
|
21
|
+
exports.API_KEY_ENVIRONMENT_VARIABLE = 'CIRCLEBACK_API_KEY';
|
|
22
|
+
exports.API_KEY_SETTINGS_URL = `${exports.BASE_URL}/settings?tab=api-access`;
|
|
19
23
|
exports.BRAND_COLOR = '#F24E1D';
|
|
20
24
|
exports.SECONDARY_COLOR = '#4262FF';
|
|
21
25
|
exports.ASCII_LOGO = `
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.formatOutput = void 0;
|
|
4
4
|
const table_1 = require("./table");
|
|
5
5
|
const parse_1 = require("./parse");
|
|
6
|
+
const output_1 = require("./output");
|
|
6
7
|
const zod_1 = require("zod");
|
|
7
8
|
const stringify = (value) => typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
8
9
|
const formatForTool = (toolName, data) => {
|
|
@@ -38,10 +39,12 @@ const formatForTool = (toolName, data) => {
|
|
|
38
39
|
const formatOutput = (toolName, rawText, jsonMode) => {
|
|
39
40
|
const parsed = (0, parse_1.extractAndValidateObjectFromString)(rawText, zod_1.z.json());
|
|
40
41
|
if (jsonMode) {
|
|
41
|
-
|
|
42
|
+
(0, output_1.printText)(stringify(parsed), output_1.TextType.Default);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
const formatted = formatForTool(toolName, parsed);
|
|
45
|
-
|
|
46
|
+
(0, output_1.printText)(formatted ?? stringify(parsed), Array.isArray(parsed) && parsed.length === 0
|
|
47
|
+
? output_1.TextType.Warning
|
|
48
|
+
: output_1.TextType.Default);
|
|
46
49
|
};
|
|
47
50
|
exports.formatOutput = formatOutput;
|
|
@@ -0,0 +1,34 @@
|
|
|
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.printTextToStderr = exports.printText = exports.formatText = exports.TextType = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
var TextType;
|
|
9
|
+
(function (TextType) {
|
|
10
|
+
TextType["Default"] = "Default";
|
|
11
|
+
TextType["Error"] = "Error";
|
|
12
|
+
TextType["Success"] = "Success";
|
|
13
|
+
TextType["Warning"] = "Warning";
|
|
14
|
+
})(TextType || (exports.TextType = TextType = {}));
|
|
15
|
+
const TEXT_STYLES = {
|
|
16
|
+
[TextType.Default]: (message) => message,
|
|
17
|
+
[TextType.Error]: chalk_1.default.red,
|
|
18
|
+
[TextType.Success]: chalk_1.default.green,
|
|
19
|
+
[TextType.Warning]: chalk_1.default.yellow,
|
|
20
|
+
};
|
|
21
|
+
const formatText = (message, type) => {
|
|
22
|
+
const text = TEXT_STYLES[type](message);
|
|
23
|
+
return type === TextType.Default ? `${text}\n` : `\n${text}\n\n`;
|
|
24
|
+
};
|
|
25
|
+
exports.formatText = formatText;
|
|
26
|
+
const printText = (message, type) => {
|
|
27
|
+
const stream = type === TextType.Error ? process.stderr : process.stdout;
|
|
28
|
+
stream.write((0, exports.formatText)(message, type));
|
|
29
|
+
};
|
|
30
|
+
exports.printText = printText;
|
|
31
|
+
const printTextToStderr = (message, type) => {
|
|
32
|
+
process.stderr.write((0, exports.formatText)(message, type));
|
|
33
|
+
};
|
|
34
|
+
exports.printTextToStderr = printTextToStderr;
|
package/dist/helpers/parse.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.validateMeetingIdentifiers = exports.parseNumericIds = exports.parseIntOption = exports.extractAndValidateObjectFromString = void 0;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
4
|
const zod_1 = require("zod");
|
|
5
|
+
const output_1 = require("./output");
|
|
9
6
|
const extractAndValidateObjectFromString = (rawText, schema) => {
|
|
10
7
|
try {
|
|
11
8
|
const json = JSON.parse(rawText);
|
|
12
9
|
const result = schema.safeParse(json);
|
|
13
10
|
if (result.success)
|
|
14
11
|
return result.data;
|
|
15
|
-
|
|
12
|
+
(0, output_1.printText)('Failed to parse response.', output_1.TextType.Error);
|
|
16
13
|
process.exit(1);
|
|
17
14
|
}
|
|
18
15
|
catch {
|
|
@@ -25,7 +22,7 @@ const numericIdsSchema = zod_1.z.array(intSchema);
|
|
|
25
22
|
const parseIntOption = (value, flagName) => {
|
|
26
23
|
const result = intSchema.safeParse(value);
|
|
27
24
|
if (!result.success) {
|
|
28
|
-
|
|
25
|
+
(0, output_1.printText)(`Invalid number for ${flagName}.`, output_1.TextType.Error);
|
|
29
26
|
process.exit(1);
|
|
30
27
|
}
|
|
31
28
|
return result.data;
|
|
@@ -34,7 +31,7 @@ exports.parseIntOption = parseIntOption;
|
|
|
34
31
|
const parseNumericIds = (value, label) => {
|
|
35
32
|
const result = numericIdsSchema.safeParse(value.split(','));
|
|
36
33
|
if (!result.success) {
|
|
37
|
-
|
|
34
|
+
(0, output_1.printText)(`Invalid ${label}. Expected numeric IDs.`, output_1.TextType.Error);
|
|
38
35
|
process.exit(1);
|
|
39
36
|
}
|
|
40
37
|
return result.data;
|
|
@@ -45,7 +42,7 @@ const validateMeetingIdentifiers = (values) => {
|
|
|
45
42
|
const isValidIdentifier = /^[A-Za-z0-9_-]{1,64}$/;
|
|
46
43
|
if (cleanedValues.length === 0 ||
|
|
47
44
|
cleanedValues.some((value) => !isValidIdentifier.test(value))) {
|
|
48
|
-
|
|
45
|
+
(0, output_1.printText)('Invalid meeting identifiers. Expected one or more meeting IDs.', output_1.TextType.Error);
|
|
49
46
|
process.exit(1);
|
|
50
47
|
}
|
|
51
48
|
return cleanedValues;
|
package/dist/helpers/table.js
CHANGED
|
@@ -38,7 +38,7 @@ const formatSender = (sender) => {
|
|
|
38
38
|
};
|
|
39
39
|
const formatMeetingsList = (meetings) => {
|
|
40
40
|
if (meetings.length === 0)
|
|
41
|
-
return
|
|
41
|
+
return 'No meetings found.';
|
|
42
42
|
const idWidth = idColumnWidth(meetings.map((meeting) => meeting.id));
|
|
43
43
|
const nameWidth = 40;
|
|
44
44
|
const dateWidth = 14;
|
|
@@ -65,7 +65,7 @@ const formatMeetingsList = (meetings) => {
|
|
|
65
65
|
exports.formatMeetingsList = formatMeetingsList;
|
|
66
66
|
const formatMeetingDetails = (meetings) => {
|
|
67
67
|
if (meetings.length === 0)
|
|
68
|
-
return
|
|
68
|
+
return 'No meetings found.';
|
|
69
69
|
return meetings
|
|
70
70
|
.map((meeting) => {
|
|
71
71
|
const header = chalk_1.default.bold.cyan(`\n# ${meeting.name}`);
|
|
@@ -98,7 +98,7 @@ const formatMeetingDetails = (meetings) => {
|
|
|
98
98
|
exports.formatMeetingDetails = formatMeetingDetails;
|
|
99
99
|
const formatTranscriptSearchResults = (results) => {
|
|
100
100
|
if (results.length === 0)
|
|
101
|
-
return
|
|
101
|
+
return 'No transcript matches found.';
|
|
102
102
|
const idWidth = idColumnWidth(results.map((result) => result.meetingId));
|
|
103
103
|
const meetingWidth = 25;
|
|
104
104
|
const contentWidth = 60;
|
|
@@ -118,7 +118,7 @@ const formatTranscriptSearchResults = (results) => {
|
|
|
118
118
|
exports.formatTranscriptSearchResults = formatTranscriptSearchResults;
|
|
119
119
|
const formatTranscriptReadResults = (results) => {
|
|
120
120
|
if (results.length === 0)
|
|
121
|
-
return
|
|
121
|
+
return 'No transcripts found.';
|
|
122
122
|
return results
|
|
123
123
|
.map((result) => {
|
|
124
124
|
const header = chalk_1.default.bold.cyan(`\n# ${result.meetingName}`);
|
|
@@ -136,7 +136,7 @@ const formatTranscriptReadResults = (results) => {
|
|
|
136
136
|
exports.formatTranscriptReadResults = formatTranscriptReadResults;
|
|
137
137
|
const formatCalendarEvents = (events) => {
|
|
138
138
|
if (events.length === 0)
|
|
139
|
-
return
|
|
139
|
+
return 'No calendar events found.';
|
|
140
140
|
const table = new cli_table3_1.default({
|
|
141
141
|
head: [
|
|
142
142
|
style_1.brand.bold('Title'),
|
|
@@ -161,7 +161,7 @@ const formatCalendarEvents = (events) => {
|
|
|
161
161
|
exports.formatCalendarEvents = formatCalendarEvents;
|
|
162
162
|
const formatProfiles = (profiles) => {
|
|
163
163
|
if (profiles.length === 0)
|
|
164
|
-
return
|
|
164
|
+
return 'No people found.';
|
|
165
165
|
const idWidth = idColumnWidth(profiles.map((profile) => profile.id));
|
|
166
166
|
const nameWidth = 25;
|
|
167
167
|
const emailWidth = 30;
|
|
@@ -191,7 +191,7 @@ const formatProfiles = (profiles) => {
|
|
|
191
191
|
exports.formatProfiles = formatProfiles;
|
|
192
192
|
const formatCompanies = (companies) => {
|
|
193
193
|
if (companies.length === 0)
|
|
194
|
-
return
|
|
194
|
+
return 'No companies found.';
|
|
195
195
|
const table = new cli_table3_1.default({
|
|
196
196
|
head: [style_1.brand.bold('Company'), style_1.brand.bold('Domain')],
|
|
197
197
|
style: style_1.tableStyle,
|
|
@@ -202,7 +202,7 @@ const formatCompanies = (companies) => {
|
|
|
202
202
|
exports.formatCompanies = formatCompanies;
|
|
203
203
|
const formatSupportArticles = (articles) => {
|
|
204
204
|
if (articles.length === 0)
|
|
205
|
-
return
|
|
205
|
+
return 'No articles found.';
|
|
206
206
|
return articles
|
|
207
207
|
.map((article) => `${(0, string_1.link)(chalk_1.default.bold.cyan(article.title), article.url)}\n${(0, string_1.link)(chalk_1.default.dim.underline(article.url), article.url)}\n${article.description}`)
|
|
208
208
|
.join('\n\n');
|
|
@@ -210,7 +210,7 @@ const formatSupportArticles = (articles) => {
|
|
|
210
210
|
exports.formatSupportArticles = formatSupportArticles;
|
|
211
211
|
const formatActionItems = (actionItems) => {
|
|
212
212
|
if (actionItems.length === 0)
|
|
213
|
-
return
|
|
213
|
+
return 'No action items found.';
|
|
214
214
|
const idWidth = idColumnWidth(actionItems.map((item) => item.id));
|
|
215
215
|
const titleWidth = 35;
|
|
216
216
|
const statusWidth = 10;
|
|
@@ -250,7 +250,7 @@ const formatActionItems = (actionItems) => {
|
|
|
250
250
|
exports.formatActionItems = formatActionItems;
|
|
251
251
|
const formatTags = (tags) => {
|
|
252
252
|
if (tags.length === 0)
|
|
253
|
-
return
|
|
253
|
+
return 'No tags found.';
|
|
254
254
|
const idWidth = idColumnWidth(tags.map((tag) => tag.id));
|
|
255
255
|
const nameWidth = 40;
|
|
256
256
|
const table = new cli_table3_1.default({
|
|
@@ -273,7 +273,7 @@ const formatMessage = (message) => {
|
|
|
273
273
|
};
|
|
274
274
|
const formatEmails = (threads) => {
|
|
275
275
|
if (threads.length === 0)
|
|
276
|
-
return
|
|
276
|
+
return 'No emails found.';
|
|
277
277
|
return threads
|
|
278
278
|
.flatMap((thread) => thread.messages.map(formatMessage))
|
|
279
279
|
.join('\n\n---\n');
|
package/dist/helpers/tag.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.resolveTagValues = void 0;
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
4
|
const zod_1 = require("zod");
|
|
9
5
|
const jsonRpc_1 = require("../client/jsonRpc");
|
|
6
|
+
const output_1 = require("./output");
|
|
10
7
|
const parse_1 = require("./parse");
|
|
11
8
|
const tagItemSchema = zod_1.z.object({
|
|
12
9
|
id: zod_1.z.number(),
|
|
@@ -25,12 +22,12 @@ const resolveTagValues = async (value) => {
|
|
|
25
22
|
.map((part) => part.trim())
|
|
26
23
|
.filter((part) => part.length > 0);
|
|
27
24
|
if (parts.length === 0) {
|
|
28
|
-
|
|
25
|
+
(0, output_1.printText)('No tag values provided.', output_1.TextType.Error);
|
|
29
26
|
process.exit(1);
|
|
30
27
|
}
|
|
31
28
|
const tagList = await fetchUserTags();
|
|
32
29
|
if (typeof tagList === 'string') {
|
|
33
|
-
|
|
30
|
+
(0, output_1.printText)('Failed to fetch tags.', output_1.TextType.Error);
|
|
34
31
|
process.exit(1);
|
|
35
32
|
}
|
|
36
33
|
return parts.map((part) => {
|
|
@@ -41,7 +38,7 @@ const resolveTagValues = async (value) => {
|
|
|
41
38
|
if (!isNaN(numericId) && tagList.some((tag) => tag.id === numericId)) {
|
|
42
39
|
return numericId;
|
|
43
40
|
}
|
|
44
|
-
|
|
41
|
+
(0, output_1.printText)(`Tag "${part}" not found.`, output_1.TextType.Error);
|
|
45
42
|
process.exit(1);
|
|
46
43
|
});
|
|
47
44
|
};
|
package/dist/helpers/update.js
CHANGED
|
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const constants_1 = require("../constants");
|
|
11
|
+
const output_1 = require("./output");
|
|
11
12
|
const CACHE_FILE = node_path_1.default.join(constants_1.CONFIG_DIRECTORY, 'update-check.json');
|
|
12
13
|
const CHECK_INTERVAL_MILLISECONDS = 60 * 60 * 1000; // 1 hour
|
|
13
14
|
const REGISTRY_TIMEOUT_MILLISECONDS = 3_000;
|
|
@@ -96,11 +97,9 @@ const printUpdateNotification = (result) => {
|
|
|
96
97
|
if (!result.updateAvailable)
|
|
97
98
|
return;
|
|
98
99
|
const message = [
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
chalk_1.default.yellow(` Run ${chalk_1.default.cyan('circleback update')} or ${chalk_1.default.cyan('cb update')} to update.`),
|
|
102
|
-
'',
|
|
100
|
+
` Update available: ${chalk_1.default.dim(result.currentVersion)} → ${chalk_1.default.green(result.latestVersion)}`,
|
|
101
|
+
` Run ${chalk_1.default.cyan('circleback update')} or ${chalk_1.default.cyan('cb update')} to update.`,
|
|
103
102
|
].join('\n');
|
|
104
|
-
|
|
103
|
+
process.stderr.write((0, output_1.formatText)(message, output_1.TextType.Warning));
|
|
105
104
|
};
|
|
106
105
|
exports.printUpdateNotification = printUpdateNotification;
|
package/dist/index.js
CHANGED
|
@@ -5,22 +5,28 @@ const commander_1 = require("commander");
|
|
|
5
5
|
const registry_1 = require("./commands/registry");
|
|
6
6
|
const constants_1 = require("./constants");
|
|
7
7
|
const help_1 = require("./helpers/help");
|
|
8
|
+
const output_1 = require("./helpers/output");
|
|
8
9
|
const style_1 = require("./helpers/style");
|
|
9
10
|
const update_1 = require("./helpers/update");
|
|
10
11
|
const program = new commander_1.Command();
|
|
11
12
|
const updateCheck = (0, update_1.getUpdateCheckResult)(constants_1.CLIENT_PACKAGE_NAME);
|
|
13
|
+
const configureCommandOutput = (command) => {
|
|
14
|
+
command.configureOutput({
|
|
15
|
+
writeOut: (text) => (0, output_1.printText)((0, help_1.styleHelpOutput)(text).trimEnd(), output_1.TextType.Default),
|
|
16
|
+
writeErr: (text) => (0, output_1.printTextToStderr)((0, help_1.styleHelpOutput)(text).trimEnd(), output_1.TextType.Default),
|
|
17
|
+
outputError: (text) => (0, output_1.printText)((0, help_1.styleHelpOutput)(text).trim(), output_1.TextType.Error),
|
|
18
|
+
});
|
|
19
|
+
command.commands.forEach(configureCommandOutput);
|
|
20
|
+
};
|
|
12
21
|
program
|
|
13
22
|
.name('circleback')
|
|
14
23
|
.description('Search and access meetings, emails, calendar events, and more.')
|
|
15
24
|
.version(constants_1.CLIENT_VERSION)
|
|
16
25
|
.option('--json', 'Output raw JSON instead of formatted text')
|
|
17
26
|
.addHelpText('before', style_1.BANNER)
|
|
18
|
-
.exitOverride()
|
|
19
|
-
.configureOutput({
|
|
20
|
-
writeOut: (text) => process.stdout.write((0, help_1.styleHelpOutput)(text)),
|
|
21
|
-
writeErr: (text) => process.stderr.write((0, help_1.styleHelpOutput)(text)),
|
|
22
|
-
});
|
|
27
|
+
.exitOverride();
|
|
23
28
|
(0, registry_1.getAllCommands)().reduce((p, command) => p.addCommand(command), program);
|
|
29
|
+
configureCommandOutput(program);
|
|
24
30
|
program.hook('postAction', async (_thisCommand, actionCommand) => {
|
|
25
31
|
if (actionCommand.name() === 'update')
|
|
26
32
|
return;
|
|
@@ -32,6 +38,6 @@ program.hook('postAction', async (_thisCommand, actionCommand) => {
|
|
|
32
38
|
program.parseAsync().catch((error) => {
|
|
33
39
|
if (error instanceof commander_1.CommanderError)
|
|
34
40
|
process.exit(error.exitCode);
|
|
35
|
-
|
|
41
|
+
(0, output_1.printText)(error instanceof Error ? error.message : String(error), output_1.TextType.Error);
|
|
36
42
|
process.exit(1);
|
|
37
43
|
});
|
package/dist/types.js
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isJsonRpcResponse = exports.isOAuthTokenResponse = exports.
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
exports.isJsonRpcResponse = exports.isOAuthTokenResponse = exports.isStoredApiKey = exports.parseStoredCredentials = exports.CredentialSource = exports.CredentialType = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
var CredentialType;
|
|
6
|
+
(function (CredentialType) {
|
|
7
|
+
CredentialType["ApiKey"] = "apiKey";
|
|
8
|
+
CredentialType["OAuth"] = "oauth";
|
|
9
|
+
})(CredentialType || (exports.CredentialType = CredentialType = {}));
|
|
10
|
+
var CredentialSource;
|
|
11
|
+
(function (CredentialSource) {
|
|
12
|
+
CredentialSource["Environment"] = "environment";
|
|
13
|
+
CredentialSource["Stored"] = "stored";
|
|
14
|
+
})(CredentialSource || (exports.CredentialSource = CredentialSource = {}));
|
|
15
|
+
const storedTokensSchema = zod_1.z.object({
|
|
16
|
+
accessToken: zod_1.z.string(),
|
|
17
|
+
refreshToken: zod_1.z.string(),
|
|
18
|
+
expiresAt: zod_1.z.number(),
|
|
19
|
+
clientId: zod_1.z.string(),
|
|
20
|
+
scope: zod_1.z.string(),
|
|
21
|
+
});
|
|
22
|
+
const storedApiKeySchema = zod_1.z.object({
|
|
23
|
+
type: zod_1.z.literal(CredentialType.ApiKey),
|
|
24
|
+
apiKey: zod_1.z.string().trim().min(1),
|
|
25
|
+
});
|
|
26
|
+
const storedCredentialsSchema = zod_1.z.union([
|
|
27
|
+
storedApiKeySchema,
|
|
28
|
+
storedTokensSchema,
|
|
29
|
+
]);
|
|
30
|
+
const parseStoredCredentials = (value) => {
|
|
31
|
+
const result = storedCredentialsSchema.safeParse(value);
|
|
32
|
+
return result.success ? result.data : undefined;
|
|
33
|
+
};
|
|
34
|
+
exports.parseStoredCredentials = parseStoredCredentials;
|
|
35
|
+
const isStoredApiKey = (value) => storedApiKeySchema.safeParse(value).success;
|
|
36
|
+
exports.isStoredApiKey = isStoredApiKey;
|
|
17
37
|
const isOAuthTokenResponse = (value) => typeof value === 'object' &&
|
|
18
38
|
value !== null &&
|
|
19
39
|
'access_token' in value &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@circleback/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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)",
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/lodash": "^4.17.24",
|
|
46
46
|
"@types/node": "^18.19.130",
|
|
47
|
-
"typescript": "
|
|
47
|
+
"typescript": "7.0.2"
|
|
48
48
|
}
|
|
49
49
|
}
|