@ogment-ai/cli 0.7.0 → 0.8.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 +59 -0
- package/dist/cli.js +1003 -929
- package/package.json +13 -20
- package/dist/cli.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -4,9 +4,9 @@ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, unlinkSyn
|
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import { execSync } from "node:child_process";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
7
8
|
import { readFile } from "node:fs/promises";
|
|
8
9
|
import { homedir } from "node:os";
|
|
9
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
10
10
|
|
|
11
11
|
//#region \0rolldown/runtime.js
|
|
12
12
|
var __create = Object.create;
|
|
@@ -3061,38 +3061,6 @@ var require_commander = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3061
3061
|
var import_commander = /* @__PURE__ */ __toESM(require_commander(), 1);
|
|
3062
3062
|
const { program, createCommand, createArgument, createOption, CommanderError, InvalidArgumentError, InvalidOptionArgumentError, Command, Argument, Option, Help } = import_commander.default;
|
|
3063
3063
|
|
|
3064
|
-
//#endregion
|
|
3065
|
-
//#region src/shared/error-codes.ts
|
|
3066
|
-
const ERROR_CATEGORY = {
|
|
3067
|
-
auth: "auth",
|
|
3068
|
-
authorization: "authorization",
|
|
3069
|
-
contractMismatch: "contract_mismatch",
|
|
3070
|
-
internal: "internal",
|
|
3071
|
-
notFound: "not_found",
|
|
3072
|
-
rateLimit: "rate_limit",
|
|
3073
|
-
remote: "remote",
|
|
3074
|
-
transport: "transport",
|
|
3075
|
-
validation: "validation"
|
|
3076
|
-
};
|
|
3077
|
-
const ERROR_CODE = {
|
|
3078
|
-
authDeviceExpired: "AUTH_DEVICE_EXPIRED",
|
|
3079
|
-
authDevicePending: "AUTH_DEVICE_PENDING",
|
|
3080
|
-
authInvalidCredentials: "AUTH_INVALID_CREDENTIALS",
|
|
3081
|
-
authRequired: "AUTH_REQUIRED",
|
|
3082
|
-
contractVersionUnsupported: "CONTRACT_VERSION_UNSUPPORTED",
|
|
3083
|
-
internalUnexpected: "INTERNAL_UNEXPECTED",
|
|
3084
|
-
remoteRateLimited: "REMOTE_RATE_LIMITED",
|
|
3085
|
-
remoteUnavailable: "REMOTE_UNAVAILABLE",
|
|
3086
|
-
toolInputSchemaViolation: "TOOL_INPUT_SCHEMA_VIOLATION",
|
|
3087
|
-
toolNotFound: "TOOL_NOT_FOUND",
|
|
3088
|
-
transportRequestFailed: "TRANSPORT_REQUEST_FAILED",
|
|
3089
|
-
validationInvalidInput: "VALIDATION_INVALID_INPUT"
|
|
3090
|
-
};
|
|
3091
|
-
const staticErrorCodes = new Set(Object.values(ERROR_CODE));
|
|
3092
|
-
const isStaticErrorCode = (code) => {
|
|
3093
|
-
return staticErrorCodes.has(code);
|
|
3094
|
-
};
|
|
3095
|
-
|
|
3096
3064
|
//#endregion
|
|
3097
3065
|
//#region ../../node_modules/.pnpm/better-result@2.7.0/node_modules/better-result/dist/index.mjs
|
|
3098
3066
|
/**
|
|
@@ -3806,6 +3774,65 @@ const Result = {
|
|
|
3806
3774
|
flatten
|
|
3807
3775
|
};
|
|
3808
3776
|
|
|
3777
|
+
//#endregion
|
|
3778
|
+
//#region src/shared/error-codes.ts
|
|
3779
|
+
const ERROR_CATEGORY = {
|
|
3780
|
+
auth: "auth",
|
|
3781
|
+
authorization: "authorization",
|
|
3782
|
+
contractMismatch: "contract_mismatch",
|
|
3783
|
+
internal: "internal",
|
|
3784
|
+
notFound: "not_found",
|
|
3785
|
+
rateLimit: "rate_limit",
|
|
3786
|
+
remote: "remote",
|
|
3787
|
+
transport: "transport",
|
|
3788
|
+
validation: "validation"
|
|
3789
|
+
};
|
|
3790
|
+
const ERROR_CODE = {
|
|
3791
|
+
authDeviceExpired: "AUTH_DEVICE_EXPIRED",
|
|
3792
|
+
authDevicePending: "AUTH_DEVICE_PENDING",
|
|
3793
|
+
authInvalidCredentials: "AUTH_INVALID_CREDENTIALS",
|
|
3794
|
+
authRequired: "AUTH_REQUIRED",
|
|
3795
|
+
contractVersionUnsupported: "CONTRACT_VERSION_UNSUPPORTED",
|
|
3796
|
+
internalUnexpected: "INTERNAL_UNEXPECTED",
|
|
3797
|
+
remoteRateLimited: "REMOTE_RATE_LIMITED",
|
|
3798
|
+
remoteUnavailable: "REMOTE_UNAVAILABLE",
|
|
3799
|
+
toolInputSchemaViolation: "TOOL_INPUT_SCHEMA_VIOLATION",
|
|
3800
|
+
toolNotFound: "TOOL_NOT_FOUND",
|
|
3801
|
+
transportRequestFailed: "TRANSPORT_REQUEST_FAILED",
|
|
3802
|
+
validationInvalidInput: "VALIDATION_INVALID_INPUT"
|
|
3803
|
+
};
|
|
3804
|
+
const staticErrorCodes = new Set(Object.values(ERROR_CODE));
|
|
3805
|
+
const isStaticErrorCode = (code) => {
|
|
3806
|
+
return staticErrorCodes.has(code);
|
|
3807
|
+
};
|
|
3808
|
+
|
|
3809
|
+
//#endregion
|
|
3810
|
+
//#region src/shared/json.ts
|
|
3811
|
+
const isJsonValue = (value) => {
|
|
3812
|
+
if (value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string") return true;
|
|
3813
|
+
if (Array.isArray(value)) return value.every((item) => isJsonValue(item));
|
|
3814
|
+
if (typeof value === "object") {
|
|
3815
|
+
if (value === null) return false;
|
|
3816
|
+
return Object.values(value).every((item) => isJsonValue(item));
|
|
3817
|
+
}
|
|
3818
|
+
return false;
|
|
3819
|
+
};
|
|
3820
|
+
const isJsonObject = (value) => {
|
|
3821
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && isJsonValue(value);
|
|
3822
|
+
};
|
|
3823
|
+
const toJsonValue = (value) => {
|
|
3824
|
+
if (isJsonValue(value)) return value;
|
|
3825
|
+
try {
|
|
3826
|
+
const serialized = JSON.stringify(value);
|
|
3827
|
+
if (serialized === void 0) return "[unserializable]";
|
|
3828
|
+
const parsed = JSON.parse(serialized);
|
|
3829
|
+
if (isJsonValue(parsed)) return parsed;
|
|
3830
|
+
return "[unserializable]";
|
|
3831
|
+
} catch {
|
|
3832
|
+
return "[unserializable]";
|
|
3833
|
+
}
|
|
3834
|
+
};
|
|
3835
|
+
|
|
3809
3836
|
//#endregion
|
|
3810
3837
|
//#region src/shared/recovery.ts
|
|
3811
3838
|
const defaultRecoveryByCode = {
|
|
@@ -3982,13 +4009,18 @@ const resolveRemoteErrorCode = (payload, diagnostics) => {
|
|
|
3982
4009
|
};
|
|
3983
4010
|
const resolveRemoteDiagnostics = (payload) => {
|
|
3984
4011
|
const source = payload.source ?? payload.diagnostics?.source ?? "network";
|
|
4012
|
+
const httpStatus = payload.httpStatus ?? payload.status ?? payload.diagnostics?.httpStatus;
|
|
4013
|
+
const mcpCode = payload.mcpCode ?? payload.diagnostics?.mcpCode;
|
|
4014
|
+
const mcpData = payload.mcpData ?? payload.diagnostics?.mcpData;
|
|
4015
|
+
const operation = payload.operation ?? payload.diagnostics?.operation;
|
|
4016
|
+
const raw = payload.raw ?? payload.diagnostics?.raw;
|
|
3985
4017
|
return {
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
4018
|
+
source,
|
|
4019
|
+
...httpStatus === void 0 ? {} : { httpStatus },
|
|
4020
|
+
...mcpCode === void 0 ? {} : { mcpCode },
|
|
4021
|
+
...mcpData === void 0 ? {} : { mcpData },
|
|
4022
|
+
...operation === void 0 ? {} : { operation },
|
|
4023
|
+
...raw === void 0 ? {} : { raw }
|
|
3992
4024
|
};
|
|
3993
4025
|
};
|
|
3994
4026
|
const resolveRetryableRemoteError = (diagnostics, code) => {
|
|
@@ -4093,7 +4125,7 @@ const appErrorDiagnostics = (error) => {
|
|
|
4093
4125
|
if (error._tag === "NotFoundError") return { resource: error.resource };
|
|
4094
4126
|
if (error._tag === "UnexpectedError") {
|
|
4095
4127
|
if (error.cause === void 0) return {};
|
|
4096
|
-
return { cause: error.cause };
|
|
4128
|
+
return { cause: toJsonValue(error.cause) };
|
|
4097
4129
|
}
|
|
4098
4130
|
if (hasDetails(error) && typeof error.details === "string" && error.details.length > 0) return { details: error.details };
|
|
4099
4131
|
return {};
|
|
@@ -4110,58 +4142,6 @@ const formatAppError = (error) => {
|
|
|
4110
4142
|
return error.message;
|
|
4111
4143
|
};
|
|
4112
4144
|
|
|
4113
|
-
//#endregion
|
|
4114
|
-
//#region src/shared/exit-codes.ts
|
|
4115
|
-
const EXIT_CODE = {
|
|
4116
|
-
authFailed: 4,
|
|
4117
|
-
authRequired: 3,
|
|
4118
|
-
contractMismatch: 8,
|
|
4119
|
-
internal: 9,
|
|
4120
|
-
notFound: 5,
|
|
4121
|
-
rateLimit: 6,
|
|
4122
|
-
remote: 7,
|
|
4123
|
-
success: 0,
|
|
4124
|
-
validation: 2
|
|
4125
|
-
};
|
|
4126
|
-
const exitCodeForError = (error) => {
|
|
4127
|
-
const { category, code } = appErrorMeta(error);
|
|
4128
|
-
switch (category) {
|
|
4129
|
-
case ERROR_CATEGORY.auth:
|
|
4130
|
-
if (code === ERROR_CODE.authRequired) return EXIT_CODE.authRequired;
|
|
4131
|
-
return EXIT_CODE.authFailed;
|
|
4132
|
-
case ERROR_CATEGORY.notFound: return EXIT_CODE.notFound;
|
|
4133
|
-
case ERROR_CATEGORY.rateLimit: return EXIT_CODE.rateLimit;
|
|
4134
|
-
case ERROR_CATEGORY.remote:
|
|
4135
|
-
case ERROR_CATEGORY.transport:
|
|
4136
|
-
case ERROR_CATEGORY.authorization: return EXIT_CODE.remote;
|
|
4137
|
-
case ERROR_CATEGORY.contractMismatch: return EXIT_CODE.contractMismatch;
|
|
4138
|
-
case ERROR_CATEGORY.validation: return EXIT_CODE.validation;
|
|
4139
|
-
case ERROR_CATEGORY.internal: return EXIT_CODE.internal;
|
|
4140
|
-
}
|
|
4141
|
-
};
|
|
4142
|
-
|
|
4143
|
-
//#endregion
|
|
4144
|
-
//#region src/commands/auth.ts
|
|
4145
|
-
const runAuthLoginCommand = async (context, options) => {
|
|
4146
|
-
const loginOptions = (() => {
|
|
4147
|
-
if (options.mode === "apiKey") return {
|
|
4148
|
-
apiKey: options.apiKey,
|
|
4149
|
-
mode: "apiKey"
|
|
4150
|
-
};
|
|
4151
|
-
return {
|
|
4152
|
-
mode: "device",
|
|
4153
|
-
...options.onPending === void 0 ? {} : { onPending: options.onPending }
|
|
4154
|
-
};
|
|
4155
|
-
})();
|
|
4156
|
-
return context.services.auth.login(loginOptions);
|
|
4157
|
-
};
|
|
4158
|
-
const runAuthStatusCommand = async (context) => {
|
|
4159
|
-
return context.services.auth.status(context.apiKeyOverride);
|
|
4160
|
-
};
|
|
4161
|
-
const runAuthLogoutCommand = async (context) => {
|
|
4162
|
-
return context.services.auth.logout();
|
|
4163
|
-
};
|
|
4164
|
-
|
|
4165
4145
|
//#endregion
|
|
4166
4146
|
//#region src/shared/guards.ts
|
|
4167
4147
|
const formatIssues = (issues) => {
|
|
@@ -4180,22 +4160,60 @@ const parseWithSchema = (schema, payload, context, options = {}) => {
|
|
|
4180
4160
|
}));
|
|
4181
4161
|
return Result.ok(parsed.data);
|
|
4182
4162
|
};
|
|
4183
|
-
const
|
|
4163
|
+
const parseJsonValue = (raw, context) => {
|
|
4184
4164
|
return Result.try({
|
|
4185
|
-
catch: () =>
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4165
|
+
catch: () => {
|
|
4166
|
+
return new ValidationError({
|
|
4167
|
+
details: raw,
|
|
4168
|
+
message: `Invalid JSON in ${context}`
|
|
4169
|
+
});
|
|
4170
|
+
},
|
|
4189
4171
|
try: () => {
|
|
4190
|
-
return JSON.parse(raw);
|
|
4172
|
+
return toJsonValue(JSON.parse(raw));
|
|
4191
4173
|
}
|
|
4192
4174
|
});
|
|
4193
4175
|
};
|
|
4194
4176
|
const isRecord$1 = (value) => {
|
|
4195
4177
|
return typeof value === "object" && value !== null;
|
|
4196
4178
|
};
|
|
4197
|
-
|
|
4198
|
-
|
|
4179
|
+
|
|
4180
|
+
//#endregion
|
|
4181
|
+
//#region src/shared/remote-error-details.ts
|
|
4182
|
+
const parseJsonDetails = (raw) => {
|
|
4183
|
+
const parsed = parseJsonValue(raw, "remote error payload");
|
|
4184
|
+
if (Result.isError(parsed)) return null;
|
|
4185
|
+
const details = parseRemoteErrorDetails(parsed.value);
|
|
4186
|
+
if (details.message === void 0 && details.mcpCode === void 0 && details.data === void 0) return null;
|
|
4187
|
+
return details;
|
|
4188
|
+
};
|
|
4189
|
+
const parseRemoteErrorDetails = (payload) => {
|
|
4190
|
+
if (typeof payload === "string") {
|
|
4191
|
+
const trimmed = payload.trim();
|
|
4192
|
+
if (trimmed.length === 0) return {};
|
|
4193
|
+
const fromFullJson = parseJsonDetails(trimmed);
|
|
4194
|
+
if (fromFullJson !== null) return fromFullJson;
|
|
4195
|
+
const firstBraceIndex = trimmed.indexOf("{");
|
|
4196
|
+
if (firstBraceIndex > 0) {
|
|
4197
|
+
const fromEmbeddedJson = parseJsonDetails(trimmed.slice(firstBraceIndex));
|
|
4198
|
+
if (fromEmbeddedJson !== null) return fromEmbeddedJson;
|
|
4199
|
+
}
|
|
4200
|
+
return { message: trimmed };
|
|
4201
|
+
}
|
|
4202
|
+
if (!isRecord$1(payload)) return {};
|
|
4203
|
+
const directCode = payload["code"];
|
|
4204
|
+
const directMessage = payload["message"];
|
|
4205
|
+
if (typeof directCode === "number" || typeof directMessage === "string") return {
|
|
4206
|
+
...typeof directCode === "number" ? { mcpCode: directCode } : {},
|
|
4207
|
+
...typeof directMessage === "string" ? { message: directMessage } : {},
|
|
4208
|
+
...Object.hasOwn(payload, "data") ? { data: toJsonValue(payload["data"]) } : {}
|
|
4209
|
+
};
|
|
4210
|
+
const nestedError = payload["error"];
|
|
4211
|
+
if (!isRecord$1(nestedError)) return {};
|
|
4212
|
+
return {
|
|
4213
|
+
...typeof nestedError["code"] === "number" ? { mcpCode: nestedError["code"] } : {},
|
|
4214
|
+
...typeof nestedError["message"] === "string" ? { message: nestedError["message"] } : {},
|
|
4215
|
+
...Object.hasOwn(nestedError, "data") ? { data: toJsonValue(nestedError["data"]) } : {}
|
|
4216
|
+
};
|
|
4199
4217
|
};
|
|
4200
4218
|
|
|
4201
4219
|
//#endregion
|
|
@@ -4213,37 +4231,24 @@ const sanitizeRemoteMessage = (value) => {
|
|
|
4213
4231
|
const normalized = trimmed.replace(/^[\w]+Error:\s*/u, "").trim();
|
|
4214
4232
|
return normalized.length > 0 ? normalized : void 0;
|
|
4215
4233
|
};
|
|
4216
|
-
const
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
const extractMessageFromBody = (body) => {
|
|
4222
|
-
if (typeof body !== "string" || body.length === 0) return;
|
|
4223
|
-
const parsed = (() => {
|
|
4224
|
-
try {
|
|
4225
|
-
return JSON.parse(body);
|
|
4226
|
-
} catch {
|
|
4227
|
-
return null;
|
|
4228
|
-
}
|
|
4229
|
-
})();
|
|
4230
|
-
if (isRecord$1(parsed)) {
|
|
4231
|
-
const fromParsed = extractMessageFromRecord(parsed);
|
|
4232
|
-
if (fromParsed !== void 0) return fromParsed;
|
|
4234
|
+
const extractNormalizedRemoteMessage = (payload) => {
|
|
4235
|
+
const details = parseRemoteErrorDetails(payload);
|
|
4236
|
+
if (details.message !== void 0) {
|
|
4237
|
+
const normalized = sanitizeRemoteMessage(details.message);
|
|
4238
|
+
if (normalized !== void 0) return normalized;
|
|
4233
4239
|
}
|
|
4234
|
-
return sanitizeRemoteMessage(
|
|
4240
|
+
if (typeof payload === "string") return sanitizeRemoteMessage(payload);
|
|
4235
4241
|
};
|
|
4236
4242
|
const extractRemoteUserMessage = (error) => {
|
|
4237
4243
|
if (error.source !== "mcp_transport_http" && error.source !== "mcp_jsonrpc") return;
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
if (fromData !== void 0) return fromData;
|
|
4244
|
+
for (const payload of [
|
|
4245
|
+
error.raw,
|
|
4246
|
+
error.body,
|
|
4247
|
+
error.mcpData
|
|
4248
|
+
]) {
|
|
4249
|
+
if (payload === void 0) continue;
|
|
4250
|
+
const message = extractNormalizedRemoteMessage(payload);
|
|
4251
|
+
if (message !== void 0) return message;
|
|
4247
4252
|
}
|
|
4248
4253
|
};
|
|
4249
4254
|
const resolvePrimaryCode = (error) => {
|
|
@@ -4306,36 +4311,306 @@ const presentCatalogFailureError = (error, options) => {
|
|
|
4306
4311
|
};
|
|
4307
4312
|
};
|
|
4308
4313
|
|
|
4314
|
+
//#endregion
|
|
4315
|
+
//#region src/output/envelope.ts
|
|
4316
|
+
const createEnvelopeBuilder = (deps = {}) => {
|
|
4317
|
+
const createRequestId = deps.createRequestId ?? randomUUID;
|
|
4318
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
4319
|
+
const toMeta = (context) => {
|
|
4320
|
+
const base = { command: context.command };
|
|
4321
|
+
if (context.pagination !== void 0) return {
|
|
4322
|
+
...base,
|
|
4323
|
+
pagination: context.pagination,
|
|
4324
|
+
...context.includeDebug === true ? {
|
|
4325
|
+
entity: context.entity ?? null,
|
|
4326
|
+
requestId: createRequestId(),
|
|
4327
|
+
timestamp: now().toISOString()
|
|
4328
|
+
} : {}
|
|
4329
|
+
};
|
|
4330
|
+
return {
|
|
4331
|
+
...base,
|
|
4332
|
+
...context.includeDebug === true ? {
|
|
4333
|
+
entity: context.entity ?? null,
|
|
4334
|
+
requestId: createRequestId(),
|
|
4335
|
+
timestamp: now().toISOString()
|
|
4336
|
+
} : {}
|
|
4337
|
+
};
|
|
4338
|
+
};
|
|
4339
|
+
return {
|
|
4340
|
+
error: (error, context) => {
|
|
4341
|
+
return {
|
|
4342
|
+
data: null,
|
|
4343
|
+
error: presentRuntimeErrorPayload(error, {
|
|
4344
|
+
...context.diagnostics === void 0 ? {} : { contextDiagnostics: context.diagnostics },
|
|
4345
|
+
includeDebug: context.includeDebug === true
|
|
4346
|
+
}),
|
|
4347
|
+
meta: toMeta(context),
|
|
4348
|
+
next_actions: context.nextActions ?? [],
|
|
4349
|
+
ok: false
|
|
4350
|
+
};
|
|
4351
|
+
},
|
|
4352
|
+
parseError: (payload, context) => {
|
|
4353
|
+
return {
|
|
4354
|
+
data: null,
|
|
4355
|
+
error: payload,
|
|
4356
|
+
meta: toMeta(context),
|
|
4357
|
+
next_actions: context.nextActions ?? [],
|
|
4358
|
+
ok: false
|
|
4359
|
+
};
|
|
4360
|
+
},
|
|
4361
|
+
success: (data, context) => {
|
|
4362
|
+
return {
|
|
4363
|
+
data,
|
|
4364
|
+
error: null,
|
|
4365
|
+
meta: toMeta(context),
|
|
4366
|
+
next_actions: context.nextActions ?? [],
|
|
4367
|
+
ok: true
|
|
4368
|
+
};
|
|
4369
|
+
}
|
|
4370
|
+
};
|
|
4371
|
+
};
|
|
4372
|
+
|
|
4373
|
+
//#endregion
|
|
4374
|
+
//#region src/output/manager.ts
|
|
4375
|
+
const toJson = (value) => {
|
|
4376
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
4377
|
+
};
|
|
4378
|
+
const toMinimalEnvelope = (envelope) => {
|
|
4379
|
+
return {
|
|
4380
|
+
data: envelope.data,
|
|
4381
|
+
error: envelope.error,
|
|
4382
|
+
ok: envelope.ok
|
|
4383
|
+
};
|
|
4384
|
+
};
|
|
4385
|
+
const mergeNextActions = (recovery, contextActions) => {
|
|
4386
|
+
const merged = [...recovery === void 0 || recovery === null ? [] : [recovery], ...contextActions ?? []];
|
|
4387
|
+
const deduped = [];
|
|
4388
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4389
|
+
for (const action of merged) {
|
|
4390
|
+
const key = `${action.id}::${action.command}`;
|
|
4391
|
+
if (seen.has(key)) continue;
|
|
4392
|
+
seen.add(key);
|
|
4393
|
+
deduped.push(action);
|
|
4394
|
+
}
|
|
4395
|
+
return deduped;
|
|
4396
|
+
};
|
|
4397
|
+
var OutputManager = class {
|
|
4398
|
+
#envelopeBuilder;
|
|
4399
|
+
#mode;
|
|
4400
|
+
#debug = false;
|
|
4401
|
+
#stderr;
|
|
4402
|
+
#stdout;
|
|
4403
|
+
constructor(deps = {}) {
|
|
4404
|
+
this.#stderr = deps.stderr ?? process.stderr;
|
|
4405
|
+
this.#stdout = deps.stdout ?? process.stdout;
|
|
4406
|
+
this.#mode = "json";
|
|
4407
|
+
this.#envelopeBuilder = createEnvelopeBuilder({
|
|
4408
|
+
...deps.createRequestId === void 0 ? {} : { createRequestId: deps.createRequestId },
|
|
4409
|
+
...deps.now === void 0 ? {} : { now: deps.now }
|
|
4410
|
+
});
|
|
4411
|
+
}
|
|
4412
|
+
configure(options) {
|
|
4413
|
+
this.#mode = options.quiet ? "quiet" : "json";
|
|
4414
|
+
this.#debug = options.debug;
|
|
4415
|
+
}
|
|
4416
|
+
get mode() {
|
|
4417
|
+
return this.#mode;
|
|
4418
|
+
}
|
|
4419
|
+
get debug() {
|
|
4420
|
+
return this.#debug;
|
|
4421
|
+
}
|
|
4422
|
+
error(error, options) {
|
|
4423
|
+
const envelope = this.#envelopeBuilder.error(error, {
|
|
4424
|
+
...options,
|
|
4425
|
+
includeDebug: this.#debug,
|
|
4426
|
+
nextActions: mergeNextActions(appErrorMeta(error).recovery, options.nextActions)
|
|
4427
|
+
});
|
|
4428
|
+
if (this.#mode === "json") {
|
|
4429
|
+
this.#stdout.write(toJson(envelope));
|
|
4430
|
+
return envelope;
|
|
4431
|
+
}
|
|
4432
|
+
this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
|
|
4433
|
+
return envelope;
|
|
4434
|
+
}
|
|
4435
|
+
parseError(payload, options) {
|
|
4436
|
+
const envelope = this.#envelopeBuilder.parseError(payload, {
|
|
4437
|
+
...options,
|
|
4438
|
+
includeDebug: this.#debug
|
|
4439
|
+
});
|
|
4440
|
+
if (this.#mode === "json") {
|
|
4441
|
+
this.#stdout.write(toJson(envelope));
|
|
4442
|
+
return envelope;
|
|
4443
|
+
}
|
|
4444
|
+
this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
|
|
4445
|
+
return envelope;
|
|
4446
|
+
}
|
|
4447
|
+
info(message) {
|
|
4448
|
+
if (this.#debug) this.#stderr.write(`${message}\n`);
|
|
4449
|
+
}
|
|
4450
|
+
success(data, options) {
|
|
4451
|
+
const envelope = this.#envelopeBuilder.success(data, {
|
|
4452
|
+
...options,
|
|
4453
|
+
includeDebug: this.#debug
|
|
4454
|
+
});
|
|
4455
|
+
if (this.#mode === "json") {
|
|
4456
|
+
this.#stdout.write(toJson(envelope));
|
|
4457
|
+
return;
|
|
4458
|
+
}
|
|
4459
|
+
this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
|
|
4460
|
+
}
|
|
4461
|
+
writeStdout(chunk) {
|
|
4462
|
+
this.#stdout.write(chunk);
|
|
4463
|
+
}
|
|
4464
|
+
};
|
|
4465
|
+
|
|
4466
|
+
//#endregion
|
|
4467
|
+
//#region src/shared/exit-codes.ts
|
|
4468
|
+
const EXIT_CODE = {
|
|
4469
|
+
authFailed: 4,
|
|
4470
|
+
authRequired: 3,
|
|
4471
|
+
contractMismatch: 8,
|
|
4472
|
+
internal: 9,
|
|
4473
|
+
notFound: 5,
|
|
4474
|
+
rateLimit: 6,
|
|
4475
|
+
remote: 7,
|
|
4476
|
+
success: 0,
|
|
4477
|
+
validation: 2
|
|
4478
|
+
};
|
|
4479
|
+
const exitCodeForError = (error) => {
|
|
4480
|
+
const { category, code } = appErrorMeta(error);
|
|
4481
|
+
switch (category) {
|
|
4482
|
+
case ERROR_CATEGORY.auth:
|
|
4483
|
+
if (code === ERROR_CODE.authRequired) return EXIT_CODE.authRequired;
|
|
4484
|
+
return EXIT_CODE.authFailed;
|
|
4485
|
+
case ERROR_CATEGORY.notFound: return EXIT_CODE.notFound;
|
|
4486
|
+
case ERROR_CATEGORY.rateLimit: return EXIT_CODE.rateLimit;
|
|
4487
|
+
case ERROR_CATEGORY.remote:
|
|
4488
|
+
case ERROR_CATEGORY.transport:
|
|
4489
|
+
case ERROR_CATEGORY.authorization: return EXIT_CODE.remote;
|
|
4490
|
+
case ERROR_CATEGORY.contractMismatch: return EXIT_CODE.contractMismatch;
|
|
4491
|
+
case ERROR_CATEGORY.validation: return EXIT_CODE.validation;
|
|
4492
|
+
case ERROR_CATEGORY.internal: return EXIT_CODE.internal;
|
|
4493
|
+
}
|
|
4494
|
+
};
|
|
4495
|
+
|
|
4496
|
+
//#endregion
|
|
4497
|
+
//#region src/commands/auth.ts
|
|
4498
|
+
const runAuthLoginCommand = async (context, options) => {
|
|
4499
|
+
const loginOptions = (() => {
|
|
4500
|
+
if (options.mode === "apiKey") return {
|
|
4501
|
+
apiKey: options.apiKey,
|
|
4502
|
+
mode: "apiKey"
|
|
4503
|
+
};
|
|
4504
|
+
return {
|
|
4505
|
+
mode: "device",
|
|
4506
|
+
...options.onPending === void 0 ? {} : { onPending: options.onPending }
|
|
4507
|
+
};
|
|
4508
|
+
})();
|
|
4509
|
+
return context.services.auth.login(loginOptions);
|
|
4510
|
+
};
|
|
4511
|
+
const runAuthStatusCommand = async (context) => {
|
|
4512
|
+
return context.services.auth.status(context.apiKeyOverride);
|
|
4513
|
+
};
|
|
4514
|
+
const runAuthLogoutCommand = async (context) => {
|
|
4515
|
+
return context.services.auth.logout();
|
|
4516
|
+
};
|
|
4517
|
+
|
|
4309
4518
|
//#endregion
|
|
4310
4519
|
//#region src/commands/server-context.ts
|
|
4520
|
+
const formatCandidateSelectors = (profile, path) => {
|
|
4521
|
+
return profile.orgs.flatMap((org) => {
|
|
4522
|
+
return org.servers.filter((server) => server.path === path).map((server) => `${org.orgSlug}/${server.path}`);
|
|
4523
|
+
});
|
|
4524
|
+
};
|
|
4525
|
+
const parseQualifiedSelector = (selector) => {
|
|
4526
|
+
const firstSlash = selector.indexOf("/");
|
|
4527
|
+
if (firstSlash <= 0 || firstSlash >= selector.length - 1) return null;
|
|
4528
|
+
return {
|
|
4529
|
+
orgSlug: selector.slice(0, firstSlash),
|
|
4530
|
+
serverPath: selector.slice(firstSlash + 1)
|
|
4531
|
+
};
|
|
4532
|
+
};
|
|
4533
|
+
const findByOrgAndPath = (profile, orgSlug, path) => {
|
|
4534
|
+
for (const org of profile.orgs) {
|
|
4535
|
+
if (org.orgSlug !== orgSlug) continue;
|
|
4536
|
+
const server = org.servers.find((item) => item.path === path);
|
|
4537
|
+
if (server !== void 0) return {
|
|
4538
|
+
orgSlug: org.orgSlug,
|
|
4539
|
+
server
|
|
4540
|
+
};
|
|
4541
|
+
}
|
|
4542
|
+
return null;
|
|
4543
|
+
};
|
|
4311
4544
|
const resolveServerState = async (context) => {
|
|
4312
4545
|
const apiKeyResult = await context.services.auth.resolveApiKey(context.apiKeyOverride);
|
|
4313
4546
|
if (Result.isError(apiKeyResult)) return apiKeyResult;
|
|
4314
|
-
const
|
|
4315
|
-
if (Result.isError(
|
|
4547
|
+
const accountResult = await context.services.account.fetchAccount(apiKeyResult.value);
|
|
4548
|
+
if (Result.isError(accountResult)) return accountResult;
|
|
4316
4549
|
return Result.ok({
|
|
4317
4550
|
apiKey: apiKeyResult.value,
|
|
4318
|
-
|
|
4551
|
+
profile: accountResult.value
|
|
4319
4552
|
});
|
|
4320
4553
|
};
|
|
4321
|
-
const findServerByPath = (
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4554
|
+
const findServerByPath = (profile, selector, options) => {
|
|
4555
|
+
if (options.orgSlug !== void 0) {
|
|
4556
|
+
const scoped = findByOrgAndPath(profile, options.orgSlug, selector);
|
|
4557
|
+
if (scoped !== null) return Result.ok({
|
|
4558
|
+
orgSlug: scoped.orgSlug,
|
|
4559
|
+
server: scoped.server
|
|
4560
|
+
});
|
|
4561
|
+
return Result.err(new NotFoundError({
|
|
4562
|
+
message: `Server "${selector}" not found in organization "${options.orgSlug}"`,
|
|
4563
|
+
resource: `${options.orgSlug}/${selector}`
|
|
4564
|
+
}));
|
|
4565
|
+
}
|
|
4566
|
+
const pathMatches = formatCandidateSelectors(profile, selector);
|
|
4567
|
+
if (pathMatches.length === 1) {
|
|
4568
|
+
const [candidate] = pathMatches;
|
|
4569
|
+
if (candidate === void 0) return Result.err(new NotFoundError({
|
|
4570
|
+
message: `Server "${selector}" not found`,
|
|
4571
|
+
resource: selector
|
|
4572
|
+
}));
|
|
4573
|
+
const qualified = parseQualifiedSelector(candidate);
|
|
4574
|
+
if (qualified === null) return Result.err(new NotFoundError({
|
|
4575
|
+
message: `Server "${selector}" not found`,
|
|
4576
|
+
resource: selector
|
|
4577
|
+
}));
|
|
4578
|
+
const resolved = findByOrgAndPath(profile, qualified.orgSlug, qualified.serverPath);
|
|
4579
|
+
if (resolved !== null) return Result.ok(resolved);
|
|
4580
|
+
}
|
|
4581
|
+
if (pathMatches.length > 1) {
|
|
4582
|
+
const sortedCandidates = pathMatches.toSorted();
|
|
4583
|
+
const [firstCandidate] = sortedCandidates;
|
|
4584
|
+
if (firstCandidate !== void 0) {
|
|
4585
|
+
const firstCandidateParsed = parseQualifiedSelector(firstCandidate);
|
|
4586
|
+
const message = options.selectorKind === "invoke" ? `Server "${selector}" is ambiguous across organizations (${sortedCandidates.join(", ")}). Re-run with --org <org-slug>.` : `Server "${selector}" is ambiguous across organizations (${sortedCandidates.join(", ")}). Use a qualified selector like "${firstCandidate}".`;
|
|
4587
|
+
const recoveryCommand = options.selectorKind === "invoke" ? options.toolName === void 0 ? "ogment invoke --help" : firstCandidateParsed === null ? "ogment invoke --help" : `ogment invoke --org ${firstCandidateParsed.orgSlug} ${selector} ${options.toolName}` : `ogment catalog ${firstCandidate}`;
|
|
4588
|
+
return Result.err(new ValidationError({
|
|
4589
|
+
message,
|
|
4590
|
+
recovery: { command: recoveryCommand }
|
|
4591
|
+
}));
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
const qualifiedSelector = parseQualifiedSelector(selector);
|
|
4595
|
+
if (qualifiedSelector !== null) {
|
|
4596
|
+
const qualifiedMatch = findByOrgAndPath(profile, qualifiedSelector.orgSlug, qualifiedSelector.serverPath);
|
|
4597
|
+
if (qualifiedMatch !== null) return Result.ok(qualifiedMatch);
|
|
4598
|
+
}
|
|
4599
|
+
return Result.err(new NotFoundError({
|
|
4600
|
+
message: `Server "${selector}" not found`,
|
|
4601
|
+
resource: selector
|
|
4326
4602
|
}));
|
|
4327
|
-
return Result.ok(server);
|
|
4328
4603
|
};
|
|
4329
4604
|
|
|
4330
4605
|
//#endregion
|
|
4331
4606
|
//#region src/commands/catalog.ts
|
|
4332
|
-
const toServerSummary = (
|
|
4607
|
+
const toServerSummary = (target, toolCount) => {
|
|
4333
4608
|
return {
|
|
4334
4609
|
capabilities: [],
|
|
4335
|
-
description: server.description,
|
|
4336
|
-
name: server.name,
|
|
4337
|
-
orgSlug:
|
|
4338
|
-
serverId: server.path,
|
|
4610
|
+
description: target.server.description,
|
|
4611
|
+
name: target.server.name,
|
|
4612
|
+
orgSlug: target.orgSlug,
|
|
4613
|
+
serverId: target.server.path,
|
|
4339
4614
|
toolCount,
|
|
4340
4615
|
version: null
|
|
4341
4616
|
};
|
|
@@ -4343,7 +4618,7 @@ const toServerSummary = (server, toolCount) => {
|
|
|
4343
4618
|
const toToolSummaries = (tools) => {
|
|
4344
4619
|
return tools.map((tool) => {
|
|
4345
4620
|
return {
|
|
4346
|
-
description: tool.description,
|
|
4621
|
+
description: tool.description ?? null,
|
|
4347
4622
|
name: tool.name
|
|
4348
4623
|
};
|
|
4349
4624
|
});
|
|
@@ -4351,7 +4626,7 @@ const toToolSummaries = (tools) => {
|
|
|
4351
4626
|
const listServerTools = async (context, apiKey, server) => {
|
|
4352
4627
|
return context.services.mcp.listTools({
|
|
4353
4628
|
orgSlug: server.orgSlug,
|
|
4354
|
-
serverPath: server.path
|
|
4629
|
+
serverPath: server.server.path
|
|
4355
4630
|
}, apiKey);
|
|
4356
4631
|
};
|
|
4357
4632
|
const TOOL_COUNT_CONCURRENCY = 4;
|
|
@@ -4359,7 +4634,7 @@ const toCatalogServerFailure = (server, error, includeDebug) => {
|
|
|
4359
4634
|
return {
|
|
4360
4635
|
error: presentCatalogFailureError(error, { includeDebug }),
|
|
4361
4636
|
orgSlug: server.orgSlug,
|
|
4362
|
-
serverId: server.path
|
|
4637
|
+
serverId: server.server.path
|
|
4363
4638
|
};
|
|
4364
4639
|
};
|
|
4365
4640
|
const mapWithConcurrency = async (items, concurrency, mapItem) => {
|
|
@@ -4384,11 +4659,19 @@ const mapWithConcurrency = async (items, concurrency, mapItem) => {
|
|
|
4384
4659
|
const runCatalogCommand = async (context, options) => {
|
|
4385
4660
|
const stateResult = await resolveServerState(context);
|
|
4386
4661
|
if (Result.isError(stateResult)) return stateResult;
|
|
4387
|
-
let targetServers = stateResult.value.
|
|
4662
|
+
let targetServers = stateResult.value.profile.orgs.flatMap((org) => {
|
|
4663
|
+
return org.servers.map((server) => ({
|
|
4664
|
+
orgSlug: org.orgSlug,
|
|
4665
|
+
server
|
|
4666
|
+
}));
|
|
4667
|
+
});
|
|
4388
4668
|
if (options.serverId !== void 0) {
|
|
4389
|
-
const serverResult = findServerByPath(stateResult.value.
|
|
4669
|
+
const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
|
|
4390
4670
|
if (Result.isError(serverResult)) return serverResult;
|
|
4391
|
-
targetServers = [
|
|
4671
|
+
targetServers = [{
|
|
4672
|
+
orgSlug: serverResult.value.orgSlug,
|
|
4673
|
+
server: serverResult.value.server
|
|
4674
|
+
}];
|
|
4392
4675
|
}
|
|
4393
4676
|
const serverSummaries = await mapWithConcurrency(targetServers, TOOL_COUNT_CONCURRENCY, async (server) => {
|
|
4394
4677
|
return {
|
|
@@ -4433,21 +4716,29 @@ const runCatalogCommand = async (context, options) => {
|
|
|
4433
4716
|
const runCatalogToolsCommand = async (context, options) => {
|
|
4434
4717
|
const stateResult = await resolveServerState(context);
|
|
4435
4718
|
if (Result.isError(stateResult)) return stateResult;
|
|
4436
|
-
const serverResult = findServerByPath(stateResult.value.
|
|
4719
|
+
const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
|
|
4437
4720
|
if (Result.isError(serverResult)) return serverResult;
|
|
4438
|
-
const
|
|
4721
|
+
const targetServer = {
|
|
4722
|
+
orgSlug: serverResult.value.orgSlug,
|
|
4723
|
+
server: serverResult.value.server
|
|
4724
|
+
};
|
|
4725
|
+
const toolsResult = await listServerTools(context, stateResult.value.apiKey, targetServer);
|
|
4439
4726
|
if (Result.isError(toolsResult)) return toolsResult;
|
|
4440
4727
|
return Result.ok({
|
|
4441
|
-
server: toServerSummary(
|
|
4728
|
+
server: toServerSummary(targetServer, toolsResult.value.length),
|
|
4442
4729
|
tools: toToolSummaries(toolsResult.value)
|
|
4443
4730
|
});
|
|
4444
4731
|
};
|
|
4445
4732
|
const runCatalogToolDetailsCommand = async (context, options) => {
|
|
4446
4733
|
const stateResult = await resolveServerState(context);
|
|
4447
4734
|
if (Result.isError(stateResult)) return stateResult;
|
|
4448
|
-
const serverResult = findServerByPath(stateResult.value.
|
|
4735
|
+
const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
|
|
4449
4736
|
if (Result.isError(serverResult)) return serverResult;
|
|
4450
|
-
const
|
|
4737
|
+
const targetServer = {
|
|
4738
|
+
orgSlug: serverResult.value.orgSlug,
|
|
4739
|
+
server: serverResult.value.server
|
|
4740
|
+
};
|
|
4741
|
+
const toolsResult = await listServerTools(context, stateResult.value.apiKey, targetServer);
|
|
4451
4742
|
if (Result.isError(toolsResult)) return toolsResult;
|
|
4452
4743
|
const tool = toolsResult.value.find((item) => item.name === options.toolName);
|
|
4453
4744
|
if (tool === void 0) return Result.err(new NotFoundError({
|
|
@@ -4455,18 +4746,18 @@ const runCatalogToolDetailsCommand = async (context, options) => {
|
|
|
4455
4746
|
resource: options.toolName
|
|
4456
4747
|
}));
|
|
4457
4748
|
return Result.ok({
|
|
4458
|
-
description: tool.description,
|
|
4749
|
+
description: tool.description ?? null,
|
|
4459
4750
|
inputSchema: tool.inputSchema,
|
|
4460
4751
|
name: tool.name,
|
|
4461
4752
|
outputSchema: tool.outputSchema ?? null,
|
|
4462
|
-
server: toServerSummary(
|
|
4753
|
+
server: toServerSummary(targetServer, toolsResult.value.length)
|
|
4463
4754
|
});
|
|
4464
4755
|
};
|
|
4465
4756
|
|
|
4466
4757
|
//#endregion
|
|
4467
4758
|
//#region src/commands/invoke.ts
|
|
4468
4759
|
const mapInputFileReadError = (inputFile, cause) => {
|
|
4469
|
-
const code =
|
|
4760
|
+
const code = cause instanceof Error && "code" in cause && typeof cause.code === "string" ? cause.code : void 0;
|
|
4470
4761
|
if (code === "ENOENT") return new ValidationError({ message: `Input file not found: ${inputFile}` });
|
|
4471
4762
|
if (code === "EACCES" || code === "EPERM") return new ValidationError({ message: `Input file is not readable: ${inputFile}` });
|
|
4472
4763
|
if (code === "EISDIR") return new ValidationError({ message: `Input path must be a file: ${inputFile}` });
|
|
@@ -4475,62 +4766,22 @@ const mapInputFileReadError = (inputFile, cause) => {
|
|
|
4475
4766
|
message: `Failed to read input file: ${inputFile}`
|
|
4476
4767
|
});
|
|
4477
4768
|
};
|
|
4478
|
-
const parseToolErrorDetails = (payload) => {
|
|
4479
|
-
if (typeof payload === "string") {
|
|
4480
|
-
const trimmed = payload.trim();
|
|
4481
|
-
if (trimmed.length === 0) return {};
|
|
4482
|
-
const parseJsonDetails = (raw) => {
|
|
4483
|
-
const parsed = parseJsonUnknown(raw, "tool error payload");
|
|
4484
|
-
if (Result.isError(parsed)) return;
|
|
4485
|
-
const details = parseToolErrorDetails(parsed.value);
|
|
4486
|
-
if (details.message !== void 0 || details.mcpCode !== void 0 || details.mcpData !== void 0) return details;
|
|
4487
|
-
};
|
|
4488
|
-
const fromFullJson = parseJsonDetails(trimmed);
|
|
4489
|
-
if (fromFullJson !== void 0) return fromFullJson;
|
|
4490
|
-
const firstBraceIndex = trimmed.indexOf("{");
|
|
4491
|
-
if (firstBraceIndex > 0) {
|
|
4492
|
-
const fromEmbeddedJson = parseJsonDetails(trimmed.slice(firstBraceIndex));
|
|
4493
|
-
if (fromEmbeddedJson !== void 0) return fromEmbeddedJson;
|
|
4494
|
-
}
|
|
4495
|
-
return { message: trimmed };
|
|
4496
|
-
}
|
|
4497
|
-
if (typeof payload !== "object" || payload === null) return {};
|
|
4498
|
-
if (!isRecord$1(payload)) return {};
|
|
4499
|
-
const record = payload;
|
|
4500
|
-
const directCode = record["code"];
|
|
4501
|
-
const directMessage = record["message"];
|
|
4502
|
-
if (typeof directCode === "number" || typeof directMessage === "string") return {
|
|
4503
|
-
...typeof directCode === "number" ? { mcpCode: directCode } : {},
|
|
4504
|
-
...typeof directMessage === "string" ? { message: directMessage } : {},
|
|
4505
|
-
...Object.hasOwn(record, "data") ? { mcpData: record["data"] } : {}
|
|
4506
|
-
};
|
|
4507
|
-
const nestedError = record["error"];
|
|
4508
|
-
if (!isRecord$1(nestedError)) return {};
|
|
4509
|
-
const nestedRecord = nestedError;
|
|
4510
|
-
return {
|
|
4511
|
-
...typeof nestedRecord["code"] === "number" ? { mcpCode: nestedRecord["code"] } : {},
|
|
4512
|
-
...typeof nestedRecord["message"] === "string" ? { message: nestedRecord["message"] } : {},
|
|
4513
|
-
...Object.hasOwn(nestedRecord, "data") ? { mcpData: nestedRecord["data"] } : {}
|
|
4514
|
-
};
|
|
4515
|
-
};
|
|
4516
|
-
const parseTarget = (target) => {
|
|
4517
|
-
const separatorIndex = target.lastIndexOf("/");
|
|
4518
|
-
if (separatorIndex <= 0 || separatorIndex >= target.length - 1) return Result.err(new ValidationError({
|
|
4519
|
-
details: target,
|
|
4520
|
-
message: "Invoke target must be in format <server-id>/<tool-name>"
|
|
4521
|
-
}));
|
|
4522
|
-
const serverId = target.slice(0, separatorIndex);
|
|
4523
|
-
const toolName = target.slice(separatorIndex + 1);
|
|
4524
|
-
return Result.ok({
|
|
4525
|
-
serverId,
|
|
4526
|
-
toolName
|
|
4527
|
-
});
|
|
4528
|
-
};
|
|
4529
4769
|
const parseInputObject = (raw, context) => {
|
|
4530
|
-
const parsed =
|
|
4770
|
+
const parsed = parseJsonValue(raw, context);
|
|
4531
4771
|
if (Result.isError(parsed)) return parsed;
|
|
4532
|
-
|
|
4533
|
-
return Result.
|
|
4772
|
+
const parsedValue = parsed.value;
|
|
4773
|
+
if (!isJsonObject(parsedValue)) return Result.err(new ValidationError({ message: "Invoke input must be a JSON object" }));
|
|
4774
|
+
return Result.ok(parsedValue);
|
|
4775
|
+
};
|
|
4776
|
+
const toToolCallStructuredContent = (result) => {
|
|
4777
|
+
if (result.structuredContent !== void 0) return toJsonValue(result.structuredContent);
|
|
4778
|
+
const firstContent = (Array.isArray(result.content) ? result.content : [])[0];
|
|
4779
|
+
if (firstContent !== void 0 && firstContent.type === "text" && typeof firstContent.text === "string") {
|
|
4780
|
+
const parsedText = parseJsonValue(firstContent.text, "MCP text content");
|
|
4781
|
+
if (Result.isError(parsedText)) return firstContent.text;
|
|
4782
|
+
return parsedText.value;
|
|
4783
|
+
}
|
|
4784
|
+
return toJsonValue(result);
|
|
4534
4785
|
};
|
|
4535
4786
|
const readStdin = async () => {
|
|
4536
4787
|
return Result.tryPromise({
|
|
@@ -4578,55 +4829,57 @@ const parseInvokeArgs = async (options, deps) => {
|
|
|
4578
4829
|
return parseInputObject(options.input, "--input");
|
|
4579
4830
|
};
|
|
4580
4831
|
const runInvokeCommand = async (context, options, deps = {}) => {
|
|
4581
|
-
const targetResult = parseTarget(options.target);
|
|
4582
|
-
if (Result.isError(targetResult)) return targetResult;
|
|
4583
4832
|
const argsResult = await parseInvokeArgs(options, deps);
|
|
4584
4833
|
if (Result.isError(argsResult)) return argsResult;
|
|
4585
4834
|
const stateResult = await resolveServerState(context);
|
|
4586
4835
|
if (Result.isError(stateResult)) return stateResult;
|
|
4587
|
-
const serverResult = findServerByPath(stateResult.value.
|
|
4836
|
+
const serverResult = findServerByPath(stateResult.value.profile, options.serverId, {
|
|
4837
|
+
...options.orgSlug === void 0 ? {} : { orgSlug: options.orgSlug },
|
|
4838
|
+
selectorKind: "invoke",
|
|
4839
|
+
toolName: options.toolName
|
|
4840
|
+
});
|
|
4588
4841
|
if (Result.isError(serverResult)) return serverResult;
|
|
4589
4842
|
const mcpTarget = {
|
|
4590
4843
|
orgSlug: serverResult.value.orgSlug,
|
|
4591
|
-
serverPath: serverResult.value.path
|
|
4844
|
+
serverPath: serverResult.value.server.path
|
|
4592
4845
|
};
|
|
4593
|
-
const callResult = await context.services.mcp.callTool(mcpTarget, stateResult.value.apiKey,
|
|
4846
|
+
const callResult = await context.services.mcp.callTool(mcpTarget, stateResult.value.apiKey, options.toolName, argsResult.value);
|
|
4594
4847
|
if (Result.isError(callResult)) {
|
|
4595
4848
|
if (callResult.error._tag === "RemoteRequestError") {
|
|
4596
4849
|
const toolsResult = await context.services.mcp.listTools(mcpTarget, stateResult.value.apiKey);
|
|
4597
4850
|
if (Result.isOk(toolsResult)) {
|
|
4598
|
-
if (!toolsResult.value.some((tool) => tool.name ===
|
|
4599
|
-
message: `Tool "${
|
|
4600
|
-
resource:
|
|
4851
|
+
if (!toolsResult.value.some((tool) => tool.name === options.toolName)) return Result.err(new NotFoundError({
|
|
4852
|
+
message: `Tool "${options.toolName}" not found`,
|
|
4853
|
+
resource: options.toolName
|
|
4601
4854
|
}));
|
|
4602
4855
|
}
|
|
4603
4856
|
}
|
|
4604
4857
|
return callResult;
|
|
4605
4858
|
}
|
|
4859
|
+
const structuredContent = toToolCallStructuredContent(callResult.value);
|
|
4606
4860
|
if (callResult.value.isError) {
|
|
4607
|
-
const details =
|
|
4861
|
+
const details = parseRemoteErrorDetails(structuredContent);
|
|
4608
4862
|
return Result.err(new RemoteRequestError({
|
|
4609
4863
|
...details.mcpCode === void 0 ? {} : { mcpCode: details.mcpCode },
|
|
4610
|
-
...details.
|
|
4864
|
+
...details.data === void 0 ? {} : { mcpData: details.data },
|
|
4611
4865
|
message: details.message ?? "MCP tool call returned an error result",
|
|
4612
4866
|
operation: "tools/call",
|
|
4613
|
-
raw:
|
|
4867
|
+
raw: structuredContent,
|
|
4614
4868
|
retryable: false,
|
|
4615
4869
|
source: "mcp_jsonrpc"
|
|
4616
4870
|
}));
|
|
4617
4871
|
}
|
|
4618
4872
|
return Result.ok({
|
|
4619
|
-
result:
|
|
4620
|
-
serverId:
|
|
4621
|
-
toolName:
|
|
4873
|
+
result: structuredContent,
|
|
4874
|
+
serverId: options.serverId,
|
|
4875
|
+
toolName: options.toolName
|
|
4622
4876
|
});
|
|
4623
4877
|
};
|
|
4624
4878
|
|
|
4625
4879
|
//#endregion
|
|
4626
4880
|
//#region src/commands/status.ts
|
|
4627
4881
|
const runStatusCommand = async (options, deps) => {
|
|
4628
|
-
|
|
4629
|
-
return Result.ok(payload);
|
|
4882
|
+
return deps.infoService.collect(options.apiKeyOverride, { includeDebug: options.debug });
|
|
4630
4883
|
};
|
|
4631
4884
|
|
|
4632
4885
|
//#endregion
|
|
@@ -4650,8 +4903,8 @@ const deriveType = (schema) => {
|
|
|
4650
4903
|
if (isRecord(schema["properties"])) return "object";
|
|
4651
4904
|
if (schema["items"] !== void 0) return "array";
|
|
4652
4905
|
};
|
|
4653
|
-
const baseScalarExample = (
|
|
4654
|
-
switch (
|
|
4906
|
+
const baseScalarExample = (_typeName) => {
|
|
4907
|
+
switch (_typeName) {
|
|
4655
4908
|
case "string": return EXAMPLE_PLACEHOLDER;
|
|
4656
4909
|
case "integer": return EXAMPLE_PLACEHOLDER;
|
|
4657
4910
|
case "number": return EXAMPLE_PLACEHOLDER;
|
|
@@ -4726,11 +4979,34 @@ const cliCommands = {
|
|
|
4726
4979
|
return `ogment ${scope} --help`;
|
|
4727
4980
|
},
|
|
4728
4981
|
invoke: {
|
|
4729
|
-
command: (
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4982
|
+
command: (serverId, toolName, orgSlug) => [
|
|
4983
|
+
"ogment invoke",
|
|
4984
|
+
...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
|
|
4985
|
+
serverId,
|
|
4986
|
+
toolName
|
|
4987
|
+
].join(" "),
|
|
4988
|
+
inlineJson: (serverId, toolName, orgSlug) => [
|
|
4989
|
+
"ogment invoke",
|
|
4990
|
+
...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
|
|
4991
|
+
serverId,
|
|
4992
|
+
toolName,
|
|
4993
|
+
"--input <json>"
|
|
4994
|
+
].join(" "),
|
|
4995
|
+
stdin: (serverId, toolName, orgSlug) => [
|
|
4996
|
+
"ogment invoke",
|
|
4997
|
+
...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
|
|
4998
|
+
serverId,
|
|
4999
|
+
toolName,
|
|
5000
|
+
"--input -"
|
|
5001
|
+
].join(" "),
|
|
5002
|
+
withInputValue: (serverId, toolName, value, orgSlug) => {
|
|
5003
|
+
return [
|
|
5004
|
+
"ogment invoke",
|
|
5005
|
+
...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
|
|
5006
|
+
serverId,
|
|
5007
|
+
toolName,
|
|
5008
|
+
`--input ${value}`
|
|
5009
|
+
].join(" ");
|
|
4734
5010
|
}
|
|
4735
5011
|
},
|
|
4736
5012
|
root: {
|
|
@@ -4743,7 +5019,7 @@ const cliCommands = {
|
|
|
4743
5019
|
"catalog",
|
|
4744
5020
|
"catalog <server-id>",
|
|
4745
5021
|
"catalog <server-id> <tool-name>",
|
|
4746
|
-
"invoke <server-id
|
|
5022
|
+
"invoke <server-id> <tool-name>",
|
|
4747
5023
|
"status"
|
|
4748
5024
|
];
|
|
4749
5025
|
},
|
|
@@ -4796,7 +5072,7 @@ const nextActionsForCatalogSummary = (payload, context) => {
|
|
|
4796
5072
|
if (targetServer !== void 0) actions.push(nextAction("inspect_tools", "Inspect tools", cliCommands.catalog.server(targetServer.serverId), `${targetServer.serverId} has ${targetServer.toolCount} available tools.`, "if_tool_count_gt_0"));
|
|
4797
5073
|
if (context.nextCursor !== null) actions.push(nextAction("next_catalog_page", "Load next page", cliCommands.catalog.summary({
|
|
4798
5074
|
cursor: context.nextCursor,
|
|
4799
|
-
limit: context.limit
|
|
5075
|
+
...context.limit === null ? {} : { limit: context.limit }
|
|
4800
5076
|
}), `More servers are available after cursor ${context.nextCursor}.`, "if_more_servers"));
|
|
4801
5077
|
return actions;
|
|
4802
5078
|
};
|
|
@@ -4811,7 +5087,7 @@ const toInlineJsonTemplateArgument = (value) => {
|
|
|
4811
5087
|
};
|
|
4812
5088
|
const nextActionsForCatalogToolDetails = (payload, exampleInput) => {
|
|
4813
5089
|
const inputArgument = toInlineJsonTemplateArgument(exampleInput);
|
|
4814
|
-
return [nextAction("invoke_tool", "Invoke this tool", cliCommands.invoke.withInputValue(
|
|
5090
|
+
return [nextAction("invoke_tool", "Invoke this tool", cliCommands.invoke.withInputValue(payload.server.serverId, payload.name, inputArgument), `Replace every ... placeholder with real JSON values, then invoke ${payload.server.serverId} ${payload.name}.`, "after_tool_inspection")];
|
|
4815
5091
|
};
|
|
4816
5092
|
const nextActionsForInvoke = (payload) => {
|
|
4817
5093
|
return [nextAction("inspect_tool", "Inspect tool schema", cliCommands.catalog.tool(payload.serverId, payload.toolName, { example: false }), `Review ${payload.serverId}/${payload.toolName} schema for the next invocation.`, "after_invoke")];
|
|
@@ -4820,15 +5096,12 @@ const nextActionsForStatus = (payload) => {
|
|
|
4820
5096
|
if (!payload.auth.apiKeyPresent) return [nextAction("login", "Authenticate", cliCommands.auth.login(), "Status detected no API key; authenticate first.", "immediate")];
|
|
4821
5097
|
return [nextAction("discover_servers", "Discover servers", cliCommands.catalog.command(), `Connectivity is ${payload.summary.status}; discover available servers.`, "after_status")];
|
|
4822
5098
|
};
|
|
4823
|
-
const runLoginFlow = async (runtime,
|
|
4824
|
-
const { commandOptions, invokedCommand } =
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
},
|
|
4830
|
-
invokedCommand: cliCommands.auth.loginWithApiKeyRedacted()
|
|
4831
|
-
};
|
|
5099
|
+
const runLoginFlow = async (runtime, options) => {
|
|
5100
|
+
const { commandOptions, invokedCommand, mode } = options.mode === "apiKey" ? {
|
|
5101
|
+
commandOptions: options,
|
|
5102
|
+
invokedCommand: cliCommands.auth.loginWithApiKeyRedacted(),
|
|
5103
|
+
mode: "apiKey"
|
|
5104
|
+
} : (() => {
|
|
4832
5105
|
const deviceCommand = cliCommands.auth.login();
|
|
4833
5106
|
return {
|
|
4834
5107
|
commandOptions: {
|
|
@@ -4846,7 +5119,7 @@ const runLoginFlow = async (runtime, mode, apiKey) => {
|
|
|
4846
5119
|
command: deviceCommand,
|
|
4847
5120
|
entity: {
|
|
4848
5121
|
event: "auth_login.pending",
|
|
4849
|
-
mode,
|
|
5122
|
+
mode: "device",
|
|
4850
5123
|
verification: {
|
|
4851
5124
|
userCode,
|
|
4852
5125
|
verificationUri
|
|
@@ -4856,7 +5129,8 @@ const runLoginFlow = async (runtime, mode, apiKey) => {
|
|
|
4856
5129
|
});
|
|
4857
5130
|
}
|
|
4858
5131
|
},
|
|
4859
|
-
invokedCommand: deviceCommand
|
|
5132
|
+
invokedCommand: deviceCommand,
|
|
5133
|
+
mode: "device"
|
|
4860
5134
|
};
|
|
4861
5135
|
})();
|
|
4862
5136
|
const data = ensureSuccess(await runAuthLoginCommand(runtime.context, commandOptions), runtime, {
|
|
@@ -4881,10 +5155,13 @@ const runLoginFlow = async (runtime, mode, apiKey) => {
|
|
|
4881
5155
|
};
|
|
4882
5156
|
const executeAuthLoginInvocation = async (runtime, invocation) => {
|
|
4883
5157
|
if (invocation.apiKey !== void 0) {
|
|
4884
|
-
await runLoginFlow(runtime,
|
|
5158
|
+
await runLoginFlow(runtime, {
|
|
5159
|
+
apiKey: invocation.apiKey,
|
|
5160
|
+
mode: "apiKey"
|
|
5161
|
+
});
|
|
4885
5162
|
return;
|
|
4886
5163
|
}
|
|
4887
|
-
await runLoginFlow(runtime, "device");
|
|
5164
|
+
await runLoginFlow(runtime, { mode: "device" });
|
|
4888
5165
|
};
|
|
4889
5166
|
const executeAuthStatusInvocation = async (runtime) => {
|
|
4890
5167
|
const command = cliCommands.auth.status();
|
|
@@ -4901,144 +5178,177 @@ const executeAuthStatusInvocation = async (runtime) => {
|
|
|
4901
5178
|
const executeAuthLogoutInvocation = async (runtime) => {
|
|
4902
5179
|
const command = cliCommands.auth.logout();
|
|
4903
5180
|
const data = ensureSuccess(await runAuthLogoutCommand(runtime.context), runtime, { command });
|
|
4904
|
-
runtime.output.success(data, {
|
|
4905
|
-
command,
|
|
4906
|
-
entity: {
|
|
4907
|
-
localCredentialsDeleted: data.localCredentialsDeleted,
|
|
4908
|
-
revoked: data.revoked
|
|
4909
|
-
},
|
|
4910
|
-
nextActions: [nextAction("login", "Authenticate again", cliCommands.auth.login(), "Logout completed; authenticate again before further tool calls.", "after_logout")]
|
|
4911
|
-
});
|
|
4912
|
-
};
|
|
4913
|
-
const executeCatalogInvocation = async (runtime, invocation) => {
|
|
4914
|
-
const parsedLimit = invocation.limit;
|
|
4915
|
-
if (invocation.serverId === void 0) {
|
|
4916
|
-
if (invocation.example) throw new ValidationError({
|
|
4917
|
-
details: "--example without <server-id> <tool-name>",
|
|
4918
|
-
message: "Invalid catalog options. --example requires <server-id> <tool-name>.",
|
|
4919
|
-
recovery: { command: cliCommands.catalog.command() }
|
|
4920
|
-
});
|
|
4921
|
-
const command = cliCommands.catalog.summary({
|
|
4922
|
-
cursor: invocation.cursor,
|
|
4923
|
-
limit: parsedLimit
|
|
4924
|
-
});
|
|
4925
|
-
const data = ensureSuccess(await runCatalogCommand(runtime.context, {
|
|
4926
|
-
cursor: invocation.cursor,
|
|
4927
|
-
includeDebug: runtime.output.debug,
|
|
4928
|
-
limit: parsedLimit
|
|
4929
|
-
}), runtime, {
|
|
4930
|
-
command,
|
|
4931
|
-
entity: {
|
|
4932
|
-
cursor: invocation.cursor ?? null,
|
|
4933
|
-
limit: parsedLimit ?? null
|
|
4934
|
-
}
|
|
4935
|
-
});
|
|
4936
|
-
const outputData = {
|
|
4937
|
-
failures: data.failures,
|
|
4938
|
-
servers: data.servers
|
|
4939
|
-
};
|
|
4940
|
-
runtime.output.success(outputData, {
|
|
4941
|
-
command,
|
|
4942
|
-
entity: {
|
|
4943
|
-
cursor: invocation.cursor ?? null,
|
|
4944
|
-
failedServerCount: data.failures.length,
|
|
4945
|
-
limit: parsedLimit ?? null,
|
|
4946
|
-
serverCount: data.servers.length
|
|
4947
|
-
},
|
|
4948
|
-
nextActions: nextActionsForCatalogSummary(outputData, {
|
|
4949
|
-
limit: parsedLimit ?? null,
|
|
4950
|
-
nextCursor: data.nextCursor
|
|
4951
|
-
}),
|
|
4952
|
-
pagination: { nextCursor: data.nextCursor }
|
|
4953
|
-
});
|
|
4954
|
-
return;
|
|
4955
|
-
}
|
|
4956
|
-
if (invocation.toolName === void 0) {
|
|
4957
|
-
if (invocation.cursor !== void 0 || parsedLimit !== void 0) throw new ValidationError({
|
|
4958
|
-
details: `${invocation.cursor === void 0 ? "" : `--cursor ${invocation.cursor} `}${parsedLimit === void 0 ? "" : `--limit ${parsedLimit}`}`.trim(),
|
|
4959
|
-
message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
|
|
4960
|
-
recovery: { command: cliCommands.catalog.command() }
|
|
4961
|
-
});
|
|
4962
|
-
if (invocation.example) throw new ValidationError({
|
|
4963
|
-
details: `--example without tool name for ${invocation.serverId}`,
|
|
4964
|
-
message: "Invalid catalog options. --example requires <tool-name>.",
|
|
4965
|
-
recovery: { command: cliCommands.catalog.server(invocation.serverId) }
|
|
4966
|
-
});
|
|
4967
|
-
const serverId = invocation.serverId;
|
|
4968
|
-
const command = cliCommands.catalog.server(serverId);
|
|
4969
|
-
const data = ensureSuccess(await runCatalogToolsCommand(runtime.context, { serverId }), runtime, {
|
|
4970
|
-
command,
|
|
4971
|
-
entity: { serverId }
|
|
4972
|
-
});
|
|
4973
|
-
runtime.output.success(data, {
|
|
4974
|
-
command,
|
|
4975
|
-
entity: {
|
|
4976
|
-
serverId: data.server.serverId,
|
|
4977
|
-
toolCount: data.tools.length
|
|
4978
|
-
},
|
|
4979
|
-
nextActions: nextActionsForCatalogTools(data)
|
|
4980
|
-
});
|
|
4981
|
-
return;
|
|
4982
|
-
}
|
|
4983
|
-
if (invocation.cursor !== void 0 || parsedLimit !== void 0) throw new ValidationError({
|
|
4984
|
-
details: `${invocation.cursor === void 0 ? "" : `--cursor ${invocation.cursor} `}${parsedLimit === void 0 ? "" : `--limit ${parsedLimit}`}`.trim(),
|
|
4985
|
-
message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
|
|
4986
|
-
recovery: { command: cliCommands.catalog.tool(invocation.serverId, invocation.toolName, { example: invocation.example }) }
|
|
4987
|
-
});
|
|
4988
|
-
const serverId = invocation.serverId;
|
|
4989
|
-
const toolName = invocation.toolName;
|
|
4990
|
-
const command = cliCommands.catalog.tool(serverId, toolName, { example: invocation.example });
|
|
4991
|
-
const data = ensureSuccess(await runCatalogToolDetailsCommand(runtime.context, {
|
|
4992
|
-
serverId,
|
|
4993
|
-
toolName
|
|
4994
|
-
}), runtime, {
|
|
4995
|
-
command,
|
|
4996
|
-
entity: {
|
|
4997
|
-
serverId,
|
|
4998
|
-
toolName
|
|
4999
|
-
}
|
|
5000
|
-
});
|
|
5001
|
-
const exampleInput = buildJsonSchemaExample(data.inputSchema);
|
|
5002
|
-
const outputData = invocation.example ? {
|
|
5003
|
-
...data,
|
|
5004
|
-
exampleInput
|
|
5005
|
-
} : data;
|
|
5006
|
-
runtime.output.success(outputData, {
|
|
5181
|
+
runtime.output.success(data, {
|
|
5007
5182
|
command,
|
|
5008
5183
|
entity: {
|
|
5009
|
-
|
|
5010
|
-
|
|
5184
|
+
localCredentialsDeleted: data.localCredentialsDeleted,
|
|
5185
|
+
revoked: data.revoked
|
|
5011
5186
|
},
|
|
5012
|
-
nextActions:
|
|
5187
|
+
nextActions: [nextAction("login", "Authenticate again", cliCommands.auth.login(), "Logout completed; authenticate again before further tool calls.", "after_logout")]
|
|
5013
5188
|
});
|
|
5014
5189
|
};
|
|
5190
|
+
const executeCatalogInvocation = async (runtime, invocation) => {
|
|
5191
|
+
const formatPaginationDetails = () => {
|
|
5192
|
+
return `${invocation.cursor === void 0 ? "" : `--cursor ${invocation.cursor} `}${invocation.limit === void 0 ? "" : `--limit ${invocation.limit}`}`.trim();
|
|
5193
|
+
};
|
|
5194
|
+
const toCatalogExecutionPlan = () => {
|
|
5195
|
+
if (invocation.serverId === void 0) {
|
|
5196
|
+
if (invocation.example) return Result.err(new ValidationError({
|
|
5197
|
+
details: "--example without <server-id> <tool-name>",
|
|
5198
|
+
message: "Invalid catalog options. --example requires <server-id> <tool-name>.",
|
|
5199
|
+
recovery: { command: cliCommands.catalog.command() }
|
|
5200
|
+
}));
|
|
5201
|
+
return Result.ok({
|
|
5202
|
+
cursor: invocation.cursor,
|
|
5203
|
+
kind: "summary",
|
|
5204
|
+
limit: invocation.limit
|
|
5205
|
+
});
|
|
5206
|
+
}
|
|
5207
|
+
if (invocation.toolName === void 0) {
|
|
5208
|
+
if (invocation.cursor !== void 0 || invocation.limit !== void 0) return Result.err(new ValidationError({
|
|
5209
|
+
details: formatPaginationDetails(),
|
|
5210
|
+
message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
|
|
5211
|
+
recovery: { command: cliCommands.catalog.command() }
|
|
5212
|
+
}));
|
|
5213
|
+
if (invocation.example) return Result.err(new ValidationError({
|
|
5214
|
+
details: `--example without tool name for ${invocation.serverId}`,
|
|
5215
|
+
message: "Invalid catalog options. --example requires <tool-name>.",
|
|
5216
|
+
recovery: { command: cliCommands.catalog.server(invocation.serverId) }
|
|
5217
|
+
}));
|
|
5218
|
+
return Result.ok({
|
|
5219
|
+
kind: "tools",
|
|
5220
|
+
serverId: invocation.serverId
|
|
5221
|
+
});
|
|
5222
|
+
}
|
|
5223
|
+
if (invocation.cursor !== void 0 || invocation.limit !== void 0) return Result.err(new ValidationError({
|
|
5224
|
+
details: formatPaginationDetails(),
|
|
5225
|
+
message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
|
|
5226
|
+
recovery: { command: cliCommands.catalog.tool(invocation.serverId, invocation.toolName, { example: invocation.example }) }
|
|
5227
|
+
}));
|
|
5228
|
+
return Result.ok({
|
|
5229
|
+
example: invocation.example,
|
|
5230
|
+
kind: "tool",
|
|
5231
|
+
serverId: invocation.serverId,
|
|
5232
|
+
toolName: invocation.toolName
|
|
5233
|
+
});
|
|
5234
|
+
};
|
|
5235
|
+
const planResult = toCatalogExecutionPlan();
|
|
5236
|
+
if (Result.isError(planResult)) throw planResult.error;
|
|
5237
|
+
switch (planResult.value.kind) {
|
|
5238
|
+
case "summary": {
|
|
5239
|
+
const plan = planResult.value;
|
|
5240
|
+
const command = cliCommands.catalog.summary({
|
|
5241
|
+
...plan.cursor === void 0 ? {} : { cursor: plan.cursor },
|
|
5242
|
+
...plan.limit === void 0 ? {} : { limit: plan.limit }
|
|
5243
|
+
});
|
|
5244
|
+
const data = ensureSuccess(await runCatalogCommand(runtime.context, {
|
|
5245
|
+
...plan.cursor === void 0 ? {} : { cursor: plan.cursor },
|
|
5246
|
+
includeDebug: runtime.output.debug,
|
|
5247
|
+
...plan.limit === void 0 ? {} : { limit: plan.limit }
|
|
5248
|
+
}), runtime, {
|
|
5249
|
+
command,
|
|
5250
|
+
entity: {
|
|
5251
|
+
cursor: plan.cursor ?? null,
|
|
5252
|
+
limit: plan.limit ?? null
|
|
5253
|
+
}
|
|
5254
|
+
});
|
|
5255
|
+
const outputData = {
|
|
5256
|
+
failures: data.failures,
|
|
5257
|
+
servers: data.servers
|
|
5258
|
+
};
|
|
5259
|
+
runtime.output.success(outputData, {
|
|
5260
|
+
command,
|
|
5261
|
+
entity: {
|
|
5262
|
+
cursor: plan.cursor ?? null,
|
|
5263
|
+
failedServerCount: data.failures.length,
|
|
5264
|
+
limit: plan.limit ?? null,
|
|
5265
|
+
serverCount: data.servers.length
|
|
5266
|
+
},
|
|
5267
|
+
nextActions: nextActionsForCatalogSummary(outputData, {
|
|
5268
|
+
limit: plan.limit ?? null,
|
|
5269
|
+
nextCursor: data.nextCursor
|
|
5270
|
+
}),
|
|
5271
|
+
pagination: { nextCursor: data.nextCursor }
|
|
5272
|
+
});
|
|
5273
|
+
return;
|
|
5274
|
+
}
|
|
5275
|
+
case "tools": {
|
|
5276
|
+
const command = cliCommands.catalog.server(planResult.value.serverId);
|
|
5277
|
+
const data = ensureSuccess(await runCatalogToolsCommand(runtime.context, { serverId: planResult.value.serverId }), runtime, {
|
|
5278
|
+
command,
|
|
5279
|
+
entity: { serverId: planResult.value.serverId }
|
|
5280
|
+
});
|
|
5281
|
+
runtime.output.success(data, {
|
|
5282
|
+
command,
|
|
5283
|
+
entity: {
|
|
5284
|
+
serverId: data.server.serverId,
|
|
5285
|
+
toolCount: data.tools.length
|
|
5286
|
+
},
|
|
5287
|
+
nextActions: nextActionsForCatalogTools(data)
|
|
5288
|
+
});
|
|
5289
|
+
return;
|
|
5290
|
+
}
|
|
5291
|
+
case "tool": {
|
|
5292
|
+
const command = cliCommands.catalog.tool(planResult.value.serverId, planResult.value.toolName, { example: planResult.value.example });
|
|
5293
|
+
const data = ensureSuccess(await runCatalogToolDetailsCommand(runtime.context, {
|
|
5294
|
+
serverId: planResult.value.serverId,
|
|
5295
|
+
toolName: planResult.value.toolName
|
|
5296
|
+
}), runtime, {
|
|
5297
|
+
command,
|
|
5298
|
+
entity: {
|
|
5299
|
+
serverId: planResult.value.serverId,
|
|
5300
|
+
toolName: planResult.value.toolName
|
|
5301
|
+
}
|
|
5302
|
+
});
|
|
5303
|
+
const exampleInput = toJsonValue(buildJsonSchemaExample(data.inputSchema));
|
|
5304
|
+
const outputData = planResult.value.example ? {
|
|
5305
|
+
...data,
|
|
5306
|
+
exampleInput
|
|
5307
|
+
} : data;
|
|
5308
|
+
runtime.output.success(outputData, {
|
|
5309
|
+
command,
|
|
5310
|
+
entity: {
|
|
5311
|
+
serverId: data.server.serverId,
|
|
5312
|
+
toolName: data.name
|
|
5313
|
+
},
|
|
5314
|
+
nextActions: nextActionsForCatalogToolDetails(data, exampleInput)
|
|
5315
|
+
});
|
|
5316
|
+
return;
|
|
5317
|
+
}
|
|
5318
|
+
}
|
|
5319
|
+
};
|
|
5015
5320
|
const executeInvokeInvocation = async (runtime, invocation) => {
|
|
5016
5321
|
let inputSource = "none";
|
|
5017
|
-
let command = cliCommands.invoke.command(invocation.
|
|
5322
|
+
let command = cliCommands.invoke.command(invocation.serverId, invocation.toolName, invocation.orgSlug);
|
|
5018
5323
|
if (invocation.input !== void 0) if (invocation.input === "-") {
|
|
5019
5324
|
inputSource = "stdin";
|
|
5020
|
-
command = cliCommands.invoke.stdin(invocation.
|
|
5325
|
+
command = cliCommands.invoke.stdin(invocation.serverId, invocation.toolName, invocation.orgSlug);
|
|
5021
5326
|
} else if (invocation.input.startsWith("@")) {
|
|
5022
5327
|
inputSource = "file";
|
|
5023
|
-
command = cliCommands.invoke.withInputValue(invocation.
|
|
5328
|
+
command = cliCommands.invoke.withInputValue(invocation.serverId, invocation.toolName, invocation.input, invocation.orgSlug);
|
|
5024
5329
|
} else {
|
|
5025
5330
|
inputSource = "inline_json";
|
|
5026
|
-
command = cliCommands.invoke.inlineJson(invocation.
|
|
5331
|
+
command = cliCommands.invoke.inlineJson(invocation.serverId, invocation.toolName, invocation.orgSlug);
|
|
5027
5332
|
}
|
|
5028
5333
|
const data = ensureSuccess(await runInvokeCommand(runtime.context, {
|
|
5029
5334
|
input: invocation.input,
|
|
5030
|
-
|
|
5335
|
+
...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
|
|
5336
|
+
serverId: invocation.serverId,
|
|
5337
|
+
toolName: invocation.toolName
|
|
5031
5338
|
}), runtime, {
|
|
5032
5339
|
command,
|
|
5033
5340
|
entity: {
|
|
5034
5341
|
inputSource,
|
|
5035
|
-
|
|
5342
|
+
...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
|
|
5343
|
+
serverId: invocation.serverId,
|
|
5344
|
+
toolName: invocation.toolName
|
|
5036
5345
|
}
|
|
5037
5346
|
});
|
|
5038
5347
|
runtime.output.success(data, {
|
|
5039
5348
|
command,
|
|
5040
5349
|
entity: {
|
|
5041
5350
|
inputSource,
|
|
5351
|
+
...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
|
|
5042
5352
|
serverId: data.serverId,
|
|
5043
5353
|
toolName: data.toolName
|
|
5044
5354
|
},
|
|
@@ -5047,8 +5357,10 @@ const executeInvokeInvocation = async (runtime, invocation) => {
|
|
|
5047
5357
|
};
|
|
5048
5358
|
const executeStatusInvocation = async (runtime) => {
|
|
5049
5359
|
const command = cliCommands.status.command();
|
|
5050
|
-
|
|
5051
|
-
|
|
5360
|
+
const data = await runStatusCommand({
|
|
5361
|
+
apiKeyOverride: runtime.context.apiKeyOverride,
|
|
5362
|
+
debug: runtime.output.debug
|
|
5363
|
+
}, { infoService: runtime.infoService });
|
|
5052
5364
|
runtime.output.success(data, {
|
|
5053
5365
|
command,
|
|
5054
5366
|
entity: { summaryStatus: data.summary.status },
|
|
@@ -5062,39 +5374,28 @@ const executeRootInvocation = (runtime) => {
|
|
|
5062
5374
|
nextActions: [nextAction("login", "Authenticate", cliCommands.auth.login(), "Authenticate first so catalog and invoke commands can run.", "immediate"), nextAction("catalog", "Discover servers", cliCommands.catalog.command(), "List accessible servers and tool counts.", "after_auth")]
|
|
5063
5375
|
});
|
|
5064
5376
|
};
|
|
5065
|
-
const invocationHandlers = {
|
|
5066
|
-
auth_login: executeAuthLoginInvocation,
|
|
5067
|
-
auth_logout: async (runtime) => executeAuthLogoutInvocation(runtime),
|
|
5068
|
-
auth_status: async (runtime) => executeAuthStatusInvocation(runtime),
|
|
5069
|
-
catalog: executeCatalogInvocation,
|
|
5070
|
-
invoke: executeInvokeInvocation,
|
|
5071
|
-
root: async (runtime) => {
|
|
5072
|
-
executeRootInvocation(runtime);
|
|
5073
|
-
},
|
|
5074
|
-
status: async (runtime) => executeStatusInvocation(runtime)
|
|
5075
|
-
};
|
|
5076
5377
|
const executeInvocation = async (runtime, invocation) => {
|
|
5077
5378
|
switch (invocation.kind) {
|
|
5078
5379
|
case "auth_login":
|
|
5079
|
-
await
|
|
5380
|
+
await executeAuthLoginInvocation(runtime, invocation);
|
|
5080
5381
|
return;
|
|
5081
5382
|
case "auth_logout":
|
|
5082
|
-
await
|
|
5383
|
+
await executeAuthLogoutInvocation(runtime);
|
|
5083
5384
|
return;
|
|
5084
5385
|
case "auth_status":
|
|
5085
|
-
await
|
|
5386
|
+
await executeAuthStatusInvocation(runtime);
|
|
5086
5387
|
return;
|
|
5087
5388
|
case "catalog":
|
|
5088
|
-
await
|
|
5389
|
+
await executeCatalogInvocation(runtime, invocation);
|
|
5089
5390
|
return;
|
|
5090
5391
|
case "invoke":
|
|
5091
|
-
await
|
|
5392
|
+
await executeInvokeInvocation(runtime, invocation);
|
|
5092
5393
|
return;
|
|
5093
5394
|
case "root":
|
|
5094
|
-
|
|
5395
|
+
executeRootInvocation(runtime);
|
|
5095
5396
|
return;
|
|
5096
5397
|
case "status":
|
|
5097
|
-
await
|
|
5398
|
+
await executeStatusInvocation(runtime);
|
|
5098
5399
|
return;
|
|
5099
5400
|
}
|
|
5100
5401
|
};
|
|
@@ -9383,78 +9684,6 @@ const readPackageJson = () => {
|
|
|
9383
9684
|
const packageJson = readPackageJson();
|
|
9384
9685
|
const VERSION = packageJson.version;
|
|
9385
9686
|
|
|
9386
|
-
//#endregion
|
|
9387
|
-
//#region ../../packages/shared/src/cli/common.ts
|
|
9388
|
-
const jsonObjectSchema = record(string(), unknown());
|
|
9389
|
-
const cliErrorSchema = object({
|
|
9390
|
-
code: string().min(1),
|
|
9391
|
-
message: string().min(1)
|
|
9392
|
-
}).strict();
|
|
9393
|
-
const cliErrorEnvelopeSchema = object({ error: cliErrorSchema }).strict();
|
|
9394
|
-
const cliSuccessEnvelopeSchema = (dataSchema) => {
|
|
9395
|
-
return object({ data: dataSchema }).strict();
|
|
9396
|
-
};
|
|
9397
|
-
|
|
9398
|
-
//#endregion
|
|
9399
|
-
//#region ../../packages/shared/src/cli/account.ts
|
|
9400
|
-
const cliServerSchema = object({
|
|
9401
|
-
createdAt: string().nullable(),
|
|
9402
|
-
description: string().nullable(),
|
|
9403
|
-
enabled: boolean(),
|
|
9404
|
-
enabledToolCount: number$1().int().nonnegative(),
|
|
9405
|
-
id: string(),
|
|
9406
|
-
name: string(),
|
|
9407
|
-
path: string(),
|
|
9408
|
-
readOnlyEnabledToolCount: number$1().int().nonnegative(),
|
|
9409
|
-
toolCount: number$1().int().nonnegative()
|
|
9410
|
-
}).strict();
|
|
9411
|
-
const cliOrgSchema = object({
|
|
9412
|
-
orgId: string(),
|
|
9413
|
-
orgName: string(),
|
|
9414
|
-
orgSlug: string(),
|
|
9415
|
-
role: string(),
|
|
9416
|
-
servers: array(cliServerSchema)
|
|
9417
|
-
}).strict();
|
|
9418
|
-
const cliMeDataSchema = object({
|
|
9419
|
-
email: string().nullable(),
|
|
9420
|
-
imageUrl: string().nullable(),
|
|
9421
|
-
name: string().nullable(),
|
|
9422
|
-
orgs: array(cliOrgSchema),
|
|
9423
|
-
userId: string()
|
|
9424
|
-
}).strict();
|
|
9425
|
-
const accountMeSchema = cliSuccessEnvelopeSchema(cliMeDataSchema);
|
|
9426
|
-
|
|
9427
|
-
//#endregion
|
|
9428
|
-
//#region ../../packages/shared/src/cli/auth.ts
|
|
9429
|
-
const deviceCodeStartDataSchema = object({
|
|
9430
|
-
deviceCode: string().min(1),
|
|
9431
|
-
expiresIn: number$1().int().positive(),
|
|
9432
|
-
interval: number$1().int().positive(),
|
|
9433
|
-
userCode: string().min(1),
|
|
9434
|
-
verificationUri: string().url()
|
|
9435
|
-
}).strict();
|
|
9436
|
-
const deviceCodeStartSchema = cliSuccessEnvelopeSchema(deviceCodeStartDataSchema);
|
|
9437
|
-
const deviceTokenPendingDataSchema = object({ status: literal("authorization_pending") }).strict();
|
|
9438
|
-
const deviceTokenApprovedDataSchema = object({
|
|
9439
|
-
agentName: string().min(1),
|
|
9440
|
-
apiKey: string().min(1),
|
|
9441
|
-
status: literal("approved")
|
|
9442
|
-
}).strict();
|
|
9443
|
-
const deviceTokenDataSchema = discriminatedUnion("status", [deviceTokenPendingDataSchema, deviceTokenApprovedDataSchema]);
|
|
9444
|
-
const deviceTokenSchema = cliSuccessEnvelopeSchema(deviceTokenDataSchema);
|
|
9445
|
-
const deviceTokenApprovedSchema = cliSuccessEnvelopeSchema(deviceTokenApprovedDataSchema);
|
|
9446
|
-
const revokeSelfDataSchema = object({ success: literal(true) }).strict();
|
|
9447
|
-
const revokeSelfSchema = cliSuccessEnvelopeSchema(revokeSelfDataSchema);
|
|
9448
|
-
|
|
9449
|
-
//#endregion
|
|
9450
|
-
//#region ../../packages/shared/src/cli/endpoints.ts
|
|
9451
|
-
const cliEndpoints = {
|
|
9452
|
-
accountMe: "/api/v1/cli/me",
|
|
9453
|
-
cliRevokeSelf: "/api/v1/cli/revoke-self",
|
|
9454
|
-
deviceCode: "/api/v1/cli/device-code",
|
|
9455
|
-
deviceToken: "/api/v1/cli/device-token"
|
|
9456
|
-
};
|
|
9457
|
-
|
|
9458
9687
|
//#endregion
|
|
9459
9688
|
//#region src/shared/schemas.ts
|
|
9460
9689
|
const credentialsFileSchema = object({
|
|
@@ -9470,7 +9699,7 @@ const deleteIfExists = (path, existsSyncFn, unlinkSyncFn) => {
|
|
|
9470
9699
|
const normalizeCredentials = (value) => {
|
|
9471
9700
|
const parsed = parseWithSchema(credentialsFileSchema, value, "credentials file");
|
|
9472
9701
|
if (Result.isError(parsed)) return null;
|
|
9473
|
-
if (
|
|
9702
|
+
if (parsed.value.apiKey !== void 0) {
|
|
9474
9703
|
const credentials = { apiKey: parsed.value.apiKey };
|
|
9475
9704
|
if (typeof parsed.value.agentName === "string") credentials.agentName = parsed.value.agentName;
|
|
9476
9705
|
return credentials;
|
|
@@ -9529,11 +9758,22 @@ const createFileCredentialsStore = (deps) => {
|
|
|
9529
9758
|
|
|
9530
9759
|
//#endregion
|
|
9531
9760
|
//#region src/infra/env.ts
|
|
9761
|
+
const baseUrlSchema = url().transform((value) => {
|
|
9762
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
9763
|
+
});
|
|
9532
9764
|
const createRuntimeConfig = (env = process.env, homeDirectory = homedir()) => {
|
|
9533
9765
|
const configDir = join(homeDirectory, ".config", "ogment");
|
|
9534
|
-
const
|
|
9766
|
+
const envBaseUrl = env["OGMENT_BASE_URL"];
|
|
9767
|
+
const hasBaseUrlOverride = typeof envBaseUrl === "string";
|
|
9535
9768
|
return {
|
|
9536
|
-
baseUrl:
|
|
9769
|
+
baseUrl: hasBaseUrlOverride ? (() => {
|
|
9770
|
+
const parsed = baseUrlSchema.safeParse(envBaseUrl);
|
|
9771
|
+
if (!parsed.success) throw new ValidationError({
|
|
9772
|
+
details: envBaseUrl,
|
|
9773
|
+
message: "Invalid OGMENT_BASE_URL. Expected a full URL (for example, https://dashboard.ogment.ai)."
|
|
9774
|
+
});
|
|
9775
|
+
return parsed.data;
|
|
9776
|
+
})() : DEFAULT_OGMENT_BASE_URL,
|
|
9537
9777
|
baseUrlSource: hasBaseUrlOverride ? "env" : "default",
|
|
9538
9778
|
configDir,
|
|
9539
9779
|
credentialsPath: join(configDir, "credentials.json"),
|
|
@@ -9616,193 +9856,135 @@ const createHttpClient = (deps = {}) => {
|
|
|
9616
9856
|
cleanupCallbacks.push(() => {
|
|
9617
9857
|
clearTimeout(timeoutId);
|
|
9618
9858
|
});
|
|
9619
|
-
return Result.tryPromise({
|
|
9620
|
-
catch: (cause) => new RemoteRequestError({
|
|
9621
|
-
message: isAbortError(cause) ? "HTTP request timed out" : "HTTP request failed",
|
|
9622
|
-
...options?.operation === void 0 ? {} : { operation: options.operation },
|
|
9623
|
-
raw: cause instanceof Error ? {
|
|
9624
|
-
message: cause.message,
|
|
9625
|
-
name: cause.name,
|
|
9626
|
-
stack: cause.stack
|
|
9627
|
-
} : cause,
|
|
9628
|
-
retryable: isAbortError(cause),
|
|
9629
|
-
source: "network"
|
|
9630
|
-
}),
|
|
9631
|
-
try: async () => fetchFn(input, {
|
|
9632
|
-
...init,
|
|
9633
|
-
signal: abortController.signal
|
|
9634
|
-
})
|
|
9635
|
-
}).finally(() => {
|
|
9636
|
-
for (const cleanup of cleanupCallbacks) cleanup();
|
|
9637
|
-
});
|
|
9638
|
-
} };
|
|
9639
|
-
};
|
|
9640
|
-
const readResponseText = async (response) => {
|
|
9641
|
-
return Result.tryPromise({
|
|
9642
|
-
catch: () => "",
|
|
9643
|
-
try: async () => response.text()
|
|
9644
|
-
}).then((result) => {
|
|
9645
|
-
if (Result.isError(result)) return "";
|
|
9646
|
-
return result.value;
|
|
9647
|
-
});
|
|
9648
|
-
};
|
|
9649
|
-
|
|
9650
|
-
//#endregion
|
|
9651
|
-
//#region src/output/envelope.ts
|
|
9652
|
-
const createEnvelopeBuilder = (deps = {}) => {
|
|
9653
|
-
const createRequestId = deps.createRequestId ?? randomUUID;
|
|
9654
|
-
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
9655
|
-
const toMeta = (context) => {
|
|
9656
|
-
const base = { command: context.command };
|
|
9657
|
-
if (context.pagination !== void 0) return {
|
|
9658
|
-
...base,
|
|
9659
|
-
pagination: context.pagination,
|
|
9660
|
-
...context.includeDebug === true ? {
|
|
9661
|
-
entity: context.entity ?? null,
|
|
9662
|
-
requestId: createRequestId(),
|
|
9663
|
-
timestamp: now().toISOString()
|
|
9664
|
-
} : {}
|
|
9665
|
-
};
|
|
9666
|
-
return {
|
|
9667
|
-
...base,
|
|
9668
|
-
...context.includeDebug === true ? {
|
|
9669
|
-
entity: context.entity ?? null,
|
|
9670
|
-
requestId: createRequestId(),
|
|
9671
|
-
timestamp: now().toISOString()
|
|
9672
|
-
} : {}
|
|
9673
|
-
};
|
|
9674
|
-
};
|
|
9675
|
-
return {
|
|
9676
|
-
error: (error, context) => {
|
|
9677
|
-
return {
|
|
9678
|
-
data: null,
|
|
9679
|
-
error: presentRuntimeErrorPayload(error, {
|
|
9680
|
-
...context.diagnostics === void 0 ? {} : { contextDiagnostics: context.diagnostics },
|
|
9681
|
-
includeDebug: context.includeDebug === true
|
|
9682
|
-
}),
|
|
9683
|
-
meta: toMeta(context),
|
|
9684
|
-
next_actions: context.nextActions ?? [],
|
|
9685
|
-
ok: false
|
|
9686
|
-
};
|
|
9687
|
-
},
|
|
9688
|
-
parseError: (payload, context) => {
|
|
9689
|
-
return {
|
|
9690
|
-
data: null,
|
|
9691
|
-
error: payload,
|
|
9692
|
-
meta: toMeta(context),
|
|
9693
|
-
next_actions: context.nextActions ?? [],
|
|
9694
|
-
ok: false
|
|
9695
|
-
};
|
|
9696
|
-
},
|
|
9697
|
-
success: (data, context) => {
|
|
9698
|
-
return {
|
|
9699
|
-
data,
|
|
9700
|
-
error: null,
|
|
9701
|
-
meta: toMeta(context),
|
|
9702
|
-
next_actions: context.nextActions ?? [],
|
|
9703
|
-
ok: true
|
|
9704
|
-
};
|
|
9705
|
-
}
|
|
9706
|
-
};
|
|
9707
|
-
};
|
|
9708
|
-
|
|
9709
|
-
//#endregion
|
|
9710
|
-
//#region src/output/manager.ts
|
|
9711
|
-
const toJson = (value) => {
|
|
9712
|
-
return `${JSON.stringify(value, null, 2)}\n`;
|
|
9713
|
-
};
|
|
9714
|
-
const toMinimalEnvelope = (envelope) => {
|
|
9715
|
-
return {
|
|
9716
|
-
data: envelope.data,
|
|
9717
|
-
error: envelope.error,
|
|
9718
|
-
ok: envelope.ok
|
|
9719
|
-
};
|
|
9720
|
-
};
|
|
9721
|
-
const mergeNextActions = (recovery, contextActions) => {
|
|
9722
|
-
const merged = [...recovery === void 0 || recovery === null ? [] : [recovery], ...contextActions ?? []];
|
|
9723
|
-
const deduped = [];
|
|
9724
|
-
const seen = /* @__PURE__ */ new Set();
|
|
9725
|
-
for (const action of merged) {
|
|
9726
|
-
const key = `${action.id}::${action.command}`;
|
|
9727
|
-
if (seen.has(key)) continue;
|
|
9728
|
-
seen.add(key);
|
|
9729
|
-
deduped.push(action);
|
|
9730
|
-
}
|
|
9731
|
-
return deduped;
|
|
9732
|
-
};
|
|
9733
|
-
var OutputManager = class {
|
|
9734
|
-
#envelopeBuilder;
|
|
9735
|
-
#mode;
|
|
9736
|
-
#debug = false;
|
|
9737
|
-
#stderr;
|
|
9738
|
-
#stdout;
|
|
9739
|
-
constructor(deps = {}) {
|
|
9740
|
-
this.#stderr = deps.stderr ?? process.stderr;
|
|
9741
|
-
this.#stdout = deps.stdout ?? process.stdout;
|
|
9742
|
-
this.#mode = "json";
|
|
9743
|
-
this.#envelopeBuilder = createEnvelopeBuilder({
|
|
9744
|
-
...deps.createRequestId === void 0 ? {} : { createRequestId: deps.createRequestId },
|
|
9745
|
-
...deps.now === void 0 ? {} : { now: deps.now }
|
|
9746
|
-
});
|
|
9747
|
-
}
|
|
9748
|
-
configure(options) {
|
|
9749
|
-
this.#mode = options.quiet === true ? "quiet" : "json";
|
|
9750
|
-
this.#debug = options.debug === true;
|
|
9751
|
-
}
|
|
9752
|
-
get mode() {
|
|
9753
|
-
return this.#mode;
|
|
9754
|
-
}
|
|
9755
|
-
get debug() {
|
|
9756
|
-
return this.#debug;
|
|
9757
|
-
}
|
|
9758
|
-
error(error, options) {
|
|
9759
|
-
const envelope = this.#envelopeBuilder.error(error, {
|
|
9760
|
-
...options,
|
|
9761
|
-
includeDebug: this.#debug,
|
|
9762
|
-
nextActions: mergeNextActions(appErrorMeta(error).recovery, options.nextActions)
|
|
9763
|
-
});
|
|
9764
|
-
if (this.#mode === "json") {
|
|
9765
|
-
this.#stdout.write(toJson(envelope));
|
|
9766
|
-
return envelope;
|
|
9767
|
-
}
|
|
9768
|
-
this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
|
|
9769
|
-
return envelope;
|
|
9770
|
-
}
|
|
9771
|
-
parseError(payload, options) {
|
|
9772
|
-
const envelope = this.#envelopeBuilder.parseError(payload, {
|
|
9773
|
-
...options,
|
|
9774
|
-
includeDebug: this.#debug
|
|
9859
|
+
return Result.tryPromise({
|
|
9860
|
+
catch: (cause) => new RemoteRequestError({
|
|
9861
|
+
message: isAbortError(cause) ? "HTTP request timed out" : "HTTP request failed",
|
|
9862
|
+
...options?.operation === void 0 ? {} : { operation: options.operation },
|
|
9863
|
+
raw: toJsonValue(cause instanceof Error ? {
|
|
9864
|
+
message: cause.message,
|
|
9865
|
+
name: cause.name,
|
|
9866
|
+
stack: cause.stack
|
|
9867
|
+
} : cause),
|
|
9868
|
+
retryable: isAbortError(cause),
|
|
9869
|
+
source: "network"
|
|
9870
|
+
}),
|
|
9871
|
+
try: async () => fetchFn(input, {
|
|
9872
|
+
...init,
|
|
9873
|
+
signal: abortController.signal
|
|
9874
|
+
})
|
|
9875
|
+
}).finally(() => {
|
|
9876
|
+
for (const cleanup of cleanupCallbacks) cleanup();
|
|
9775
9877
|
});
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
}
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
}
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
}
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9878
|
+
} };
|
|
9879
|
+
};
|
|
9880
|
+
const readResponseText = async (response) => {
|
|
9881
|
+
return Result.tryPromise({
|
|
9882
|
+
catch: () => "",
|
|
9883
|
+
try: async () => response.text()
|
|
9884
|
+
}).then((result) => {
|
|
9885
|
+
if (Result.isError(result)) return "";
|
|
9886
|
+
return result.value;
|
|
9887
|
+
});
|
|
9888
|
+
};
|
|
9889
|
+
const requestJson = async (httpClient, input, schema, init, options) => {
|
|
9890
|
+
const responseResult = await httpClient.request(input, init, { operation: options.operation });
|
|
9891
|
+
if (Result.isError(responseResult)) return responseResult;
|
|
9892
|
+
const response = responseResult.value;
|
|
9893
|
+
if (!response.ok) {
|
|
9894
|
+
const body = await readResponseText(response);
|
|
9895
|
+
const statusError = options.mapStatusError?.(response, body) ?? new RemoteRequestError({
|
|
9896
|
+
body,
|
|
9897
|
+
httpStatus: response.status,
|
|
9898
|
+
message: `Request failed for ${options.operation}`,
|
|
9899
|
+
operation: options.operation,
|
|
9900
|
+
raw: body,
|
|
9901
|
+
source: "http"
|
|
9793
9902
|
});
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9903
|
+
return Result.err(statusError);
|
|
9904
|
+
}
|
|
9905
|
+
const jsonResult = await Result.tryPromise({
|
|
9906
|
+
catch: () => new RemoteRequestError({
|
|
9907
|
+
httpStatus: response.status,
|
|
9908
|
+
message: `Failed to parse JSON response for ${options.operation}`,
|
|
9909
|
+
operation: options.operation,
|
|
9910
|
+
source: "http"
|
|
9911
|
+
}),
|
|
9912
|
+
try: async () => response.json()
|
|
9913
|
+
});
|
|
9914
|
+
if (Result.isError(jsonResult)) return jsonResult;
|
|
9915
|
+
return parseWithSchema(schema, jsonResult.value, options.context);
|
|
9916
|
+
};
|
|
9917
|
+
|
|
9918
|
+
//#endregion
|
|
9919
|
+
//#region ../../packages/shared/src/cli/common.ts
|
|
9920
|
+
const jsonObjectSchema = record(string(), unknown());
|
|
9921
|
+
const cliErrorSchema = object({
|
|
9922
|
+
code: string().min(1),
|
|
9923
|
+
message: string().min(1)
|
|
9924
|
+
}).strict();
|
|
9925
|
+
const cliErrorEnvelopeSchema = object({ error: cliErrorSchema }).strict();
|
|
9926
|
+
const cliSuccessEnvelopeSchema = (dataSchema) => {
|
|
9927
|
+
return object({ data: dataSchema }).strict();
|
|
9928
|
+
};
|
|
9929
|
+
|
|
9930
|
+
//#endregion
|
|
9931
|
+
//#region ../../packages/shared/src/cli/account.ts
|
|
9932
|
+
const cliServerSchema = object({
|
|
9933
|
+
createdAt: string().nullable(),
|
|
9934
|
+
description: string().nullable(),
|
|
9935
|
+
enabled: boolean(),
|
|
9936
|
+
enabledToolCount: number$1().int().nonnegative(),
|
|
9937
|
+
id: string(),
|
|
9938
|
+
name: string(),
|
|
9939
|
+
path: string(),
|
|
9940
|
+
readOnlyEnabledToolCount: number$1().int().nonnegative(),
|
|
9941
|
+
toolCount: number$1().int().nonnegative()
|
|
9942
|
+
}).strict();
|
|
9943
|
+
const cliOrgSchema = object({
|
|
9944
|
+
orgId: string(),
|
|
9945
|
+
orgName: string(),
|
|
9946
|
+
orgSlug: string(),
|
|
9947
|
+
role: string(),
|
|
9948
|
+
servers: array(cliServerSchema)
|
|
9949
|
+
}).strict();
|
|
9950
|
+
const cliMeDataSchema = object({
|
|
9951
|
+
email: string().nullable(),
|
|
9952
|
+
imageUrl: string().nullable(),
|
|
9953
|
+
name: string().nullable(),
|
|
9954
|
+
orgs: array(cliOrgSchema),
|
|
9955
|
+
userId: string()
|
|
9956
|
+
}).strict();
|
|
9957
|
+
const accountMeSchema = cliSuccessEnvelopeSchema(cliMeDataSchema);
|
|
9958
|
+
|
|
9959
|
+
//#endregion
|
|
9960
|
+
//#region ../../packages/shared/src/cli/auth.ts
|
|
9961
|
+
const deviceCodeStartDataSchema = object({
|
|
9962
|
+
deviceCode: string().min(1),
|
|
9963
|
+
expiresIn: number$1().int().positive(),
|
|
9964
|
+
interval: number$1().int().positive(),
|
|
9965
|
+
userCode: string().min(1),
|
|
9966
|
+
verificationUri: string().url()
|
|
9967
|
+
}).strict();
|
|
9968
|
+
const deviceCodeStartSchema = cliSuccessEnvelopeSchema(deviceCodeStartDataSchema);
|
|
9969
|
+
const deviceTokenPendingDataSchema = object({ status: literal("authorization_pending") }).strict();
|
|
9970
|
+
const deviceTokenApprovedDataSchema = object({
|
|
9971
|
+
agentName: string().min(1),
|
|
9972
|
+
apiKey: string().min(1),
|
|
9973
|
+
status: literal("approved")
|
|
9974
|
+
}).strict();
|
|
9975
|
+
const deviceTokenDataSchema = discriminatedUnion("status", [deviceTokenPendingDataSchema, deviceTokenApprovedDataSchema]);
|
|
9976
|
+
const deviceTokenSchema = cliSuccessEnvelopeSchema(deviceTokenDataSchema);
|
|
9977
|
+
const deviceTokenApprovedSchema = cliSuccessEnvelopeSchema(deviceTokenApprovedDataSchema);
|
|
9978
|
+
const revokeSelfDataSchema = object({ success: literal(true) }).strict();
|
|
9979
|
+
const revokeSelfSchema = cliSuccessEnvelopeSchema(revokeSelfDataSchema);
|
|
9980
|
+
|
|
9981
|
+
//#endregion
|
|
9982
|
+
//#region ../../packages/shared/src/cli/endpoints.ts
|
|
9983
|
+
const cliEndpoints = {
|
|
9984
|
+
accountMe: "/api/v1/cli/me",
|
|
9985
|
+
cliRevokeSelf: "/api/v1/cli/revoke-self",
|
|
9986
|
+
deviceCode: "/api/v1/cli/device-code",
|
|
9987
|
+
deviceToken: "/api/v1/cli/device-token"
|
|
9806
9988
|
};
|
|
9807
9989
|
|
|
9808
9990
|
//#endregion
|
|
@@ -9814,58 +9996,68 @@ const toEndpointUrl$1 = (baseUrl, endpoint) => {
|
|
|
9814
9996
|
return `${baseUrl}${endpoint}`;
|
|
9815
9997
|
};
|
|
9816
9998
|
const createAccountService = (deps) => {
|
|
9817
|
-
const
|
|
9818
|
-
const
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
}
|
|
9835
|
-
|
|
9836
|
-
const jsonResult = await Result.tryPromise({
|
|
9837
|
-
catch: () => new RemoteRequestError({
|
|
9838
|
-
httpStatus: responseResult.value.status,
|
|
9839
|
-
message: "Failed to parse account response JSON",
|
|
9840
|
-
operation: "account/fetch",
|
|
9841
|
-
source: "http"
|
|
9842
|
-
}),
|
|
9843
|
-
try: async () => responseResult.value.json()
|
|
9999
|
+
const fetchAccount = async (apiKey) => {
|
|
10000
|
+
const payloadResult = await requestJson(deps.httpClient, toEndpointUrl$1(deps.baseUrl, cliEndpoints.accountMe), accountMeSchema, { headers: authHeader(apiKey) }, {
|
|
10001
|
+
context: "account response",
|
|
10002
|
+
mapStatusError: (response, body) => {
|
|
10003
|
+
if (response.status === 401) return new AuthError({
|
|
10004
|
+
code: ERROR_CODE.authInvalidCredentials,
|
|
10005
|
+
message: "Authentication failed. Run `ogment auth login` again.",
|
|
10006
|
+
recovery: { command: "ogment auth login" }
|
|
10007
|
+
});
|
|
10008
|
+
return new RemoteRequestError({
|
|
10009
|
+
body,
|
|
10010
|
+
httpStatus: response.status,
|
|
10011
|
+
message: "Failed to fetch account details",
|
|
10012
|
+
operation: "account/fetch",
|
|
10013
|
+
raw: body,
|
|
10014
|
+
source: "http"
|
|
10015
|
+
});
|
|
10016
|
+
},
|
|
10017
|
+
operation: "account/fetch"
|
|
9844
10018
|
});
|
|
9845
|
-
if (Result.isError(
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
10019
|
+
if (Result.isError(payloadResult)) return payloadResult;
|
|
10020
|
+
return Result.ok(payloadResult.value.data);
|
|
10021
|
+
};
|
|
10022
|
+
return { fetchAccount };
|
|
10023
|
+
};
|
|
10024
|
+
|
|
10025
|
+
//#endregion
|
|
10026
|
+
//#region src/services/api-key-resolution.ts
|
|
10027
|
+
const isNonEmptyString = (value) => {
|
|
10028
|
+
return typeof value === "string" && value.length > 0;
|
|
10029
|
+
};
|
|
10030
|
+
const resolveApiKey = (options) => {
|
|
10031
|
+
if (isNonEmptyString(options.apiKeyOverride)) return {
|
|
10032
|
+
agentName: null,
|
|
10033
|
+
apiKey: options.apiKeyOverride,
|
|
10034
|
+
loadError: null,
|
|
10035
|
+
source: "apiKeyOption"
|
|
10036
|
+
};
|
|
10037
|
+
if (isNonEmptyString(options.envApiKey)) return {
|
|
10038
|
+
agentName: null,
|
|
10039
|
+
apiKey: options.envApiKey,
|
|
10040
|
+
loadError: null,
|
|
10041
|
+
source: "env"
|
|
10042
|
+
};
|
|
10043
|
+
const storedCredentials = options.credentialsStore.load();
|
|
10044
|
+
if (Result.isError(storedCredentials)) return {
|
|
10045
|
+
agentName: null,
|
|
10046
|
+
apiKey: null,
|
|
10047
|
+
loadError: storedCredentials.error,
|
|
10048
|
+
source: "credentialsError"
|
|
10049
|
+
};
|
|
10050
|
+
if (storedCredentials.value !== null) return {
|
|
10051
|
+
agentName: storedCredentials.value.agentName ?? null,
|
|
10052
|
+
apiKey: storedCredentials.value.apiKey,
|
|
10053
|
+
loadError: null,
|
|
10054
|
+
source: "credentialsFile"
|
|
9849
10055
|
};
|
|
9850
|
-
const fetchAccount = async (apiKey) => fetchAccountOnce(apiKey);
|
|
9851
10056
|
return {
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
const servers = profileResult.value.orgs.flatMap((organization) => {
|
|
9857
|
-
return organization.servers.map((server) => {
|
|
9858
|
-
return {
|
|
9859
|
-
description: server.description,
|
|
9860
|
-
enabled: server.enabled,
|
|
9861
|
-
name: server.name,
|
|
9862
|
-
orgSlug: organization.orgSlug,
|
|
9863
|
-
path: server.path
|
|
9864
|
-
};
|
|
9865
|
-
});
|
|
9866
|
-
});
|
|
9867
|
-
return Result.ok(servers);
|
|
9868
|
-
}
|
|
10057
|
+
agentName: null,
|
|
10058
|
+
apiKey: null,
|
|
10059
|
+
loadError: null,
|
|
10060
|
+
source: "none"
|
|
9869
10061
|
};
|
|
9870
10062
|
};
|
|
9871
10063
|
|
|
@@ -9891,87 +10083,62 @@ const revokeUrl = (baseUrl) => {
|
|
|
9891
10083
|
const createAuthService = (deps) => {
|
|
9892
10084
|
const now = deps.now ?? Date.now;
|
|
9893
10085
|
const sleep = deps.sleep ?? defaultSleep;
|
|
9894
|
-
const requestRemote = async (input, init) => {
|
|
9895
|
-
return deps.httpClient.request(input, init);
|
|
9896
|
-
};
|
|
9897
10086
|
const loginWithDevice = async (options) => {
|
|
9898
|
-
const
|
|
10087
|
+
const startPayload = await requestJson(deps.httpClient, deviceCodeUrl(deps.baseUrl), deviceCodeStartSchema, {
|
|
9899
10088
|
headers: { "Content-Type": "application/json" },
|
|
9900
10089
|
method: "POST"
|
|
9901
|
-
}
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
const body = await readResponseText(startFlowResponse.value);
|
|
9905
|
-
return Result.err(new RemoteRequestError({
|
|
10090
|
+
}, {
|
|
10091
|
+
context: "device login start response",
|
|
10092
|
+
mapStatusError: (response, body) => new RemoteRequestError({
|
|
9906
10093
|
body,
|
|
9907
|
-
httpStatus:
|
|
10094
|
+
httpStatus: response.status,
|
|
9908
10095
|
message: "Failed to start device login",
|
|
9909
10096
|
operation: "auth/device/start",
|
|
9910
10097
|
raw: body,
|
|
9911
10098
|
source: "http"
|
|
9912
|
-
}));
|
|
9913
|
-
}
|
|
9914
|
-
const startPayload = await Result.tryPromise({
|
|
9915
|
-
catch: () => new RemoteRequestError({
|
|
9916
|
-
httpStatus: startFlowResponse.value.status,
|
|
9917
|
-
message: "Failed to parse device login start payload",
|
|
9918
|
-
operation: "auth/device/start",
|
|
9919
|
-
source: "http"
|
|
9920
10099
|
}),
|
|
9921
|
-
|
|
10100
|
+
operation: "auth/device/start"
|
|
9922
10101
|
});
|
|
9923
10102
|
if (Result.isError(startPayload)) return startPayload;
|
|
9924
|
-
const parsedStartPayload = parseWithSchema(deviceCodeStartSchema, startPayload.value, "device login start response");
|
|
9925
|
-
if (Result.isError(parsedStartPayload)) return parsedStartPayload;
|
|
9926
10103
|
options.onPending?.({
|
|
9927
|
-
userCode:
|
|
9928
|
-
verificationUri:
|
|
10104
|
+
userCode: startPayload.value.data.userCode,
|
|
10105
|
+
verificationUri: startPayload.value.data.verificationUri
|
|
9929
10106
|
});
|
|
9930
|
-
const deadline = now() +
|
|
9931
|
-
const interval =
|
|
10107
|
+
const deadline = now() + startPayload.value.data.expiresIn * 1e3;
|
|
10108
|
+
const interval = startPayload.value.data.interval * 1e3;
|
|
9932
10109
|
while (now() < deadline) {
|
|
9933
10110
|
await sleep(interval);
|
|
9934
|
-
const
|
|
9935
|
-
body: JSON.stringify({ deviceCode:
|
|
10111
|
+
const pollPayload = await requestJson(deps.httpClient, deviceTokenUrl(deps.baseUrl), deviceTokenSchema, {
|
|
10112
|
+
body: JSON.stringify({ deviceCode: startPayload.value.data.deviceCode }),
|
|
9936
10113
|
headers: { "Content-Type": "application/json" },
|
|
9937
10114
|
method: "POST"
|
|
9938
|
-
}
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
}
|
|
9960
|
-
|
|
9961
|
-
const pollPayload = await Result.tryPromise({
|
|
9962
|
-
catch: () => new RemoteRequestError({
|
|
9963
|
-
httpStatus: pollResponse.value.status,
|
|
9964
|
-
message: "Failed to parse device login poll payload",
|
|
9965
|
-
operation: "auth/device/poll",
|
|
9966
|
-
source: "http"
|
|
9967
|
-
}),
|
|
9968
|
-
try: async () => pollResponse.value.json()
|
|
10115
|
+
}, {
|
|
10116
|
+
context: "device login poll response",
|
|
10117
|
+
mapStatusError: (response, body) => {
|
|
10118
|
+
if (response.status === 410) return new AuthError({
|
|
10119
|
+
code: ERROR_CODE.authDeviceExpired,
|
|
10120
|
+
message: "Device login code expired. Run `ogment auth login` again.",
|
|
10121
|
+
recovery: { command: "ogment auth login" }
|
|
10122
|
+
});
|
|
10123
|
+
if (response.status === 404) return new AuthError({
|
|
10124
|
+
code: ERROR_CODE.authInvalidCredentials,
|
|
10125
|
+
message: "Invalid device login code. Run `ogment auth login` again.",
|
|
10126
|
+
recovery: { command: "ogment auth login" }
|
|
10127
|
+
});
|
|
10128
|
+
return new RemoteRequestError({
|
|
10129
|
+
body,
|
|
10130
|
+
httpStatus: response.status,
|
|
10131
|
+
message: "Failed to poll device login status",
|
|
10132
|
+
operation: "auth/device/poll",
|
|
10133
|
+
raw: body,
|
|
10134
|
+
source: "http"
|
|
10135
|
+
});
|
|
10136
|
+
},
|
|
10137
|
+
operation: "auth/device/poll"
|
|
9969
10138
|
});
|
|
9970
10139
|
if (Result.isError(pollPayload)) return pollPayload;
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
if (parsedTokenPayload.value.data.status === "authorization_pending") continue;
|
|
9974
|
-
const approvedPayload = parsedTokenPayload.value.data;
|
|
10140
|
+
if (pollPayload.value.data.status === "authorization_pending") continue;
|
|
10141
|
+
const approvedPayload = pollPayload.value.data;
|
|
9975
10142
|
const saveResult = deps.credentialsStore.save({
|
|
9976
10143
|
agentName: approvedPayload.agentName,
|
|
9977
10144
|
apiKey: approvedPayload.apiKey
|
|
@@ -10024,7 +10191,7 @@ const createAuthService = (deps) => {
|
|
|
10024
10191
|
localCredentialsDeleted: false,
|
|
10025
10192
|
revoked: false
|
|
10026
10193
|
});
|
|
10027
|
-
const revokeResult = await
|
|
10194
|
+
const revokeResult = await deps.httpClient.request(revokeUrl(deps.baseUrl), {
|
|
10028
10195
|
headers: { Authorization: `Bearer ${stored.value.apiKey}` },
|
|
10029
10196
|
method: "POST"
|
|
10030
10197
|
});
|
|
@@ -10037,11 +10204,13 @@ const createAuthService = (deps) => {
|
|
|
10037
10204
|
});
|
|
10038
10205
|
},
|
|
10039
10206
|
resolveApiKey: async (overrideApiKey) => {
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10207
|
+
const resolution = resolveApiKey({
|
|
10208
|
+
apiKeyOverride: overrideApiKey,
|
|
10209
|
+
credentialsStore: deps.credentialsStore,
|
|
10210
|
+
envApiKey: deps.envApiKey
|
|
10211
|
+
});
|
|
10212
|
+
if (resolution.apiKey !== null) return Result.ok(resolution.apiKey);
|
|
10213
|
+
if (resolution.source === "credentialsError" && resolution.loadError) return Result.err(resolution.loadError);
|
|
10045
10214
|
return Result.err(new AuthError({
|
|
10046
10215
|
code: ERROR_CODE.authRequired,
|
|
10047
10216
|
message: "Not logged in. Run `ogment auth login` or set OGMENT_API_KEY.",
|
|
@@ -10049,26 +10218,21 @@ const createAuthService = (deps) => {
|
|
|
10049
10218
|
}));
|
|
10050
10219
|
},
|
|
10051
10220
|
status: async (overrideApiKey) => {
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
|
|
10056
|
-
});
|
|
10057
|
-
if (typeof deps.envApiKey === "string" && deps.envApiKey.length > 0) return Result.ok({
|
|
10058
|
-
agentName: null,
|
|
10059
|
-
apiKeySource: "env",
|
|
10060
|
-
loggedIn: true
|
|
10221
|
+
const resolution = resolveApiKey({
|
|
10222
|
+
apiKeyOverride: overrideApiKey,
|
|
10223
|
+
credentialsStore: deps.credentialsStore,
|
|
10224
|
+
envApiKey: deps.envApiKey
|
|
10061
10225
|
});
|
|
10062
|
-
|
|
10063
|
-
if (
|
|
10064
|
-
if (stored.value === null) return Result.ok({
|
|
10226
|
+
if (resolution.source === "credentialsError" && resolution.loadError) return Result.err(resolution.loadError);
|
|
10227
|
+
if (resolution.apiKey === null) return Result.ok({
|
|
10065
10228
|
agentName: null,
|
|
10066
10229
|
apiKeySource: "none",
|
|
10067
10230
|
loggedIn: false
|
|
10068
10231
|
});
|
|
10232
|
+
const apiKeySource = resolution.source === "credentialsFile" ? "credentialsFile" : resolution.source === "apiKeyOption" ? "apiKeyOption" : "env";
|
|
10069
10233
|
return Result.ok({
|
|
10070
|
-
agentName:
|
|
10071
|
-
apiKeySource
|
|
10234
|
+
agentName: resolution.agentName,
|
|
10235
|
+
apiKeySource,
|
|
10072
10236
|
loggedIn: true
|
|
10073
10237
|
});
|
|
10074
10238
|
}
|
|
@@ -10081,44 +10245,19 @@ const maskApiKey = (apiKey) => {
|
|
|
10081
10245
|
if (apiKey.length <= 8) return `*** (sha256:${createHash("sha256").update(apiKey).digest("hex").slice(0, 12)})`;
|
|
10082
10246
|
return `${apiKey.slice(0, 4)}...${apiKey.slice(-4)} (sha256:${createHash("sha256").update(apiKey).digest("hex").slice(0, 12)})`;
|
|
10083
10247
|
};
|
|
10084
|
-
const
|
|
10085
|
-
if (typeof apiKeyOverride === "string" && apiKeyOverride.length > 0) return {
|
|
10086
|
-
loadError: null,
|
|
10087
|
-
source: "apiKeyOption",
|
|
10088
|
-
value: apiKeyOverride
|
|
10089
|
-
};
|
|
10090
|
-
if (typeof envApiKey === "string" && envApiKey.length > 0) return {
|
|
10091
|
-
loadError: null,
|
|
10092
|
-
source: "env",
|
|
10093
|
-
value: envApiKey
|
|
10094
|
-
};
|
|
10095
|
-
const storedCredentials = credentialsStore.load();
|
|
10096
|
-
if (Result.isError(storedCredentials)) return {
|
|
10097
|
-
loadError: storedCredentials.error.message,
|
|
10098
|
-
source: "credentialsError",
|
|
10099
|
-
value: null
|
|
10100
|
-
};
|
|
10101
|
-
if (storedCredentials.value !== null) return {
|
|
10102
|
-
loadError: null,
|
|
10103
|
-
source: "credentialsFile",
|
|
10104
|
-
value: storedCredentials.value.apiKey
|
|
10105
|
-
};
|
|
10248
|
+
const nextActionByIssueCode = (includeDebug) => {
|
|
10106
10249
|
return {
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10250
|
+
auth_failed: "Run `ogment auth login` to refresh credentials.",
|
|
10251
|
+
credentials_load_failed: "Check file permissions and contents of `~/.config/ogment/credentials.json`.",
|
|
10252
|
+
no_api_key: "Run `ogment auth login` or set `OGMENT_API_KEY`.",
|
|
10253
|
+
unreachable: includeDebug ? "Verify `OGMENT_BASE_URL` and network connectivity." : "Verify network connectivity."
|
|
10110
10254
|
};
|
|
10111
10255
|
};
|
|
10112
|
-
const
|
|
10113
|
-
|
|
10114
|
-
credentials_load_failed: "Check file permissions and contents of `~/.config/ogment/credentials.json`.",
|
|
10115
|
-
no_api_key: "Run `ogment auth login` or set `OGMENT_API_KEY`.",
|
|
10116
|
-
unreachable: "Verify `OGMENT_BASE_URL` and network connectivity."
|
|
10117
|
-
};
|
|
10118
|
-
const toSummary = (issues) => {
|
|
10256
|
+
const toSummary = (issues, includeDebug) => {
|
|
10257
|
+
const issueActions = nextActionByIssueCode(includeDebug);
|
|
10119
10258
|
const nextActions = /* @__PURE__ */ new Set();
|
|
10120
10259
|
for (const issue of issues) {
|
|
10121
|
-
const nextAction =
|
|
10260
|
+
const nextAction = issueActions[issue.code];
|
|
10122
10261
|
if (nextAction !== void 0) nextActions.add(nextAction);
|
|
10123
10262
|
}
|
|
10124
10263
|
nextActions.add("Run `ogment catalog` to inspect available servers.");
|
|
@@ -10142,9 +10281,14 @@ const createInfoService = (deps) => {
|
|
|
10142
10281
|
const detectEnvironment = deps.detectExecutionEnvironmentFn ?? detectExecutionEnvironment;
|
|
10143
10282
|
const existsSyncFn = deps.existsSyncFn ?? existsSync;
|
|
10144
10283
|
const now = deps.now ?? Date.now;
|
|
10145
|
-
return { collect: async (apiKeyOverride) => {
|
|
10146
|
-
const
|
|
10147
|
-
const
|
|
10284
|
+
return { collect: async (apiKeyOverride, options) => {
|
|
10285
|
+
const includeDebug = options?.includeDebug === true;
|
|
10286
|
+
const apiKeyResolution = resolveApiKey({
|
|
10287
|
+
apiKeyOverride,
|
|
10288
|
+
credentialsStore: deps.credentialsStore,
|
|
10289
|
+
envApiKey: deps.envApiKey
|
|
10290
|
+
});
|
|
10291
|
+
const selectedApiKey = apiKeyResolution.apiKey;
|
|
10148
10292
|
const credentialsFileExists = existsSyncFn(deps.credentialsPath);
|
|
10149
10293
|
const endpoint = `${deps.baseUrl}${cliEndpoints.accountMe}`;
|
|
10150
10294
|
const pingHeaders = typeof selectedApiKey === "string" ? { Authorization: `Bearer ${selectedApiKey}` } : void 0;
|
|
@@ -10238,7 +10382,7 @@ const createInfoService = (deps) => {
|
|
|
10238
10382
|
});
|
|
10239
10383
|
if (apiKeyResolution.source === "credentialsError" && apiKeyResolution.loadError !== null) issues.push({
|
|
10240
10384
|
code: "credentials_load_failed",
|
|
10241
|
-
message: `Failed to load credentials file: ${apiKeyResolution.loadError}`
|
|
10385
|
+
message: `Failed to load credentials file: ${apiKeyResolution.loadError.message}`
|
|
10242
10386
|
});
|
|
10243
10387
|
if (account.status === "auth_error") issues.push({
|
|
10244
10388
|
code: "auth_failed",
|
|
@@ -10262,7 +10406,7 @@ const createInfoService = (deps) => {
|
|
|
10262
10406
|
apiKeyPreview: selectedApiKey === null ? null : maskApiKey(selectedApiKey),
|
|
10263
10407
|
apiKeySource: apiKeyResolution.source,
|
|
10264
10408
|
credentialsFileExists,
|
|
10265
|
-
credentialsFileLoadError: apiKeyResolution.loadError
|
|
10409
|
+
credentialsFileLoadError: apiKeyResolution.loadError?.message ?? null
|
|
10266
10410
|
},
|
|
10267
10411
|
config: {
|
|
10268
10412
|
baseUrl: deps.baseUrl,
|
|
@@ -10275,7 +10419,7 @@ const createInfoService = (deps) => {
|
|
|
10275
10419
|
"--api-key option",
|
|
10276
10420
|
"OGMENT_API_KEY environment variable",
|
|
10277
10421
|
"~/.config/ogment/credentials.json",
|
|
10278
|
-
"default base URL when OGMENT_BASE_URL is unset"
|
|
10422
|
+
...includeDebug ? ["default base URL when OGMENT_BASE_URL is unset"] : []
|
|
10279
10423
|
],
|
|
10280
10424
|
quickCommands: [
|
|
10281
10425
|
"ogment status",
|
|
@@ -10283,7 +10427,7 @@ const createInfoService = (deps) => {
|
|
|
10283
10427
|
"ogment catalog",
|
|
10284
10428
|
"ogment catalog <server-id>",
|
|
10285
10429
|
"ogment catalog <server-id> <tool-name>",
|
|
10286
|
-
"ogment invoke <server-id
|
|
10430
|
+
"ogment invoke <server-id> <tool-name> --input '{}'"
|
|
10287
10431
|
]
|
|
10288
10432
|
},
|
|
10289
10433
|
generatedAt: new Date(now()).toISOString(),
|
|
@@ -10298,7 +10442,7 @@ const createInfoService = (deps) => {
|
|
|
10298
10442
|
platform: process.platform,
|
|
10299
10443
|
processArch: process.arch
|
|
10300
10444
|
},
|
|
10301
|
-
summary: toSummary(issues)
|
|
10445
|
+
summary: toSummary(issues, includeDebug)
|
|
10302
10446
|
};
|
|
10303
10447
|
} };
|
|
10304
10448
|
};
|
|
@@ -20915,33 +21059,12 @@ var StreamableHTTPClientTransport = class {
|
|
|
20915
21059
|
//#endregion
|
|
20916
21060
|
//#region src/services/mcp-error-mapping.ts
|
|
20917
21061
|
const toSerializable = (value) => {
|
|
20918
|
-
if (value instanceof Error) return {
|
|
21062
|
+
if (value instanceof Error) return toJsonValue({
|
|
20919
21063
|
message: value.message,
|
|
20920
21064
|
name: value.name,
|
|
20921
21065
|
stack: value.stack
|
|
20922
|
-
};
|
|
20923
|
-
|
|
20924
|
-
return structuredClone(value);
|
|
20925
|
-
} catch {
|
|
20926
|
-
return String(value);
|
|
20927
|
-
}
|
|
20928
|
-
};
|
|
20929
|
-
const toJsonRpcErrorPayload = (payload) => {
|
|
20930
|
-
if (isJSONRPCErrorResponse(payload)) return {
|
|
20931
|
-
code: payload.error.code,
|
|
20932
|
-
data: payload.error.data,
|
|
20933
|
-
raw: toSerializable(payload)
|
|
20934
|
-
};
|
|
20935
|
-
if (!isRecord$1(payload) || !Object.hasOwn(payload, "error")) return null;
|
|
20936
|
-
const errorRecord = payload["error"];
|
|
20937
|
-
if (!isRecord$1(errorRecord)) return null;
|
|
20938
|
-
const code = errorRecord["code"];
|
|
20939
|
-
if (typeof code !== "number") return null;
|
|
20940
|
-
return {
|
|
20941
|
-
code,
|
|
20942
|
-
data: errorRecord["data"],
|
|
20943
|
-
raw: toSerializable(payload)
|
|
20944
|
-
};
|
|
21066
|
+
});
|
|
21067
|
+
return toJsonValue(value);
|
|
20945
21068
|
};
|
|
20946
21069
|
const extractStreamableBody = (message) => {
|
|
20947
21070
|
const markerIndex = message.indexOf("Error POSTing to endpoint:");
|
|
@@ -20951,24 +21074,15 @@ const extractStreamableBody = (message) => {
|
|
|
20951
21074
|
};
|
|
20952
21075
|
const mapStreamableHttpError = (error) => {
|
|
20953
21076
|
const body = extractStreamableBody(error.message);
|
|
20954
|
-
const
|
|
20955
|
-
const parsed = Result.try({
|
|
20956
|
-
catch: () => null,
|
|
20957
|
-
try: () => {
|
|
20958
|
-
return JSON.parse(body);
|
|
20959
|
-
}
|
|
20960
|
-
});
|
|
20961
|
-
return Result.isError(parsed) ? null : parsed.value;
|
|
20962
|
-
})();
|
|
20963
|
-
const jsonRpcPayload = parsedBody === null ? null : toJsonRpcErrorPayload(parsedBody);
|
|
21077
|
+
const details = body === void 0 ? {} : parseRemoteErrorDetails(body);
|
|
20964
21078
|
const httpStatus = typeof error.code === "number" && error.code >= 100 ? error.code : void 0;
|
|
20965
21079
|
const retryable = httpStatus === void 0 ? void 0 : httpStatus === 429 || httpStatus >= 500 || httpStatus === 408;
|
|
20966
21080
|
return {
|
|
20967
21081
|
...body === void 0 ? {} : { body },
|
|
20968
21082
|
...httpStatus === void 0 ? {} : { httpStatus },
|
|
20969
|
-
...
|
|
20970
|
-
...
|
|
20971
|
-
raw:
|
|
21083
|
+
...details.mcpCode === void 0 ? {} : { mcpCode: details.mcpCode },
|
|
21084
|
+
...details.data === void 0 ? {} : { mcpData: details.data },
|
|
21085
|
+
raw: toSerializable(body ?? error),
|
|
20972
21086
|
...retryable === void 0 ? {} : { retryable },
|
|
20973
21087
|
source: "mcp_transport_http"
|
|
20974
21088
|
};
|
|
@@ -21024,45 +21138,13 @@ const MCP_DISCOVERY_TIMEOUT_MS = 1e4;
|
|
|
21024
21138
|
const MCP_INVOKE_TIMEOUT_MS = 45e3;
|
|
21025
21139
|
const defaultCreateClient = (version) => {
|
|
21026
21140
|
return new Client({
|
|
21027
|
-
name:
|
|
21141
|
+
name: APP_NAME,
|
|
21028
21142
|
version
|
|
21029
21143
|
}, { capabilities: {} });
|
|
21030
21144
|
};
|
|
21031
21145
|
const defaultCreateTransport = (url, apiKey) => {
|
|
21032
21146
|
return new StreamableHTTPClientTransport(url, { requestInit: { headers: { Authorization: `Bearer ${apiKey}` } } });
|
|
21033
21147
|
};
|
|
21034
|
-
const parseToolCallContent = (result) => {
|
|
21035
|
-
const parsedResult = parseWithSchema(CompatibilityCallToolResultSchema, result, "MCP tool call result", {
|
|
21036
|
-
code: ERROR_CODE.toolInputSchemaViolation,
|
|
21037
|
-
recovery: { command: "ogment catalog" }
|
|
21038
|
-
});
|
|
21039
|
-
if (Result.isError(parsedResult)) return parsedResult;
|
|
21040
|
-
const payload = parsedResult.value;
|
|
21041
|
-
if ("toolResult" in payload) return Result.ok({
|
|
21042
|
-
isError: false,
|
|
21043
|
-
structuredContent: payload.toolResult
|
|
21044
|
-
});
|
|
21045
|
-
if (payload.structuredContent !== void 0) return Result.ok({
|
|
21046
|
-
isError: payload.isError === true,
|
|
21047
|
-
structuredContent: payload.structuredContent
|
|
21048
|
-
});
|
|
21049
|
-
const firstContent = payload.content[0];
|
|
21050
|
-
if (firstContent?.type === "text") {
|
|
21051
|
-
const parsedText = parseJsonUnknown(firstContent.text, "MCP text content");
|
|
21052
|
-
if (Result.isError(parsedText)) return Result.ok({
|
|
21053
|
-
isError: payload.isError === true,
|
|
21054
|
-
structuredContent: firstContent.text
|
|
21055
|
-
});
|
|
21056
|
-
return Result.ok({
|
|
21057
|
-
isError: payload.isError === true,
|
|
21058
|
-
structuredContent: parsedText.value
|
|
21059
|
-
});
|
|
21060
|
-
}
|
|
21061
|
-
return Result.ok({
|
|
21062
|
-
isError: payload.isError === true,
|
|
21063
|
-
structuredContent: payload
|
|
21064
|
-
});
|
|
21065
|
-
};
|
|
21066
21148
|
const createMcpService = (deps) => {
|
|
21067
21149
|
const createClient = deps.createClient ?? (() => defaultCreateClient(deps.version));
|
|
21068
21150
|
const createTransport = deps.createTransport ?? defaultCreateTransport;
|
|
@@ -21109,32 +21191,17 @@ const createMcpService = (deps) => {
|
|
|
21109
21191
|
return client.callTool({
|
|
21110
21192
|
arguments: args,
|
|
21111
21193
|
name: toolName
|
|
21112
|
-
},
|
|
21194
|
+
}, CallToolResultSchema, { timeout: MCP_INVOKE_TIMEOUT_MS });
|
|
21113
21195
|
}, "MCP tool call failed", "tools/call");
|
|
21114
21196
|
if (Result.isError(toolCallResult)) return toolCallResult;
|
|
21115
|
-
return
|
|
21197
|
+
return Result.ok(toolCallResult.value);
|
|
21116
21198
|
});
|
|
21117
21199
|
},
|
|
21118
21200
|
listTools: async (target, apiKey) => {
|
|
21119
21201
|
return withClient(target, apiKey, async (client) => {
|
|
21120
21202
|
const toolsResult = await withRemoteCall(async () => client.listTools(void 0, { timeout: MCP_DISCOVERY_TIMEOUT_MS }), "MCP tools/list failed", "tools/list");
|
|
21121
21203
|
if (Result.isError(toolsResult)) return toolsResult;
|
|
21122
|
-
|
|
21123
|
-
code: ERROR_CODE.toolInputSchemaViolation,
|
|
21124
|
-
recovery: { command: "ogment catalog" }
|
|
21125
|
-
});
|
|
21126
|
-
if (Result.isError(parsedToolsResult)) return parsedToolsResult;
|
|
21127
|
-
const parsedTools = [];
|
|
21128
|
-
for (const tool of parsedToolsResult.value.tools) {
|
|
21129
|
-
const normalizedTool = {
|
|
21130
|
-
description: tool.description ?? null,
|
|
21131
|
-
inputSchema: tool.inputSchema,
|
|
21132
|
-
name: tool.name
|
|
21133
|
-
};
|
|
21134
|
-
if (tool.outputSchema !== void 0) normalizedTool.outputSchema = tool.outputSchema;
|
|
21135
|
-
parsedTools.push(normalizedTool);
|
|
21136
|
-
}
|
|
21137
|
-
return Result.ok(parsedTools);
|
|
21204
|
+
return Result.ok(toolsResult.value.tools);
|
|
21138
21205
|
});
|
|
21139
21206
|
}
|
|
21140
21207
|
};
|
|
@@ -21191,24 +21258,21 @@ const asGlobalOptions = (command) => {
|
|
|
21191
21258
|
const options = command.optsWithGlobals();
|
|
21192
21259
|
return {
|
|
21193
21260
|
apiKey: options.apiKey,
|
|
21194
|
-
debug: options.debug,
|
|
21195
|
-
quiet: options.quiet
|
|
21196
|
-
yes: options.yes
|
|
21261
|
+
debug: Boolean(options.debug),
|
|
21262
|
+
quiet: Boolean(options.quiet)
|
|
21197
21263
|
};
|
|
21198
21264
|
};
|
|
21199
21265
|
const mapGlobalOutputOptions = (options) => {
|
|
21200
21266
|
return {
|
|
21201
21267
|
debug: options.debug,
|
|
21202
|
-
quiet: options.quiet
|
|
21203
|
-
yes: options.yes
|
|
21268
|
+
quiet: options.quiet
|
|
21204
21269
|
};
|
|
21205
21270
|
};
|
|
21206
21271
|
const parseOutputOptionsFromArgv = (argv) => {
|
|
21207
21272
|
const hasFlag = (flag) => argv.includes(flag);
|
|
21208
21273
|
return {
|
|
21209
21274
|
debug: hasFlag("--debug"),
|
|
21210
|
-
quiet: hasFlag("--quiet")
|
|
21211
|
-
yes: hasFlag("--yes")
|
|
21275
|
+
quiet: hasFlag("--quiet")
|
|
21212
21276
|
};
|
|
21213
21277
|
};
|
|
21214
21278
|
|
|
@@ -21221,11 +21285,6 @@ const parseCatalogLimitOption = (value) => {
|
|
|
21221
21285
|
if (!Number.isSafeInteger(parsed) || parsed < 1) throw new InvalidArgumentError("Expected a positive integer.");
|
|
21222
21286
|
return parsed;
|
|
21223
21287
|
};
|
|
21224
|
-
const parseInvokeTarget = (value) => {
|
|
21225
|
-
const separatorIndex = value.lastIndexOf("/");
|
|
21226
|
-
if (separatorIndex <= 0 || separatorIndex >= value.length - 1 || /\s/.test(value)) throw new InvalidArgumentError("Expected <server-id>/<tool-name>.");
|
|
21227
|
-
return value;
|
|
21228
|
-
};
|
|
21229
21288
|
const createProgram = (runtime, parseState) => {
|
|
21230
21289
|
const program = new Command();
|
|
21231
21290
|
let invocation = null;
|
|
@@ -21257,12 +21316,12 @@ const createProgram = (runtime, parseState) => {
|
|
|
21257
21316
|
"Examples:",
|
|
21258
21317
|
" $ ogment auth login",
|
|
21259
21318
|
" $ ogment catalog billing create_invoice --example",
|
|
21260
|
-
" $ ogment invoke billing
|
|
21319
|
+
" $ ogment invoke billing create_invoice --input '{\"amount\":100}'",
|
|
21261
21320
|
"",
|
|
21262
21321
|
"Run `ogment help <command>` for command-specific usage."
|
|
21263
21322
|
].join("\n");
|
|
21264
21323
|
});
|
|
21265
|
-
program.name(APP_NAME).description(APP_DESCRIPTION).version(VERSION).optionsGroup("Connection Options:").option("--api-key <key>", "API key override").optionsGroup("Output Options:").option("--debug", "Include debug metadata and diagnostics in JSON output").option("--quiet", "Emit minimal JSON output (ok + data/error)").
|
|
21324
|
+
program.name(APP_NAME).description(APP_DESCRIPTION).version(VERSION).optionsGroup("Connection Options:").option("--api-key <key>", "API key override").optionsGroup("Output Options:").option("--debug", "Include debug metadata and diagnostics in JSON output").option("--quiet", "Emit minimal JSON output (ok + data/error)").hook("preAction", (thisCommand) => {
|
|
21266
21325
|
const options = asGlobalOptions(thisCommand);
|
|
21267
21326
|
runtime.output.configure(mapGlobalOutputOptions(options));
|
|
21268
21327
|
runtime.context.apiKeyOverride = options.apiKey;
|
|
@@ -21291,19 +21350,21 @@ const createProgram = (runtime, parseState) => {
|
|
|
21291
21350
|
});
|
|
21292
21351
|
program.command("catalog [serverId] [toolName]").summary("Discover servers and inspect tools").description("Discover servers and tools with progressive disclosure").helpGroup("Discovery Commands:").addOption(new Option("--cursor <cursor>", "Pagination cursor (catalog summary only)").conflicts("example")).addOption(new Option("--limit <limit>", "Maximum servers to return (catalog summary only)").argParser(parseCatalogLimitOption).conflicts("example")).addOption(new Option("--example", "Include a generated example input payload (tool details only)").conflicts(["cursor", "limit"])).action((serverId, toolName, options) => {
|
|
21293
21352
|
setInvocation({
|
|
21294
|
-
cursor: options.cursor,
|
|
21295
21353
|
example: options.example === true,
|
|
21296
21354
|
kind: "catalog",
|
|
21297
|
-
|
|
21298
|
-
|
|
21299
|
-
|
|
21355
|
+
...options.cursor === void 0 ? {} : { cursor: options.cursor },
|
|
21356
|
+
...options.limit === void 0 ? {} : { limit: options.limit },
|
|
21357
|
+
...serverId === void 0 ? {} : { serverId },
|
|
21358
|
+
...toolName === void 0 ? {} : { toolName }
|
|
21300
21359
|
});
|
|
21301
21360
|
});
|
|
21302
|
-
program.command("invoke").summary("Invoke a tool by <server-id
|
|
21361
|
+
program.command("invoke").summary("Invoke a tool by <server-id> <tool-name>").description("Invoke a tool using <server-id> <tool-name>").helpGroup("Execution Commands:").argument("<serverId>", "Server id").argument("<toolName>", "Tool name").addOption(new Option("--org <orgSlug>", "Organization slug").hideHelp()).option("--input <value>", "Input payload: inline JSON object, @path, or - for stdin").action((serverId, toolName, options) => {
|
|
21303
21362
|
setInvocation({
|
|
21304
21363
|
input: options.input,
|
|
21305
21364
|
kind: "invoke",
|
|
21306
|
-
|
|
21365
|
+
...options.org === void 0 ? {} : { orgSlug: options.org },
|
|
21366
|
+
serverId,
|
|
21367
|
+
toolName
|
|
21307
21368
|
});
|
|
21308
21369
|
});
|
|
21309
21370
|
program.command("status").summary("Show runtime diagnostics").description("Show runtime configuration and connectivity diagnostics").helpGroup("Diagnostics Commands:").action(() => {
|
|
@@ -21329,22 +21390,36 @@ const commandFromArgv = (argv) => {
|
|
|
21329
21390
|
if (normalized.length === 0) return "ogment";
|
|
21330
21391
|
return `ogment ${normalized.join(" ")}`;
|
|
21331
21392
|
};
|
|
21332
|
-
const runCli = async (argv = process.argv.slice(2), runtime =
|
|
21393
|
+
const runCli = async (argv = process.argv.slice(2), runtime = void 0) => {
|
|
21333
21394
|
const normalizedArgv = normalizeCliArgv(argv);
|
|
21334
|
-
|
|
21395
|
+
const outputOptions = parseOutputOptionsFromArgv(normalizedArgv);
|
|
21396
|
+
let resolvedRuntime;
|
|
21397
|
+
try {
|
|
21398
|
+
resolvedRuntime = runtime ?? createRuntime();
|
|
21399
|
+
} catch (error) {
|
|
21400
|
+
const output = new OutputManager();
|
|
21401
|
+
output.configure(outputOptions);
|
|
21402
|
+
const normalized = normalizeCliRuntimeError(error);
|
|
21403
|
+
output.error(normalized, {
|
|
21404
|
+
command: commandFromArgv(argv),
|
|
21405
|
+
entity: null
|
|
21406
|
+
});
|
|
21407
|
+
return exitCodeForError(normalized);
|
|
21408
|
+
}
|
|
21409
|
+
resolvedRuntime.output.configure(outputOptions);
|
|
21335
21410
|
const parseState = createCommanderParseState();
|
|
21336
|
-
const { program, readInvocation } = createProgram(
|
|
21411
|
+
const { program, readInvocation } = createProgram(resolvedRuntime, parseState);
|
|
21337
21412
|
try {
|
|
21338
21413
|
await program.parseAsync(normalizedArgv, { from: "user" });
|
|
21339
21414
|
const invocation = readInvocation();
|
|
21340
|
-
if (invocation !== null) await executeInvocation(
|
|
21415
|
+
if (invocation !== null) await executeInvocation(resolvedRuntime, invocation);
|
|
21341
21416
|
return EXIT_CODE.success;
|
|
21342
21417
|
} catch (error) {
|
|
21343
21418
|
if (error instanceof CliExitError) return error.exitCode;
|
|
21344
21419
|
if (error instanceof CommanderError) {
|
|
21345
21420
|
if (error.exitCode === EXIT_CODE.success) return EXIT_CODE.success;
|
|
21346
|
-
const parseError = toParseCliError(error, parseState, { includeDebug:
|
|
21347
|
-
|
|
21421
|
+
const parseError = toParseCliError(error, parseState, { includeDebug: resolvedRuntime.output.debug });
|
|
21422
|
+
resolvedRuntime.output.parseError(parseError.payload, {
|
|
21348
21423
|
command: commandFromArgv(argv),
|
|
21349
21424
|
entity: null,
|
|
21350
21425
|
nextActions: parseError.nextActions
|
|
@@ -21352,7 +21427,7 @@ const runCli = async (argv = process.argv.slice(2), runtime = createRuntime()) =
|
|
|
21352
21427
|
return EXIT_CODE.validation;
|
|
21353
21428
|
}
|
|
21354
21429
|
const normalized = normalizeCliRuntimeError(error);
|
|
21355
|
-
|
|
21430
|
+
resolvedRuntime.output.error(normalized, {
|
|
21356
21431
|
command: commandFromArgv(argv),
|
|
21357
21432
|
entity: null
|
|
21358
21433
|
});
|
|
@@ -21380,5 +21455,4 @@ const shouldExecuteCli = (importMetaUrl, argv1) => {
|
|
|
21380
21455
|
if (shouldExecuteCli(import.meta.url, process.argv[1])) await executeCli();
|
|
21381
21456
|
|
|
21382
21457
|
//#endregion
|
|
21383
|
-
export { executeCli, runCli, shouldExecuteCli };
|
|
21384
|
-
//# sourceMappingURL=cli.js.map
|
|
21458
|
+
export { executeCli, runCli, shouldExecuteCli };
|