@ogment-ai/cli 0.4.2 → 0.5.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/dist/cli/commands.d.ts +38 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +57 -0
- package/dist/cli/execute.d.ts +11 -0
- package/dist/cli/execute.d.ts.map +1 -0
- package/dist/cli/execute.js +487 -0
- package/dist/cli/invocations.d.ts +32 -0
- package/dist/cli/invocations.d.ts.map +1 -0
- package/dist/cli/invocations.js +1 -0
- package/dist/cli/parse-errors.d.ts +17 -0
- package/dist/cli/parse-errors.d.ts.map +1 -0
- package/dist/cli/parse-errors.js +184 -0
- package/dist/cli/program.d.ts +10 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +183 -0
- package/dist/cli/run.d.ts +6 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +83 -0
- package/dist/cli/runtime.d.ts +22 -0
- package/dist/cli/runtime.d.ts.map +1 -0
- package/dist/cli/runtime.js +86 -0
- package/dist/cli.d.ts +2 -20
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -737
- package/dist/commands/catalog.d.ts +3 -1
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +19 -2
- package/dist/commands/invoke.d.ts.map +1 -1
- package/dist/commands/invoke.js +53 -3
- package/dist/infra/http.d.ts +5 -1
- package/dist/infra/http.d.ts.map +1 -1
- package/dist/infra/http.js +62 -5
- package/dist/output/envelope.d.ts +5 -2
- package/dist/output/envelope.d.ts.map +1 -1
- package/dist/output/envelope.js +39 -23
- package/dist/output/manager.d.ts +9 -3
- package/dist/output/manager.d.ts.map +1 -1
- package/dist/output/manager.js +53 -2
- package/dist/services/account.d.ts.map +1 -1
- package/dist/services/account.js +9 -16
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +70 -52
- package/dist/services/info.d.ts.map +1 -1
- package/dist/services/info.js +62 -0
- package/dist/services/mcp-error-mapping.d.ts +9 -0
- package/dist/services/mcp-error-mapping.d.ts.map +1 -0
- package/dist/services/mcp-error-mapping.js +129 -0
- package/dist/services/mcp.d.ts +8 -2
- package/dist/services/mcp.d.ts.map +1 -1
- package/dist/services/mcp.js +24 -14
- package/dist/shared/error-codes.d.ts +4 -1
- package/dist/shared/error-codes.d.ts.map +1 -1
- package/dist/shared/error-presentation.d.ts +17 -0
- package/dist/shared/error-presentation.d.ts.map +1 -0
- package/dist/shared/error-presentation.js +151 -0
- package/dist/shared/errors.d.ts +34 -14
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +126 -25
- package/dist/shared/guards.d.ts +2 -1
- package/dist/shared/guards.d.ts.map +1 -1
- package/dist/shared/guards.js +1 -3
- package/dist/shared/recovery.d.ts +5 -0
- package/dist/shared/recovery.d.ts.map +1 -0
- package/dist/shared/recovery.js +123 -0
- package/dist/shared/types.d.ts +53 -13
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +1 -1
- package/package.json +2 -2
- package/dist/shared/retry.d.ts +0 -17
- package/dist/shared/retry.d.ts.map +0 -1
- package/dist/shared/retry.js +0 -27
package/dist/services/auth.js
CHANGED
|
@@ -9,7 +9,6 @@ import { CLI_CLIENT_NAME, CLI_REDIRECT_HOST } from "../shared/constants.js";
|
|
|
9
9
|
import { ERROR_CODE } from "../shared/error-codes.js";
|
|
10
10
|
import { AuthError, RemoteRequestError, UnexpectedError, ValidationError, } from "../shared/errors.js";
|
|
11
11
|
import { parseWithSchema } from "../shared/guards.js";
|
|
12
|
-
import { remoteRetryConfig } from "../shared/retry.js";
|
|
13
12
|
import { browserAgentCallbackSchema, cliExchangeErrorSchema, cliExchangeRequestSchema, cliExchangeSuccessSchema, deviceCodeStartSchema, deviceTokenApprovedSchema, oauthClientRegistrationSchema, oauthTokenSchema, } from "../shared/schemas.js";
|
|
14
13
|
const CALLBACK_TIMEOUT_MILLISECONDS = 5 * 60 * 1000;
|
|
15
14
|
const defaultSleep = async (milliseconds) => {
|
|
@@ -127,7 +126,7 @@ const waitForOAuthCallback = async (server, port) => {
|
|
|
127
126
|
return Result.err(new AuthError({
|
|
128
127
|
code: ERROR_CODE.authInvalidCredentials,
|
|
129
128
|
message: `OAuth error: ${oauthError}`,
|
|
130
|
-
|
|
129
|
+
recovery: { command: "ogment auth login --browser" },
|
|
131
130
|
}));
|
|
132
131
|
}
|
|
133
132
|
const code = url.searchParams.get("code");
|
|
@@ -139,7 +138,7 @@ const waitForOAuthCallback = async (server, port) => {
|
|
|
139
138
|
return Result.err(new AuthError({
|
|
140
139
|
code: ERROR_CODE.authInvalidCredentials,
|
|
141
140
|
message: "No authorization code in callback",
|
|
142
|
-
|
|
141
|
+
recovery: { command: "ogment auth login --browser" },
|
|
143
142
|
}));
|
|
144
143
|
}
|
|
145
144
|
return Result.ok({
|
|
@@ -154,13 +153,13 @@ const waitForOAuthCallback = async (server, port) => {
|
|
|
154
153
|
return Result.err(new AuthError({
|
|
155
154
|
code: ERROR_CODE.authInvalidCredentials,
|
|
156
155
|
message: "Login timed out. No callback received within 5 minutes.",
|
|
157
|
-
|
|
156
|
+
recovery: { command: "ogment auth login --browser" },
|
|
158
157
|
}));
|
|
159
158
|
}
|
|
160
159
|
return Result.err(new AuthError({
|
|
161
160
|
code: ERROR_CODE.authInvalidCredentials,
|
|
162
161
|
message: "Failed while waiting for OAuth callback.",
|
|
163
|
-
|
|
162
|
+
recovery: { command: "ogment auth login --browser" },
|
|
164
163
|
}));
|
|
165
164
|
}
|
|
166
165
|
finally {
|
|
@@ -169,7 +168,7 @@ const waitForOAuthCallback = async (server, port) => {
|
|
|
169
168
|
return Result.err(new AuthError({
|
|
170
169
|
code: ERROR_CODE.authInvalidCredentials,
|
|
171
170
|
message: "Login timed out. No callback received within 5 minutes.",
|
|
172
|
-
|
|
171
|
+
recovery: { command: "ogment auth login --browser" },
|
|
173
172
|
}));
|
|
174
173
|
};
|
|
175
174
|
const waitForAgentCallback = async (server, port) => {
|
|
@@ -195,7 +194,7 @@ const waitForAgentCallback = async (server, port) => {
|
|
|
195
194
|
return Result.err(new AuthError({
|
|
196
195
|
code: ERROR_CODE.authInvalidCredentials,
|
|
197
196
|
message: "No exchange code in callback",
|
|
198
|
-
|
|
197
|
+
recovery: { command: "ogment auth login --browser" },
|
|
199
198
|
}));
|
|
200
199
|
}
|
|
201
200
|
const agentName = parsedCallback.value.agent_name ?? "CLI Agent";
|
|
@@ -214,13 +213,13 @@ const waitForAgentCallback = async (server, port) => {
|
|
|
214
213
|
return Result.err(new AuthError({
|
|
215
214
|
code: ERROR_CODE.authInvalidCredentials,
|
|
216
215
|
message: "Agent selection timed out.",
|
|
217
|
-
|
|
216
|
+
recovery: { command: "ogment auth login --browser" },
|
|
218
217
|
}));
|
|
219
218
|
}
|
|
220
219
|
return Result.err(new AuthError({
|
|
221
220
|
code: ERROR_CODE.authInvalidCredentials,
|
|
222
221
|
message: "Failed while waiting for agent callback.",
|
|
223
|
-
|
|
222
|
+
recovery: { command: "ogment auth login --browser" },
|
|
224
223
|
}));
|
|
225
224
|
}
|
|
226
225
|
finally {
|
|
@@ -229,7 +228,7 @@ const waitForAgentCallback = async (server, port) => {
|
|
|
229
228
|
return Result.err(new AuthError({
|
|
230
229
|
code: ERROR_CODE.authInvalidCredentials,
|
|
231
230
|
message: "Agent selection timed out.",
|
|
232
|
-
|
|
231
|
+
recovery: { command: "ogment auth login --browser" },
|
|
233
232
|
}));
|
|
234
233
|
};
|
|
235
234
|
const deviceCodeUrl = (baseUrl) => `${baseUrl}/api/v1/mcp-auth/device/code`;
|
|
@@ -246,21 +245,11 @@ export const createAuthService = (deps) => {
|
|
|
246
245
|
const createServerFn = deps.createServerFn ?? createServer;
|
|
247
246
|
const detectEnvironment = deps.detectEnvironment ?? detectExecutionEnvironment;
|
|
248
247
|
const hostnameFn = deps.hostnameFn ?? hostname;
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
return Result.tryPromise({
|
|
252
|
-
catch: (cause) => cause,
|
|
253
|
-
try: async () => {
|
|
254
|
-
const response = await deps.httpClient.request(input, init);
|
|
255
|
-
if (Result.isError(response)) {
|
|
256
|
-
throw response.error;
|
|
257
|
-
}
|
|
258
|
-
return response.value;
|
|
259
|
-
},
|
|
260
|
-
}, retryConfig);
|
|
248
|
+
const requestRemote = async (input, init) => {
|
|
249
|
+
return deps.httpClient.request(input, init);
|
|
261
250
|
};
|
|
262
251
|
const loginWithDevice = async (options) => {
|
|
263
|
-
const startFlowResponse = await
|
|
252
|
+
const startFlowResponse = await requestRemote(deviceCodeUrl(deps.baseUrl), {
|
|
264
253
|
headers: {
|
|
265
254
|
"Content-Type": "application/json",
|
|
266
255
|
},
|
|
@@ -273,14 +262,19 @@ export const createAuthService = (deps) => {
|
|
|
273
262
|
const body = await readResponseText(startFlowResponse.value);
|
|
274
263
|
return Result.err(new RemoteRequestError({
|
|
275
264
|
body,
|
|
265
|
+
httpStatus: startFlowResponse.value.status,
|
|
276
266
|
message: "Failed to start device login",
|
|
277
|
-
|
|
267
|
+
operation: "auth/device/start",
|
|
268
|
+
raw: body,
|
|
269
|
+
source: "http",
|
|
278
270
|
}));
|
|
279
271
|
}
|
|
280
272
|
const startPayload = await Result.tryPromise({
|
|
281
273
|
catch: () => new RemoteRequestError({
|
|
274
|
+
httpStatus: startFlowResponse.value.status,
|
|
282
275
|
message: "Failed to parse device login start payload",
|
|
283
|
-
|
|
276
|
+
operation: "auth/device/start",
|
|
277
|
+
source: "http",
|
|
284
278
|
}),
|
|
285
279
|
try: async () => startFlowResponse.value.json(),
|
|
286
280
|
});
|
|
@@ -299,7 +293,7 @@ export const createAuthService = (deps) => {
|
|
|
299
293
|
const interval = parsedStartPayload.value.data.interval * 1000;
|
|
300
294
|
while (now() < deadline) {
|
|
301
295
|
await sleep(interval);
|
|
302
|
-
const pollResponse = await
|
|
296
|
+
const pollResponse = await requestRemote(deviceTokenUrl(deps.baseUrl), {
|
|
303
297
|
body: JSON.stringify({
|
|
304
298
|
device_code: parsedStartPayload.value.data.device_code,
|
|
305
299
|
}),
|
|
@@ -315,28 +309,33 @@ export const createAuthService = (deps) => {
|
|
|
315
309
|
return Result.err(new AuthError({
|
|
316
310
|
code: ERROR_CODE.authDeviceExpired,
|
|
317
311
|
message: "Device login code expired. Run `ogment auth login` again.",
|
|
318
|
-
|
|
312
|
+
recovery: { command: "ogment auth login" },
|
|
319
313
|
}));
|
|
320
314
|
}
|
|
321
315
|
if (pollResponse.value.status === 404) {
|
|
322
316
|
return Result.err(new AuthError({
|
|
323
317
|
code: ERROR_CODE.authInvalidCredentials,
|
|
324
318
|
message: "Invalid device login code. Run `ogment auth login` again.",
|
|
325
|
-
|
|
319
|
+
recovery: { command: "ogment auth login" },
|
|
326
320
|
}));
|
|
327
321
|
}
|
|
328
322
|
if (!pollResponse.value.ok) {
|
|
329
323
|
const body = await readResponseText(pollResponse.value);
|
|
330
324
|
return Result.err(new RemoteRequestError({
|
|
331
325
|
body,
|
|
326
|
+
httpStatus: pollResponse.value.status,
|
|
332
327
|
message: "Failed to poll device login status",
|
|
333
|
-
|
|
328
|
+
operation: "auth/device/poll",
|
|
329
|
+
raw: body,
|
|
330
|
+
source: "http",
|
|
334
331
|
}));
|
|
335
332
|
}
|
|
336
333
|
const pollPayload = await Result.tryPromise({
|
|
337
334
|
catch: () => new RemoteRequestError({
|
|
335
|
+
httpStatus: pollResponse.value.status,
|
|
338
336
|
message: "Failed to parse device login poll payload",
|
|
339
|
-
|
|
337
|
+
operation: "auth/device/poll",
|
|
338
|
+
source: "http",
|
|
340
339
|
}),
|
|
341
340
|
try: async () => pollResponse.value.json(),
|
|
342
341
|
});
|
|
@@ -359,13 +358,14 @@ export const createAuthService = (deps) => {
|
|
|
359
358
|
}
|
|
360
359
|
return Result.ok({
|
|
361
360
|
agentName: approvedPayload.value.data.agent_name ?? "CLI Agent",
|
|
362
|
-
|
|
361
|
+
loggedIn: true,
|
|
362
|
+
outcome: "authenticated",
|
|
363
363
|
});
|
|
364
364
|
}
|
|
365
365
|
return Result.err(new AuthError({
|
|
366
366
|
code: ERROR_CODE.authDeviceExpired,
|
|
367
367
|
message: "Device login code expired. Run `ogment auth login` again.",
|
|
368
|
-
|
|
368
|
+
recovery: { command: "ogment auth login" },
|
|
369
369
|
}));
|
|
370
370
|
};
|
|
371
371
|
const loginWithBrowser = async () => {
|
|
@@ -375,7 +375,7 @@ export const createAuthService = (deps) => {
|
|
|
375
375
|
}
|
|
376
376
|
const { port, server } = callbackServerResult.value;
|
|
377
377
|
const redirectUri = `http://${CLI_REDIRECT_HOST}:${port}/callback`;
|
|
378
|
-
const registerResponse = await
|
|
378
|
+
const registerResponse = await requestRemote(oauthRegisterUrl(deps.baseUrl), {
|
|
379
379
|
body: JSON.stringify({
|
|
380
380
|
client_name: CLI_CLIENT_NAME,
|
|
381
381
|
grant_types: ["authorization_code"],
|
|
@@ -397,14 +397,19 @@ export const createAuthService = (deps) => {
|
|
|
397
397
|
await closeServer(server);
|
|
398
398
|
return Result.err(new RemoteRequestError({
|
|
399
399
|
body,
|
|
400
|
+
httpStatus: registerResponse.value.status,
|
|
400
401
|
message: "Client registration failed",
|
|
401
|
-
|
|
402
|
+
operation: "auth/browser/register",
|
|
403
|
+
raw: body,
|
|
404
|
+
source: "http",
|
|
402
405
|
}));
|
|
403
406
|
}
|
|
404
407
|
const registerPayload = await Result.tryPromise({
|
|
405
408
|
catch: () => new RemoteRequestError({
|
|
409
|
+
httpStatus: registerResponse.value.status,
|
|
406
410
|
message: "Failed to parse client registration payload",
|
|
407
|
-
|
|
411
|
+
operation: "auth/browser/register",
|
|
412
|
+
source: "http",
|
|
408
413
|
}),
|
|
409
414
|
try: async () => registerResponse.value.json(),
|
|
410
415
|
});
|
|
@@ -447,7 +452,7 @@ export const createAuthService = (deps) => {
|
|
|
447
452
|
return Result.err(new AuthError({
|
|
448
453
|
code: ERROR_CODE.authInvalidCredentials,
|
|
449
454
|
message: "OAuth state mismatch - possible CSRF attack.",
|
|
450
|
-
|
|
455
|
+
recovery: { command: "ogment auth login --browser" },
|
|
451
456
|
}));
|
|
452
457
|
}
|
|
453
458
|
const tokenBody = new URLSearchParams({
|
|
@@ -461,7 +466,7 @@ export const createAuthService = (deps) => {
|
|
|
461
466
|
parsedClient.value.client_secret.length > 0) {
|
|
462
467
|
tokenBody.set("client_secret", parsedClient.value.client_secret);
|
|
463
468
|
}
|
|
464
|
-
const tokenResponse = await
|
|
469
|
+
const tokenResponse = await requestRemote(oauthTokenUrl(deps.baseUrl), {
|
|
465
470
|
body: tokenBody.toString(),
|
|
466
471
|
headers: {
|
|
467
472
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -477,14 +482,19 @@ export const createAuthService = (deps) => {
|
|
|
477
482
|
await closeServer(server);
|
|
478
483
|
return Result.err(new RemoteRequestError({
|
|
479
484
|
body,
|
|
485
|
+
httpStatus: tokenResponse.value.status,
|
|
480
486
|
message: "Token exchange failed",
|
|
481
|
-
|
|
487
|
+
operation: "auth/browser/token",
|
|
488
|
+
raw: body,
|
|
489
|
+
source: "http",
|
|
482
490
|
}));
|
|
483
491
|
}
|
|
484
492
|
const tokenPayload = await Result.tryPromise({
|
|
485
493
|
catch: () => new RemoteRequestError({
|
|
494
|
+
httpStatus: tokenResponse.value.status,
|
|
486
495
|
message: "Failed to parse token payload",
|
|
487
|
-
|
|
496
|
+
operation: "auth/browser/token",
|
|
497
|
+
source: "http",
|
|
488
498
|
}),
|
|
489
499
|
try: async () => tokenResponse.value.json(),
|
|
490
500
|
});
|
|
@@ -518,7 +528,7 @@ export const createAuthService = (deps) => {
|
|
|
518
528
|
if (Result.isError(parsedExchangeRequestPayload)) {
|
|
519
529
|
return parsedExchangeRequestPayload;
|
|
520
530
|
}
|
|
521
|
-
const exchangeResponse = await
|
|
531
|
+
const exchangeResponse = await requestRemote(cliExchangeUrl(deps.baseUrl), {
|
|
522
532
|
body: JSON.stringify(parsedExchangeRequestPayload.value),
|
|
523
533
|
headers: {
|
|
524
534
|
"Content-Type": "application/json",
|
|
@@ -542,36 +552,41 @@ export const createAuthService = (deps) => {
|
|
|
542
552
|
return Result.err(new AuthError({
|
|
543
553
|
code: ERROR_CODE.authDeviceExpired,
|
|
544
554
|
message: "Browser login code expired. Run `ogment auth login --browser` again.",
|
|
545
|
-
|
|
555
|
+
recovery: { command: "ogment auth login --browser" },
|
|
546
556
|
}));
|
|
547
557
|
}
|
|
548
558
|
if (exchangeErrorCode === "invalid_exchange_code") {
|
|
549
559
|
return Result.err(new AuthError({
|
|
550
560
|
code: ERROR_CODE.authInvalidCredentials,
|
|
551
561
|
message: "Invalid browser login code. Run `ogment auth login --browser` again.",
|
|
552
|
-
|
|
562
|
+
recovery: { command: "ogment auth login --browser" },
|
|
553
563
|
}));
|
|
554
564
|
}
|
|
555
565
|
if (exchangeErrorCode === "authorization_pending") {
|
|
556
566
|
return Result.err(new AuthError({
|
|
557
567
|
code: ERROR_CODE.authDevicePending,
|
|
558
568
|
message: "Browser login authorization is still pending.",
|
|
569
|
+
recovery: { command: "ogment auth login --browser" },
|
|
559
570
|
retryable: true,
|
|
560
|
-
suggestedCommand: "ogment auth login --browser",
|
|
561
571
|
}));
|
|
562
572
|
}
|
|
563
573
|
}
|
|
564
574
|
}
|
|
565
575
|
return Result.err(new RemoteRequestError({
|
|
566
576
|
body,
|
|
577
|
+
httpStatus: exchangeResponse.value.status,
|
|
567
578
|
message: "Failed to exchange browser login code",
|
|
568
|
-
|
|
579
|
+
operation: "auth/browser/exchange",
|
|
580
|
+
raw: body,
|
|
581
|
+
source: "http",
|
|
569
582
|
}));
|
|
570
583
|
}
|
|
571
584
|
const exchangePayload = await Result.tryPromise({
|
|
572
585
|
catch: () => new RemoteRequestError({
|
|
586
|
+
httpStatus: exchangeResponse.value.status,
|
|
573
587
|
message: "Failed to parse browser exchange payload",
|
|
574
|
-
|
|
588
|
+
operation: "auth/browser/exchange",
|
|
589
|
+
source: "http",
|
|
575
590
|
}),
|
|
576
591
|
try: async () => exchangeResponse.value.json(),
|
|
577
592
|
});
|
|
@@ -591,7 +606,8 @@ export const createAuthService = (deps) => {
|
|
|
591
606
|
}
|
|
592
607
|
return Result.ok({
|
|
593
608
|
agentName: parsedExchangePayload.value.data.name,
|
|
594
|
-
|
|
609
|
+
loggedIn: true,
|
|
610
|
+
outcome: "authenticated",
|
|
595
611
|
});
|
|
596
612
|
};
|
|
597
613
|
return {
|
|
@@ -606,21 +622,22 @@ export const createAuthService = (deps) => {
|
|
|
606
622
|
}
|
|
607
623
|
return Result.ok({
|
|
608
624
|
agentName: "CLI Agent",
|
|
609
|
-
|
|
625
|
+
loggedIn: true,
|
|
626
|
+
outcome: "authenticated",
|
|
610
627
|
});
|
|
611
628
|
}
|
|
612
629
|
if (options.mode === "apiKey") {
|
|
613
630
|
return Result.err(new ValidationError({
|
|
614
631
|
code: ERROR_CODE.validationInvalidInput,
|
|
615
632
|
message: "Missing API key value. Provide a non-empty API key.",
|
|
616
|
-
|
|
633
|
+
recovery: { command: "ogment auth login --api-key <key>" },
|
|
617
634
|
}));
|
|
618
635
|
}
|
|
619
636
|
if (options.nonInteractive && options.mode === "browser") {
|
|
620
637
|
return Result.err(new ValidationError({
|
|
621
638
|
code: ERROR_CODE.validationInvalidInput,
|
|
622
639
|
message: "Use `ogment auth login` in non-interactive mode.",
|
|
623
|
-
|
|
640
|
+
recovery: { command: "ogment auth login" },
|
|
624
641
|
}));
|
|
625
642
|
}
|
|
626
643
|
const stored = deps.credentialsStore.load();
|
|
@@ -630,7 +647,8 @@ export const createAuthService = (deps) => {
|
|
|
630
647
|
if (stored.value !== null) {
|
|
631
648
|
return Result.ok({
|
|
632
649
|
agentName: stored.value.agentName ?? "CLI Agent",
|
|
633
|
-
|
|
650
|
+
loggedIn: true,
|
|
651
|
+
outcome: "already_authenticated",
|
|
634
652
|
});
|
|
635
653
|
}
|
|
636
654
|
if (options.mode === "device") {
|
|
@@ -649,7 +667,7 @@ export const createAuthService = (deps) => {
|
|
|
649
667
|
revoked: false,
|
|
650
668
|
});
|
|
651
669
|
}
|
|
652
|
-
const revokeResult = await
|
|
670
|
+
const revokeResult = await requestRemote(revokeUrl(deps.baseUrl), {
|
|
653
671
|
headers: {
|
|
654
672
|
Authorization: `Bearer ${stored.value.apiKey}`,
|
|
655
673
|
},
|
|
@@ -682,7 +700,7 @@ export const createAuthService = (deps) => {
|
|
|
682
700
|
return Result.err(new AuthError({
|
|
683
701
|
code: ERROR_CODE.authRequired,
|
|
684
702
|
message: "Not logged in. Run `ogment auth login` or set OGMENT_API_KEY.",
|
|
685
|
-
|
|
703
|
+
recovery: { command: "ogment auth login" },
|
|
686
704
|
}));
|
|
687
705
|
},
|
|
688
706
|
status: async (overrideApiKey) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/services/info.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,aAAa,EAGb,WAAW,EAEZ,MAAM,oBAAoB,CAAC;AAsB5B,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAED,UAAU,eAAe;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,4BAA4B,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5C,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,UAAU,EAAE,UAAU,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/services/info.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,aAAa,EAGb,WAAW,EAEZ,MAAM,oBAAoB,CAAC;AAsB5B,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAED,UAAU,eAAe;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,4BAA4B,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5C,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,UAAU,EAAE,UAAU,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAmGD,eAAO,MAAM,iBAAiB,GAAI,MAAM,eAAe,KAAG,WAwQzD,CAAC"}
|
package/dist/services/info.js
CHANGED
|
@@ -68,6 +68,16 @@ const toSummary = (issues) => {
|
|
|
68
68
|
status: issues.length > 0 ? "warning" : "ok",
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
|
+
const emptyAccountErrorDetails = () => {
|
|
72
|
+
return {
|
|
73
|
+
errorCode: null,
|
|
74
|
+
errorHttpStatus: null,
|
|
75
|
+
errorMcpCode: null,
|
|
76
|
+
errorRaw: null,
|
|
77
|
+
errorRetryable: null,
|
|
78
|
+
errorSource: null,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
71
81
|
export const createInfoService = (deps) => {
|
|
72
82
|
const detectEnvironment = deps.detectExecutionEnvironmentFn ?? detectExecutionEnvironment;
|
|
73
83
|
const existsSyncFn = deps.existsSyncFn ?? existsSync;
|
|
@@ -106,6 +116,7 @@ export const createInfoService = (deps) => {
|
|
|
106
116
|
const collectAccount = async () => {
|
|
107
117
|
if (selectedApiKey === null) {
|
|
108
118
|
return {
|
|
119
|
+
...emptyAccountErrorDetails(),
|
|
109
120
|
errorType: null,
|
|
110
121
|
latencyMs: null,
|
|
111
122
|
message: "No API key available",
|
|
@@ -123,6 +134,7 @@ export const createInfoService = (deps) => {
|
|
|
123
134
|
return organization.servers.map((server) => server.path);
|
|
124
135
|
});
|
|
125
136
|
return {
|
|
137
|
+
...emptyAccountErrorDetails(),
|
|
126
138
|
errorType: null,
|
|
127
139
|
latencyMs: accountElapsedMs,
|
|
128
140
|
message: null,
|
|
@@ -152,6 +164,56 @@ export const createInfoService = (deps) => {
|
|
|
152
164
|
}
|
|
153
165
|
}
|
|
154
166
|
return {
|
|
167
|
+
...("code" in accountResult.error
|
|
168
|
+
? {
|
|
169
|
+
errorCode: String(accountResult.error.code),
|
|
170
|
+
}
|
|
171
|
+
: {
|
|
172
|
+
errorCode: null,
|
|
173
|
+
}),
|
|
174
|
+
...("httpStatus" in accountResult.error
|
|
175
|
+
? {
|
|
176
|
+
errorHttpStatus: typeof accountResult.error.httpStatus === "number"
|
|
177
|
+
? accountResult.error.httpStatus
|
|
178
|
+
: null,
|
|
179
|
+
}
|
|
180
|
+
: {
|
|
181
|
+
errorHttpStatus: null,
|
|
182
|
+
}),
|
|
183
|
+
...("mcpCode" in accountResult.error
|
|
184
|
+
? {
|
|
185
|
+
errorMcpCode: typeof accountResult.error.mcpCode === "number"
|
|
186
|
+
? accountResult.error.mcpCode
|
|
187
|
+
: null,
|
|
188
|
+
}
|
|
189
|
+
: {
|
|
190
|
+
errorMcpCode: null,
|
|
191
|
+
}),
|
|
192
|
+
...("raw" in accountResult.error
|
|
193
|
+
? {
|
|
194
|
+
errorRaw: accountResult.error.raw ?? null,
|
|
195
|
+
}
|
|
196
|
+
: {
|
|
197
|
+
errorRaw: null,
|
|
198
|
+
}),
|
|
199
|
+
...("retryable" in accountResult.error
|
|
200
|
+
? {
|
|
201
|
+
errorRetryable: typeof accountResult.error.retryable === "boolean"
|
|
202
|
+
? accountResult.error.retryable
|
|
203
|
+
: null,
|
|
204
|
+
}
|
|
205
|
+
: {
|
|
206
|
+
errorRetryable: null,
|
|
207
|
+
}),
|
|
208
|
+
...("source" in accountResult.error
|
|
209
|
+
? {
|
|
210
|
+
errorSource: typeof accountResult.error.source === "string"
|
|
211
|
+
? accountResult.error.source
|
|
212
|
+
: null,
|
|
213
|
+
}
|
|
214
|
+
: {
|
|
215
|
+
errorSource: null,
|
|
216
|
+
}),
|
|
155
217
|
errorType: accountResult.error._tag,
|
|
156
218
|
latencyMs: accountElapsedMs,
|
|
157
219
|
message: accountResult.error.message,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RemoteRequestError } from "../shared/errors.js";
|
|
2
|
+
interface CreateRemoteRequestErrorOptions {
|
|
3
|
+
cause: unknown;
|
|
4
|
+
message: string;
|
|
5
|
+
operation: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const createRemoteRequestErrorFromMcpCause: (options: CreateRemoteRequestErrorOptions) => RemoteRequestError;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=mcp-error-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-error-mapping.d.ts","sourceRoot":"","sources":["../../src/services/mcp-error-mapping.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAazD,UAAU,+BAA+B;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AA0ID,eAAO,MAAM,oCAAoC,GAC/C,SAAS,+BAA+B,KACvC,kBAaF,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
2
|
+
import { McpError, isJSONRPCErrorResponse } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { RemoteRequestError } from "../shared/errors.js";
|
|
4
|
+
const toSerializable = (value) => {
|
|
5
|
+
if (value instanceof Error) {
|
|
6
|
+
return {
|
|
7
|
+
message: value.message,
|
|
8
|
+
name: value.name,
|
|
9
|
+
stack: value.stack,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
return structuredClone(value);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return String(value);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const toJsonRpcErrorPayload = (payload) => {
|
|
20
|
+
if (isJSONRPCErrorResponse(payload)) {
|
|
21
|
+
return {
|
|
22
|
+
code: payload.error.code,
|
|
23
|
+
data: payload.error.data,
|
|
24
|
+
raw: toSerializable(payload),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (typeof payload !== "object" || payload === null || !Object.hasOwn(payload, "error")) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const errorRecord = payload.error;
|
|
31
|
+
if (typeof errorRecord !== "object" || errorRecord === null) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const asRecord = errorRecord;
|
|
35
|
+
const code = asRecord["code"];
|
|
36
|
+
if (typeof code !== "number") {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
code,
|
|
41
|
+
data: asRecord["data"],
|
|
42
|
+
raw: toSerializable(payload),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const extractStreamableBody = (message) => {
|
|
46
|
+
const marker = "Error POSTing to endpoint:";
|
|
47
|
+
const markerIndex = message.indexOf(marker);
|
|
48
|
+
if (markerIndex === -1) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const body = message.slice(markerIndex + marker.length).trim();
|
|
52
|
+
return body.length > 0 ? body : undefined;
|
|
53
|
+
};
|
|
54
|
+
const mapStreamableHttpError = (error) => {
|
|
55
|
+
const body = extractStreamableBody(error.message);
|
|
56
|
+
const parsedBody = body === undefined
|
|
57
|
+
? null
|
|
58
|
+
: (() => {
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(body);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
const jsonRpcPayload = parsedBody === null ? null : toJsonRpcErrorPayload(parsedBody);
|
|
67
|
+
const httpStatus = typeof error.code === "number" && error.code >= 100 ? error.code : undefined;
|
|
68
|
+
const retryable = httpStatus === undefined
|
|
69
|
+
? undefined
|
|
70
|
+
: httpStatus === 429 || httpStatus >= 500 || httpStatus === 408;
|
|
71
|
+
return {
|
|
72
|
+
...(body === undefined ? {} : { body }),
|
|
73
|
+
...(httpStatus === undefined ? {} : { httpStatus }),
|
|
74
|
+
...(jsonRpcPayload === null ? {} : { mcpCode: jsonRpcPayload.code }),
|
|
75
|
+
...(jsonRpcPayload === null ? {} : { mcpData: jsonRpcPayload.data }),
|
|
76
|
+
raw: jsonRpcPayload?.raw ?? toSerializable(parsedBody ?? error),
|
|
77
|
+
...(retryable === undefined ? {} : { retryable }),
|
|
78
|
+
source: "mcp_transport_http",
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
const mapMcpError = (error) => {
|
|
82
|
+
return {
|
|
83
|
+
mcpCode: error.code,
|
|
84
|
+
mcpData: toSerializable(error.data),
|
|
85
|
+
raw: toSerializable({
|
|
86
|
+
code: error.code,
|
|
87
|
+
data: error.data,
|
|
88
|
+
message: error.message,
|
|
89
|
+
name: error.name,
|
|
90
|
+
}),
|
|
91
|
+
retryable: error.code === -32_001,
|
|
92
|
+
source: "mcp_jsonrpc",
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
const mapUnknownError = (cause) => {
|
|
96
|
+
if (cause instanceof Error) {
|
|
97
|
+
return {
|
|
98
|
+
raw: toSerializable(cause),
|
|
99
|
+
source: "network",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
raw: toSerializable(cause),
|
|
104
|
+
source: "unknown",
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
const mapCause = (cause) => {
|
|
108
|
+
if (cause instanceof StreamableHTTPError) {
|
|
109
|
+
return mapStreamableHttpError(cause);
|
|
110
|
+
}
|
|
111
|
+
if (cause instanceof McpError) {
|
|
112
|
+
return mapMcpError(cause);
|
|
113
|
+
}
|
|
114
|
+
return mapUnknownError(cause);
|
|
115
|
+
};
|
|
116
|
+
export const createRemoteRequestErrorFromMcpCause = (options) => {
|
|
117
|
+
const mapped = mapCause(options.cause);
|
|
118
|
+
return new RemoteRequestError({
|
|
119
|
+
...(mapped.body === undefined ? {} : { body: mapped.body }),
|
|
120
|
+
...(mapped.httpStatus === undefined ? {} : { httpStatus: mapped.httpStatus }),
|
|
121
|
+
...(mapped.mcpCode === undefined ? {} : { mcpCode: mapped.mcpCode }),
|
|
122
|
+
...(mapped.mcpData === undefined ? {} : { mcpData: mapped.mcpData }),
|
|
123
|
+
message: options.message,
|
|
124
|
+
operation: options.operation,
|
|
125
|
+
raw: mapped.raw,
|
|
126
|
+
...(mapped.retryable === undefined ? {} : { retryable: mapped.retryable }),
|
|
127
|
+
source: mapped.source,
|
|
128
|
+
});
|
|
129
|
+
};
|
package/dist/services/mcp.d.ts
CHANGED
|
@@ -10,10 +10,16 @@ interface McpClientLike {
|
|
|
10
10
|
callTool(params: {
|
|
11
11
|
arguments: Record<string, unknown>;
|
|
12
12
|
name: string;
|
|
13
|
+
}, resultSchema?: unknown, options?: {
|
|
14
|
+
timeout?: number;
|
|
13
15
|
}): Promise<unknown>;
|
|
14
16
|
close(): Promise<void>;
|
|
15
|
-
connect(transport: unknown
|
|
16
|
-
|
|
17
|
+
connect(transport: unknown, options?: {
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
listTools(params?: unknown, options?: {
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}): Promise<{
|
|
17
23
|
tools: Array<Record<string, unknown>>;
|
|
18
24
|
}>;
|
|
19
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/services/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/services/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,eAAe,CAAC;AAI1D,OAAO,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG/E,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMzE,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,QAAQ,CACN,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAC5D,YAAY,CAAC,EAAE,OAAO,EACtB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,CACP,MAAM,CAAC,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7B,OAAO,CAAC;QACT,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KACvC,CAAC,CAAC;CACJ;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,aAAa,CAAC;IACnC,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,6BAA6B,CAAC;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEnE,MAAM,WAAW,UAAU;IACzB,QAAQ,CACN,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;IACxD,SAAS,CACP,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;CAC3D;AAkFD,eAAO,MAAM,gBAAgB,GAAI,MAAM,cAAc,KAAG,UAkIvD,CAAC"}
|