@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/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
- httpStatus: payload.httpStatus ?? payload.status ?? payload.diagnostics?.httpStatus,
3987
- mcpCode: payload.mcpCode ?? payload.diagnostics?.mcpCode,
3988
- mcpData: payload.mcpData ?? payload.diagnostics?.mcpData,
3989
- operation: payload.operation ?? payload.diagnostics?.operation,
3990
- raw: payload.raw ?? payload.diagnostics?.raw,
3991
- source
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 parseJsonUnknown = (raw, context) => {
4163
+ const parseJsonValue = (raw, context) => {
4184
4164
  return Result.try({
4185
- catch: () => new ValidationError({
4186
- details: raw,
4187
- message: `Invalid JSON in ${context}`
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
- const isPlainObject$2 = (value) => {
4198
- return isRecord$1(value) && !Array.isArray(value);
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 extractMessageFromRecord = (record) => {
4217
- if (typeof record["message"] === "string") return sanitizeRemoteMessage(record["message"]);
4218
- const nested = record["error"];
4219
- if (isRecord$1(nested) && typeof nested["message"] === "string") return sanitizeRemoteMessage(nested["message"]);
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(body);
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
- if (isRecord$1(error.raw)) {
4239
- const fromRaw = extractMessageFromRecord(error.raw);
4240
- if (fromRaw !== void 0) return fromRaw;
4241
- }
4242
- const fromBody = extractMessageFromBody(error.body);
4243
- if (fromBody !== void 0) return fromBody;
4244
- if (typeof error.mcpData === "string") {
4245
- const fromData = sanitizeRemoteMessage(error.mcpData);
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 serversResult = await context.services.account.listServers(apiKeyResult.value);
4315
- if (Result.isError(serversResult)) return serversResult;
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
- servers: serversResult.value
4551
+ profile: accountResult.value
4319
4552
  });
4320
4553
  };
4321
- const findServerByPath = (servers, path) => {
4322
- const server = servers.find((item) => item.path === path);
4323
- if (server === void 0) return Result.err(new NotFoundError({
4324
- message: `Server "${path}" not found`,
4325
- resource: path
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 = (server, toolCount) => {
4607
+ const toServerSummary = (target, toolCount) => {
4333
4608
  return {
4334
4609
  capabilities: [],
4335
- description: server.description,
4336
- name: server.name,
4337
- orgSlug: server.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.servers;
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.servers, options.serverId);
4669
+ const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
4390
4670
  if (Result.isError(serverResult)) return serverResult;
4391
- targetServers = [serverResult.value];
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.servers, options.serverId);
4719
+ const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
4437
4720
  if (Result.isError(serverResult)) return serverResult;
4438
- const toolsResult = await listServerTools(context, stateResult.value.apiKey, serverResult.value);
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(serverResult.value, toolsResult.value.length),
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.servers, options.serverId);
4735
+ const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
4449
4736
  if (Result.isError(serverResult)) return serverResult;
4450
- const toolsResult = await listServerTools(context, stateResult.value.apiKey, serverResult.value);
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(serverResult.value, toolsResult.value.length)
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 = isRecord$1(cause) && typeof cause["code"] === "string" ? cause["code"] : void 0;
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 = parseJsonUnknown(raw, context);
4770
+ const parsed = parseJsonValue(raw, context);
4531
4771
  if (Result.isError(parsed)) return parsed;
4532
- if (!isPlainObject$2(parsed.value)) return Result.err(new ValidationError({ message: "Invoke input must be a JSON object" }));
4533
- return Result.ok(parsed.value);
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.servers, targetResult.value.serverId);
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, targetResult.value.toolName, argsResult.value);
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 === targetResult.value.toolName)) return Result.err(new NotFoundError({
4599
- message: `Tool "${targetResult.value.toolName}" not found`,
4600
- resource: targetResult.value.toolName
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 = parseToolErrorDetails(callResult.value.structuredContent);
4861
+ const details = parseRemoteErrorDetails(structuredContent);
4608
4862
  return Result.err(new RemoteRequestError({
4609
4863
  ...details.mcpCode === void 0 ? {} : { mcpCode: details.mcpCode },
4610
- ...details.mcpData === void 0 ? {} : { mcpData: details.mcpData },
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: callResult.value.structuredContent,
4867
+ raw: structuredContent,
4614
4868
  retryable: false,
4615
4869
  source: "mcp_jsonrpc"
4616
4870
  }));
4617
4871
  }
4618
4872
  return Result.ok({
4619
- result: callResult.value.structuredContent,
4620
- serverId: targetResult.value.serverId,
4621
- toolName: targetResult.value.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
- const payload = await deps.infoService.collect(options.apiKeyOverride);
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 = (typeName) => {
4654
- switch (typeName) {
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: (target) => `ogment invoke ${target}`,
4730
- inlineJson: (target) => `ogment invoke ${target} --input <json>`,
4731
- stdin: (target) => `ogment invoke ${target} --input -`,
4732
- withInputValue: (target, value) => {
4733
- return `ogment invoke ${target} --input ${value}`;
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>/<tool-name>",
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 ?? void 0
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(`${payload.server.serverId}/${payload.name}`, inputArgument), `Replace every ... placeholder with real JSON values, then invoke ${payload.server.serverId}/${payload.name}.`, "after_tool_inspection")];
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, mode, apiKey) => {
4824
- const { commandOptions, invokedCommand } = (() => {
4825
- if (mode === "api_key") return {
4826
- commandOptions: {
4827
- apiKey: apiKey ?? "",
4828
- mode: "apiKey"
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, "api_key", invocation.apiKey);
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
- serverId: data.server.serverId,
5010
- toolName: data.name
5184
+ localCredentialsDeleted: data.localCredentialsDeleted,
5185
+ revoked: data.revoked
5011
5186
  },
5012
- nextActions: nextActionsForCatalogToolDetails(data, exampleInput)
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.target);
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.target);
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.target, invocation.input);
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.target);
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
- target: invocation.target
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
- target: invocation.target
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
- if (runtime.infoService === void 0) throw new UnexpectedError({ message: "Info service is not configured" });
5051
- const data = ensureSuccess(await runStatusCommand({ apiKeyOverride: runtime.context.apiKeyOverride }, { infoService: runtime.infoService }), runtime, { command });
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 invocationHandlers.auth_login(runtime, invocation);
5380
+ await executeAuthLoginInvocation(runtime, invocation);
5080
5381
  return;
5081
5382
  case "auth_logout":
5082
- await invocationHandlers.auth_logout(runtime, invocation);
5383
+ await executeAuthLogoutInvocation(runtime);
5083
5384
  return;
5084
5385
  case "auth_status":
5085
- await invocationHandlers.auth_status(runtime, invocation);
5386
+ await executeAuthStatusInvocation(runtime);
5086
5387
  return;
5087
5388
  case "catalog":
5088
- await invocationHandlers.catalog(runtime, invocation);
5389
+ await executeCatalogInvocation(runtime, invocation);
5089
5390
  return;
5090
5391
  case "invoke":
5091
- await invocationHandlers.invoke(runtime, invocation);
5392
+ await executeInvokeInvocation(runtime, invocation);
5092
5393
  return;
5093
5394
  case "root":
5094
- await invocationHandlers.root(runtime, invocation);
5395
+ executeRootInvocation(runtime);
5095
5396
  return;
5096
5397
  case "status":
5097
- await invocationHandlers.status(runtime, invocation);
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 (typeof parsed.value.apiKey === "string" && parsed.value.apiKey.length > 0) {
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 hasBaseUrlOverride = typeof env["OGMENT_BASE_URL"] === "string";
9766
+ const envBaseUrl = env["OGMENT_BASE_URL"];
9767
+ const hasBaseUrlOverride = typeof envBaseUrl === "string";
9535
9768
  return {
9536
- baseUrl: env["OGMENT_BASE_URL"] ?? DEFAULT_OGMENT_BASE_URL,
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
- if (this.#mode === "json") {
9777
- this.#stdout.write(toJson(envelope));
9778
- return envelope;
9779
- }
9780
- this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
9781
- return envelope;
9782
- }
9783
- info(message) {
9784
- if (this.#debug) this.#stderr.write(`${message}\n`);
9785
- }
9786
- json(value) {
9787
- this.#stdout.write(toJson(value));
9788
- }
9789
- success(data, options) {
9790
- const envelope = this.#envelopeBuilder.success(data, {
9791
- ...options,
9792
- includeDebug: this.#debug
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
- if (this.#mode === "json") {
9795
- this.#stdout.write(toJson(envelope));
9796
- return;
9797
- }
9798
- this.#stdout.write(toJson(toMinimalEnvelope(envelope)));
9799
- }
9800
- writeStdout(chunk) {
9801
- this.#stdout.write(chunk);
9802
- }
9803
- writeStderr(chunk) {
9804
- this.#stderr.write(chunk);
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 fetchAccountOnce = async (apiKey) => {
9818
- const responseResult = await deps.httpClient.request(toEndpointUrl$1(deps.baseUrl, cliEndpoints.accountMe), { headers: authHeader(apiKey) });
9819
- if (Result.isError(responseResult)) return responseResult;
9820
- if (!responseResult.value.ok) {
9821
- if (responseResult.value.status === 401) return Result.err(new AuthError({
9822
- code: ERROR_CODE.authInvalidCredentials,
9823
- message: "Authentication failed. Run `ogment auth login` again.",
9824
- recovery: { command: "ogment auth login" }
9825
- }));
9826
- const body = await readResponseText(responseResult.value);
9827
- return Result.err(new RemoteRequestError({
9828
- body,
9829
- httpStatus: responseResult.value.status,
9830
- message: "Failed to fetch account details",
9831
- operation: "account/fetch",
9832
- raw: body,
9833
- source: "http"
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(jsonResult)) return jsonResult;
9846
- const parsed = parseWithSchema(accountMeSchema, jsonResult.value, "account response");
9847
- if (Result.isError(parsed)) return parsed;
9848
- return Result.ok(parsed.value.data);
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
- fetchAccount,
9853
- listServers: async (apiKey) => {
9854
- const profileResult = await fetchAccount(apiKey);
9855
- if (Result.isError(profileResult)) return profileResult;
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 startFlowResponse = await requestRemote(deviceCodeUrl(deps.baseUrl), {
10087
+ const startPayload = await requestJson(deps.httpClient, deviceCodeUrl(deps.baseUrl), deviceCodeStartSchema, {
9899
10088
  headers: { "Content-Type": "application/json" },
9900
10089
  method: "POST"
9901
- });
9902
- if (Result.isError(startFlowResponse)) return startFlowResponse;
9903
- if (!startFlowResponse.value.ok) {
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: startFlowResponse.value.status,
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
- try: async () => startFlowResponse.value.json()
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: parsedStartPayload.value.data.userCode,
9928
- verificationUri: parsedStartPayload.value.data.verificationUri
10104
+ userCode: startPayload.value.data.userCode,
10105
+ verificationUri: startPayload.value.data.verificationUri
9929
10106
  });
9930
- const deadline = now() + parsedStartPayload.value.data.expiresIn * 1e3;
9931
- const interval = parsedStartPayload.value.data.interval * 1e3;
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 pollResponse = await requestRemote(deviceTokenUrl(deps.baseUrl), {
9935
- body: JSON.stringify({ deviceCode: parsedStartPayload.value.data.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
- if (Result.isError(pollResponse)) return pollResponse;
9940
- if (pollResponse.value.status === 410) return Result.err(new AuthError({
9941
- code: ERROR_CODE.authDeviceExpired,
9942
- message: "Device login code expired. Run `ogment auth login` again.",
9943
- recovery: { command: "ogment auth login" }
9944
- }));
9945
- if (pollResponse.value.status === 404) return Result.err(new AuthError({
9946
- code: ERROR_CODE.authInvalidCredentials,
9947
- message: "Invalid device login code. Run `ogment auth login` again.",
9948
- recovery: { command: "ogment auth login" }
9949
- }));
9950
- if (!pollResponse.value.ok) {
9951
- const body = await readResponseText(pollResponse.value);
9952
- return Result.err(new RemoteRequestError({
9953
- body,
9954
- httpStatus: pollResponse.value.status,
9955
- message: "Failed to poll device login status",
9956
- operation: "auth/device/poll",
9957
- raw: body,
9958
- source: "http"
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
- const parsedTokenPayload = parseWithSchema(deviceTokenSchema, pollPayload.value, "device login poll response");
9972
- if (Result.isError(parsedTokenPayload)) return parsedTokenPayload;
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 requestRemote(revokeUrl(deps.baseUrl), {
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
- if (typeof overrideApiKey === "string" && overrideApiKey.length > 0) return Result.ok(overrideApiKey);
10041
- if (typeof deps.envApiKey === "string" && deps.envApiKey.length > 0) return Result.ok(deps.envApiKey);
10042
- const stored = deps.credentialsStore.load();
10043
- if (Result.isError(stored)) return stored;
10044
- if (stored.value !== null) return Result.ok(stored.value.apiKey);
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
- if (typeof overrideApiKey === "string" && overrideApiKey.length > 0) return Result.ok({
10053
- agentName: null,
10054
- apiKeySource: "apiKeyOption",
10055
- loggedIn: true
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
- const stored = deps.credentialsStore.load();
10063
- if (Result.isError(stored)) return stored;
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: stored.value.agentName ?? null,
10071
- apiKeySource: "credentialsFile",
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 resolveApiKey = (apiKeyOverride, envApiKey, credentialsStore) => {
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
- loadError: null,
10108
- source: "none",
10109
- value: null
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 nextActionByIssueCode = {
10113
- auth_failed: "Run `ogment auth login` to refresh credentials.",
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 = nextActionByIssueCode[issue.code];
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 apiKeyResolution = resolveApiKey(apiKeyOverride, deps.envApiKey, deps.credentialsStore);
10147
- const selectedApiKey = apiKeyResolution.value;
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>/<tool-name> --input '{}'"
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
- try {
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 parsedBody = body === void 0 ? null : (() => {
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
- ...jsonRpcPayload === null ? {} : { mcpCode: jsonRpcPayload.code },
20970
- ...jsonRpcPayload === null ? {} : { mcpData: jsonRpcPayload.data },
20971
- raw: jsonRpcPayload?.raw ?? toSerializable(parsedBody ?? error),
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: "ogment-cli",
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
- }, CompatibilityCallToolResultSchema, { timeout: MCP_INVOKE_TIMEOUT_MS });
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 parseToolCallContent(toolCallResult.value);
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
- const parsedToolsResult = parseWithSchema(ListToolsResultSchema, toolsResult.value, "MCP tools/list response", {
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/create_invoice --input '{\"amount\":100}'",
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)").optionsGroup("Automation Options:").option("--yes", "Assume yes for any confirmation").hook("preAction", (thisCommand) => {
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
- limit: options.limit,
21298
- serverId,
21299
- toolName
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>/<tool-name>").description("Invoke a tool using <server-id>/<tool-name>").helpGroup("Execution Commands:").argument("<target>", "Target tool in the form <server-id>/<tool-name>", parseInvokeTarget).option("--input <value>", "Input payload: inline JSON object, @path, or - for stdin").action((target, options) => {
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
- target
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 = createRuntime()) => {
21393
+ const runCli = async (argv = process.argv.slice(2), runtime = void 0) => {
21333
21394
  const normalizedArgv = normalizeCliArgv(argv);
21334
- runtime.output.configure(parseOutputOptionsFromArgv(normalizedArgv));
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(runtime, parseState);
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(runtime, invocation);
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: runtime.output.debug });
21347
- runtime.output.parseError(parseError.payload, {
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
- runtime.output.error(normalized, {
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 };