@ogment-ai/cli 0.9.1 → 0.10.0-beta.1

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
@@ -7998,26 +7998,26 @@ const toJsonValue = (value) => {
7998
7998
  //#region src/shared/recovery.ts
7999
7999
  const defaultRecoveryByCode = {
8000
8000
  [ERROR_CODE.authDeviceExpired]: {
8001
- command: "ogment auth login",
8002
- reason: "Device code expired; restart login to continue.",
8001
+ command: "ogment login",
8002
+ reason: "Login request expired; start login again to continue.",
8003
8003
  title: "Restart login",
8004
8004
  when: "immediate"
8005
8005
  },
8006
8006
  [ERROR_CODE.authDevicePending]: {
8007
- command: "ogment auth status",
8008
- reason: "Authorization is pending; check whether credentials are now available.",
8009
- title: "Check auth status",
8007
+ command: "ogment login",
8008
+ reason: "Authorization is pending; run login again after approving in the browser.",
8009
+ title: "Complete login",
8010
8010
  when: "immediate"
8011
8011
  },
8012
8012
  [ERROR_CODE.authInvalidCredentials]: {
8013
- command: "ogment auth logout",
8014
- reason: "Credentials are invalid; clear local state before re-authenticating.",
8015
- title: "Reset auth state",
8013
+ command: "ogment login",
8014
+ reason: "Credentials are invalid; sign in again to restore the local CLI session.",
8015
+ title: "Sign in again",
8016
8016
  when: "immediate"
8017
8017
  },
8018
8018
  [ERROR_CODE.authRequired]: {
8019
- command: "ogment auth login",
8020
- reason: "Authentication is required before catalog or invoke commands can run.",
8019
+ command: "ogment login",
8020
+ reason: "Authentication is required before catalog, search, or execute commands can run.",
8021
8021
  title: "Authenticate",
8022
8022
  when: "immediate"
8023
8023
  },
@@ -8053,14 +8053,14 @@ const defaultRecoveryByCode = {
8053
8053
  },
8054
8054
  [ERROR_CODE.toolInputSchemaViolation]: {
8055
8055
  command: "ogment catalog",
8056
- reason: "Tool contract did not validate; inspect available servers and tool metadata.",
8056
+ reason: "Tool contract did not validate; inspect available servers before retrying search or execute.",
8057
8057
  title: "Inspect catalog",
8058
8058
  when: "immediate"
8059
8059
  },
8060
8060
  [ERROR_CODE.toolNotFound]: {
8061
8061
  command: "ogment catalog",
8062
- reason: "Requested tool could not be found; rediscover servers and tools.",
8063
- title: "Rediscover tools",
8062
+ reason: "Requested server or tool context could not be found; rediscover available servers.",
8063
+ title: "Rediscover servers",
8064
8064
  when: "immediate"
8065
8065
  },
8066
8066
  [ERROR_CODE.transportRequestFailed]: {
@@ -8363,40 +8363,59 @@ const parseJsonValue = (raw, context) => {
8363
8363
  }
8364
8364
  });
8365
8365
  };
8366
- const isRecord$2 = (value) => {
8366
+ const isRecord$1 = (value) => {
8367
8367
  return typeof value === "object" && value !== null;
8368
8368
  };
8369
8369
 
8370
- //#endregion
8371
- //#region src/shared/schemas.ts
8372
- const credentialsFileSchema = object({
8373
- agentName: string().optional(),
8374
- apiKey: string().min(1).optional()
8375
- });
8376
-
8377
8370
  //#endregion
8378
8371
  //#region src/infra/credentials.ts
8379
8372
  const authStateFileSchema = object({
8373
+ currentAuthRequest: object({
8374
+ authRequestId: string().min(1),
8375
+ expiresAt: string().min(1),
8376
+ verificationUrl: string().min(1)
8377
+ }).nullable().optional(),
8378
+ installationId: uuid(),
8379
+ session: object({
8380
+ agentId: uuid(),
8381
+ agentName: string().min(1),
8382
+ apiKey: string().min(1),
8383
+ credentialId: uuid(),
8384
+ signedInAt: string().min(1)
8385
+ }).nullable().optional(),
8386
+ version: literal(3)
8387
+ }).strict();
8388
+ const authStateFileV2Schema = object({
8389
+ installationId: uuid(),
8390
+ pendingAuthRequest: object({
8391
+ authRequestId: string().min(1),
8392
+ expiresAt: string().min(1),
8393
+ verificationUrl: string().min(1)
8394
+ }).nullable().optional(),
8395
+ session: object({
8396
+ agentId: uuid(),
8397
+ agentName: string().min(1),
8398
+ apiKey: string().min(1),
8399
+ credentialId: uuid(),
8400
+ signedInAt: string().min(1)
8401
+ }).nullable().optional(),
8402
+ version: literal(2)
8403
+ }).strict();
8404
+ const legacyAuthStateFileSchema = object({
8380
8405
  activeAuth: object({
8381
8406
  agentName: string().optional(),
8382
8407
  apiKey: string().min(1),
8383
- boundAt: string().optional(),
8384
- namespaceKey: string().min(1).optional(),
8385
- scopeFingerprint: string().min(1).optional()
8408
+ boundAt: string().optional()
8386
8409
  }).nullable().optional(),
8387
8410
  installationId: uuid(),
8388
8411
  pendingRequests: array(object({
8389
8412
  authRequestId: string().min(1),
8390
- code: string().min(1),
8391
8413
  createdAt: string().min(1),
8392
8414
  expiresAt: string().min(1),
8393
- namespaceKey: string().min(1),
8394
- scopeFingerprint: string().min(1).optional(),
8395
8415
  verificationUrl: string().min(1)
8396
8416
  })).optional(),
8397
8417
  version: literal(1)
8398
8418
  }).strict();
8399
- const telemetryInstallationSchema = object({ installationId: uuid() }).strict();
8400
8419
  const LOCK_RETRY_DELAY_MS = 10;
8401
8420
  const LOCK_STALE_MS = 3e4;
8402
8421
  const LOCK_TIMEOUT_MS = 2e3;
@@ -8405,40 +8424,42 @@ const sleepBlocking = (milliseconds) => {
8405
8424
  const view = new Int32Array(buffer);
8406
8425
  Atomics.wait(view, 0, 0, milliseconds);
8407
8426
  };
8408
- const normalizeCredentials = (value) => {
8409
- const parsed = parseWithSchema(credentialsFileSchema, value, "legacy credentials file");
8410
- if (Result.isError(parsed) || parsed.value.apiKey === void 0) return null;
8411
- return {
8412
- ...parsed.value.agentName === void 0 ? {} : { agentName: parsed.value.agentName },
8413
- apiKey: parsed.value.apiKey
8414
- };
8415
- };
8416
8427
  const normalizeAuthState = (value) => {
8417
- const parsed = parseWithSchema(authStateFileSchema, value, "auth state file");
8418
- if (Result.isError(parsed)) return null;
8419
- const activeAuth = parsed.value.activeAuth === void 0 || parsed.value.activeAuth === null ? null : {
8420
- ...parsed.value.activeAuth.agentName === void 0 ? {} : { agentName: parsed.value.activeAuth.agentName },
8421
- apiKey: parsed.value.activeAuth.apiKey,
8422
- ...parsed.value.activeAuth.boundAt === void 0 ? {} : { boundAt: parsed.value.activeAuth.boundAt },
8423
- ...parsed.value.activeAuth.namespaceKey === void 0 ? {} : { namespaceKey: parsed.value.activeAuth.namespaceKey },
8424
- ...parsed.value.activeAuth.scopeFingerprint === void 0 ? {} : { scopeFingerprint: parsed.value.activeAuth.scopeFingerprint }
8425
- };
8426
- const pendingRequests = (parsed.value.pendingRequests ?? []).map((request) => {
8427
- return {
8428
- authRequestId: request.authRequestId,
8429
- code: request.code,
8430
- createdAt: request.createdAt,
8431
- expiresAt: request.expiresAt,
8432
- namespaceKey: request.namespaceKey,
8433
- ...request.scopeFingerprint === void 0 ? {} : { scopeFingerprint: request.scopeFingerprint },
8434
- verificationUrl: request.verificationUrl
8435
- };
8436
- });
8428
+ const parsedCurrentState = parseWithSchema(authStateFileSchema, value, "auth state file");
8429
+ if (Result.isOk(parsedCurrentState)) return {
8430
+ needsMigration: false,
8431
+ state: {
8432
+ currentAuthRequest: parsedCurrentState.value.currentAuthRequest ?? null,
8433
+ installationId: parsedCurrentState.value.installationId,
8434
+ session: parsedCurrentState.value.session ?? null,
8435
+ version: 3
8436
+ }
8437
+ };
8438
+ const parsedLegacyV2State = parseWithSchema(authStateFileV2Schema, value, "auth state v2 file");
8439
+ if (Result.isOk(parsedLegacyV2State)) return {
8440
+ needsMigration: true,
8441
+ state: {
8442
+ currentAuthRequest: parsedLegacyV2State.value.pendingAuthRequest ?? null,
8443
+ installationId: parsedLegacyV2State.value.installationId,
8444
+ session: parsedLegacyV2State.value.session ?? null,
8445
+ version: 3
8446
+ }
8447
+ };
8448
+ const parsedV1 = parseWithSchema(legacyAuthStateFileSchema, value, "legacy auth state file");
8449
+ if (Result.isError(parsedV1)) return null;
8450
+ const latestPendingRequest = (parsedV1.value.pendingRequests ?? []).at(-1);
8437
8451
  return {
8438
- activeAuth,
8439
- installationId: parsed.value.installationId,
8440
- pendingRequests,
8441
- version: 1
8452
+ needsMigration: true,
8453
+ state: {
8454
+ currentAuthRequest: latestPendingRequest === void 0 ? null : {
8455
+ authRequestId: latestPendingRequest.authRequestId,
8456
+ expiresAt: latestPendingRequest.expiresAt,
8457
+ verificationUrl: latestPendingRequest.verificationUrl
8458
+ },
8459
+ installationId: parsedV1.value.installationId,
8460
+ session: null,
8461
+ version: 3
8462
+ }
8442
8463
  };
8443
8464
  };
8444
8465
  const toCorruptPath = (path, nowFn) => {
@@ -8473,29 +8494,12 @@ const createFileCredentialsStore = (deps) => {
8473
8494
  const unlinkSyncFn = deps.unlinkSyncFn ?? unlinkSync;
8474
8495
  const writeFileSyncFn = deps.writeFileSyncFn ?? writeFileSync;
8475
8496
  const lockPath = `${deps.credentialsPath}.lock`;
8476
- const readJsonFile = (path) => {
8477
- if (!existsSyncFn(path)) return null;
8478
- try {
8479
- return JSON.parse(readFileSyncFn(path, "utf8"));
8480
- } catch {
8481
- return null;
8482
- }
8483
- };
8484
- const readLegacyCredentials = () => {
8485
- return normalizeCredentials(readJsonFile(deps.legacyCredentialsPath));
8486
- };
8487
- const readLegacyInstallationId = () => {
8488
- const raw = readJsonFile(deps.telemetryPath);
8489
- if (raw === null) return null;
8490
- const parsed = telemetryInstallationSchema.safeParse(raw);
8491
- return parsed.success ? parsed.data.installationId : null;
8492
- };
8493
8497
  const createEmptyState = (installationId = randomUuidFn()) => {
8494
8498
  return {
8495
- activeAuth: null,
8499
+ currentAuthRequest: null,
8496
8500
  installationId,
8497
- pendingRequests: [],
8498
- version: 1
8501
+ session: null,
8502
+ version: 3
8499
8503
  };
8500
8504
  };
8501
8505
  const withLock = (operation) => {
@@ -8588,43 +8592,33 @@ const createFileCredentialsStore = (deps) => {
8588
8592
  }
8589
8593
  throw error;
8590
8594
  }
8591
- const parsed = normalizeAuthState(parsedJson);
8592
- if (parsed === null) {
8595
+ const normalized = normalizeAuthState(parsedJson);
8596
+ if (normalized === null) {
8593
8597
  quarantineCorruptState();
8594
8598
  return null;
8595
8599
  }
8596
- return parsed;
8597
- };
8598
- const migrateStateFromLegacy = () => {
8599
- const migratedInstallationId = readLegacyInstallationId();
8600
- const migratedCredentials = readLegacyCredentials();
8601
- if (!(migratedInstallationId !== null || migratedCredentials !== null)) return null;
8602
- return {
8603
- ...createEmptyState(migratedInstallationId ?? randomUuidFn()),
8604
- ...migratedCredentials === null ? {} : { activeAuth: migratedCredentials }
8605
- };
8600
+ return normalized;
8606
8601
  };
8607
8602
  const loadState = (options) => {
8608
8603
  const currentState = loadStateFromDisk();
8609
- if (currentState !== null) return currentState;
8610
- const migratedState = migrateStateFromLegacy();
8611
- if (migratedState !== null) {
8612
- withLock(() => {
8613
- if (!existsSyncFn(deps.credentialsPath)) writeState(migratedState);
8604
+ if (currentState !== null) {
8605
+ if (currentState.needsMigration) withLock(() => {
8606
+ const latest = loadStateFromDisk();
8607
+ if (latest?.needsMigration) writeState(latest.state);
8614
8608
  });
8615
- return loadStateFromDisk() ?? migratedState;
8609
+ return currentState.state;
8616
8610
  }
8617
8611
  if (options?.persistIfMissing === true) {
8618
8612
  const emptyState = createEmptyState();
8619
8613
  withLock(() => {
8620
8614
  if (!existsSyncFn(deps.credentialsPath)) writeState(emptyState);
8621
8615
  });
8622
- return loadStateFromDisk() ?? emptyState;
8616
+ return loadStateFromDisk()?.state ?? emptyState;
8623
8617
  }
8624
8618
  return null;
8625
8619
  };
8626
8620
  return {
8627
- clearPendingRequests: (namespaceKey) => {
8621
+ clearCurrentAuthRequest: () => {
8628
8622
  return Result.try({
8629
8623
  catch: (cause) => new UnexpectedError({
8630
8624
  cause,
@@ -8632,10 +8626,9 @@ const createFileCredentialsStore = (deps) => {
8632
8626
  }),
8633
8627
  try: () => {
8634
8628
  withLock(() => {
8635
- const latest = loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState();
8636
8629
  writeState({
8637
- ...latest,
8638
- pendingRequests: namespaceKey === void 0 ? [] : latest.pendingRequests.filter((request) => request.namespaceKey !== namespaceKey)
8630
+ ...loadStateFromDisk()?.state ?? createEmptyState(),
8631
+ currentAuthRequest: null
8639
8632
  });
8640
8633
  });
8641
8634
  }
@@ -8650,27 +8643,22 @@ const createFileCredentialsStore = (deps) => {
8650
8643
  try: () => {
8651
8644
  withLock(() => {
8652
8645
  writeState({
8653
- ...loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState(),
8654
- activeAuth: null,
8655
- pendingRequests: []
8646
+ ...loadStateFromDisk()?.state ?? createEmptyState(),
8647
+ session: null
8656
8648
  });
8657
8649
  });
8658
8650
  }
8659
8651
  });
8660
8652
  },
8661
- deletePendingRequest: (authRequestId) => {
8653
+ reset: () => {
8662
8654
  return Result.try({
8663
8655
  catch: (cause) => new UnexpectedError({
8664
8656
  cause,
8665
- message: "Failed to update local auth state"
8657
+ message: "Failed to reset local auth state"
8666
8658
  }),
8667
8659
  try: () => {
8668
8660
  withLock(() => {
8669
- const latest = loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState();
8670
- writeState({
8671
- ...latest,
8672
- pendingRequests: latest.pendingRequests.filter((request) => request.authRequestId !== authRequestId)
8673
- });
8661
+ writeState(createEmptyState());
8674
8662
  });
8675
8663
  }
8676
8664
  });
@@ -8688,14 +8676,14 @@ const createFileCredentialsStore = (deps) => {
8688
8676
  }
8689
8677
  });
8690
8678
  },
8691
- listPendingRequests: () => {
8679
+ getCurrentAuthRequest: () => {
8692
8680
  return Result.try({
8693
8681
  catch: (cause) => new UnexpectedError({
8694
8682
  cause,
8695
8683
  message: "Failed to load local auth state"
8696
8684
  }),
8697
8685
  try: () => {
8698
- return loadState()?.pendingRequests ?? [];
8686
+ return loadState()?.currentAuthRequest ?? null;
8699
8687
  }
8700
8688
  });
8701
8689
  },
@@ -8706,12 +8694,7 @@ const createFileCredentialsStore = (deps) => {
8706
8694
  message: "Failed to load local auth state"
8707
8695
  }),
8708
8696
  try: () => {
8709
- const state = loadState();
8710
- if (state?.activeAuth === null || state === null) return null;
8711
- return {
8712
- ...state.activeAuth.agentName === void 0 ? {} : { agentName: state.activeAuth.agentName },
8713
- apiKey: state.activeAuth.apiKey
8714
- };
8697
+ return loadState()?.session ?? null;
8715
8698
  }
8716
8699
  });
8717
8700
  },
@@ -8724,40 +8707,15 @@ const createFileCredentialsStore = (deps) => {
8724
8707
  try: () => {
8725
8708
  withLock(() => {
8726
8709
  writeState({
8727
- ...loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState(),
8728
- activeAuth: {
8729
- ...credentials.agentName === void 0 ? {} : { agentName: credentials.agentName },
8730
- apiKey: credentials.apiKey
8731
- }
8732
- });
8733
- });
8734
- }
8735
- });
8736
- },
8737
- storeApprovedAuth: (credentials, namespaceKey) => {
8738
- return Result.try({
8739
- catch: (cause) => new UnexpectedError({
8740
- cause,
8741
- message: "Failed to update local auth state"
8742
- }),
8743
- try: () => {
8744
- withLock(() => {
8745
- const currentState = loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState();
8746
- writeState({
8747
- ...currentState,
8748
- activeAuth: {
8749
- ...credentials.agentName === void 0 ? {} : { agentName: credentials.agentName },
8750
- apiKey: credentials.apiKey,
8751
- boundAt: nowFn().toISOString(),
8752
- ...namespaceKey === void 0 ? {} : { namespaceKey }
8753
- },
8754
- pendingRequests: namespaceKey === void 0 ? [] : currentState.pendingRequests.filter((request) => request.namespaceKey !== namespaceKey)
8710
+ ...loadStateFromDisk()?.state ?? createEmptyState(),
8711
+ currentAuthRequest: null,
8712
+ session: credentials
8755
8713
  });
8756
8714
  });
8757
8715
  }
8758
8716
  });
8759
8717
  },
8760
- savePendingRequest: (request) => {
8718
+ saveCurrentAuthRequest: (request) => {
8761
8719
  return Result.try({
8762
8720
  catch: (cause) => new UnexpectedError({
8763
8721
  cause,
@@ -8765,20 +8723,13 @@ const createFileCredentialsStore = (deps) => {
8765
8723
  }),
8766
8724
  try: () => {
8767
8725
  withLock(() => {
8768
- const currentState = loadStateFromDisk() ?? migrateStateFromLegacy() ?? createEmptyState();
8769
- const pendingRequests = currentState.pendingRequests.filter((entry) => entry.authRequestId !== request.authRequestId);
8770
- pendingRequests.push({
8771
- authRequestId: request.authRequestId,
8772
- code: request.code,
8773
- createdAt: request.createdAt,
8774
- expiresAt: request.expiresAt,
8775
- namespaceKey: request.namespaceKey,
8776
- ...request.scopeFingerprint === void 0 ? {} : { scopeFingerprint: request.scopeFingerprint },
8777
- verificationUrl: request.verificationUrl
8778
- });
8779
8726
  writeState({
8780
- ...currentState,
8781
- pendingRequests
8727
+ ...loadStateFromDisk()?.state ?? createEmptyState(),
8728
+ currentAuthRequest: {
8729
+ authRequestId: request.authRequestId,
8730
+ expiresAt: request.expiresAt,
8731
+ verificationUrl: request.verificationUrl
8732
+ }
8782
8733
  });
8783
8734
  });
8784
8735
  }
@@ -8798,9 +8749,9 @@ const DEFAULT_OGMENT_BASE_URL = "https://dashboard.ogment.ai";
8798
8749
  * These are injected by Rolldown `transform.define` during release builds.
8799
8750
  * Runtime env vars (`OGMENT_CLI_SENTRY_*`) can still override them.
8800
8751
  */
8801
- const SENTRY_DSN_BUILD = "https://4219ab98670b61086758b4d0e31ae318@o4507724844957696.ingest.us.sentry.io/4510992932405248";
8802
- const SENTRY_ENVIRONMENT_BUILD = "production";
8803
- const SENTRY_RELEASE_BUILD = "cli-v0.9.1+git:99e999ee0";
8752
+ const SENTRY_DSN_BUILD = void 0;
8753
+ const SENTRY_ENVIRONMENT_BUILD = void 0;
8754
+ const SENTRY_RELEASE_BUILD = void 0;
8804
8755
  const packageJsonSchema = object({ version: string().min(1) });
8805
8756
  const hasCode = (value, code) => {
8806
8757
  if (typeof value !== "object" || value === null) return false;
@@ -8859,14 +8810,17 @@ const telemetryRuntimeFields = (env, configDir) => {
8859
8810
  credentialsPath: join(configDir, "auth-state.json"),
8860
8811
  envApiKey: env["OGMENT_API_KEY"],
8861
8812
  executionEnvironment: detectExecutionEnvironment(env),
8862
- legacyCredentialsPath: join(configDir, "credentials.json"),
8863
8813
  telemetryDisabled: telemetryDisabledFromEnv(env),
8864
- telemetryPath: join(configDir, "telemetry.json"),
8865
8814
  version: VERSION$2
8866
8815
  };
8867
8816
  };
8817
+ const resolveConfigDir = (env, homeDirectory) => {
8818
+ const configuredDir = env["OGMENT_CONFIG_DIR"]?.trim();
8819
+ if (configuredDir && configuredDir.length > 0) return configuredDir;
8820
+ return join(homeDirectory, ".config", "ogment");
8821
+ };
8868
8822
  const createRuntimeConfig = (env = process.env, homeDirectory = homedir()) => {
8869
- const configDir = join(homeDirectory, ".config", "ogment");
8823
+ const configDir = resolveConfigDir(env, homeDirectory);
8870
8824
  const envBaseUrl = env["OGMENT_BASE_URL"];
8871
8825
  const hasBaseUrlOverride = typeof envBaseUrl === "string";
8872
8826
  return {
@@ -8884,7 +8838,7 @@ const createRuntimeConfig = (env = process.env, homeDirectory = homedir()) => {
8884
8838
  };
8885
8839
  };
8886
8840
  const createTelemetryRuntimeConfig = (env = process.env, homeDirectory = homedir()) => {
8887
- const configDir = join(homeDirectory, ".config", "ogment");
8841
+ const configDir = resolveConfigDir(env, homeDirectory);
8888
8842
  const parsedBaseUrl = baseUrlSchema.safeParse(env["OGMENT_BASE_URL"]);
8889
8843
  return {
8890
8844
  baseUrl: parsedBaseUrl.success ? parsedBaseUrl.data : DEFAULT_OGMENT_BASE_URL,
@@ -13854,7 +13808,7 @@ const parseRemoteErrorDetails = (payload) => {
13854
13808
  }
13855
13809
  return { message: trimmed };
13856
13810
  }
13857
- if (!isRecord$2(payload)) return {};
13811
+ if (!isRecord$1(payload)) return {};
13858
13812
  const directCode = payload["code"];
13859
13813
  const directMessage = payload["message"];
13860
13814
  if (typeof directCode === "number" || typeof directMessage === "string") return {
@@ -13863,7 +13817,7 @@ const parseRemoteErrorDetails = (payload) => {
13863
13817
  ...Object.hasOwn(payload, "data") ? { data: toJsonValue(payload["data"]) } : {}
13864
13818
  };
13865
13819
  const nestedError = payload["error"];
13866
- if (!isRecord$2(nestedError)) return {};
13820
+ if (!isRecord$1(nestedError)) return {};
13867
13821
  return {
13868
13822
  ...typeof nestedError["code"] === "number" ? { mcpCode: nestedError["code"] } : {},
13869
13823
  ...typeof nestedError["message"] === "string" ? { message: nestedError["message"] } : {},
@@ -13954,17 +13908,6 @@ const presentRuntimeErrorPayload = (error, options) => {
13954
13908
  title: appErrorTitle(error)
13955
13909
  };
13956
13910
  };
13957
- const presentCatalogFailureError = (error, options) => {
13958
- const payload = presentRuntimeErrorPayload(error, options);
13959
- return {
13960
- code: payload.code,
13961
- detail: payload.detail,
13962
- diagnostics: payload.diagnostics,
13963
- ...payload.related_codes === void 0 ? {} : { related_codes: payload.related_codes },
13964
- retryable: payload.retryable,
13965
- title: payload.title
13966
- };
13967
- };
13968
13911
 
13969
13912
  //#endregion
13970
13913
  //#region src/output/envelope.ts
@@ -14151,7 +14094,13 @@ const cliOrgSchema = object({
14151
14094
  role: string(),
14152
14095
  servers: array(cliServerSchema)
14153
14096
  }).strict();
14097
+ const cliActingAgentSchema = object({
14098
+ agentId: string().uuid(),
14099
+ agentName: string().min(1),
14100
+ boundInstallationId: string().uuid().nullable()
14101
+ }).strict();
14154
14102
  const cliMeDataSchema = object({
14103
+ actingAgent: cliActingAgentSchema.nullable(),
14155
14104
  email: string().nullable(),
14156
14105
  imageUrl: string().nullable(),
14157
14106
  name: string().nullable(),
@@ -14162,78 +14111,67 @@ const accountMeSchema = cliSuccessEnvelopeSchema(cliMeDataSchema);
14162
14111
 
14163
14112
  //#endregion
14164
14113
  //#region ../../packages/shared/src/cli/auth.ts
14165
- const deviceCodeStartDataSchema = object({
14166
- deviceCode: string().min(1),
14167
- expiresIn: number$1().int().positive(),
14168
- interval: number$1().int().positive(),
14169
- userCode: string().min(1),
14170
- verificationUri: string().url()
14171
- }).strict();
14172
- const deviceCodeStartSchema = cliSuccessEnvelopeSchema(deviceCodeStartDataSchema);
14173
14114
  const authStartDataSchema = object({
14174
14115
  authRequestId: string().min(1),
14116
+ disposition: _enum([
14117
+ "created",
14118
+ "reused_approved",
14119
+ "reused_pending"
14120
+ ]),
14175
14121
  expiresAt: isoTimestampSchema,
14176
- userCode: string().min(1),
14177
14122
  verificationUrl: string().url()
14178
14123
  }).strict();
14179
14124
  const authStartSchema = cliSuccessEnvelopeSchema(authStartDataSchema);
14180
- const deviceTokenPendingDataSchema = object({ status: literal("authorization_pending") }).strict();
14181
- const deviceTokenApprovedDataSchema = object({
14182
- agentName: string().min(1),
14183
- apiKey: string().min(1),
14184
- status: literal("approved")
14185
- }).strict();
14186
- const deviceTokenDataSchema = discriminatedUnion("status", [deviceTokenPendingDataSchema, deviceTokenApprovedDataSchema]);
14187
- const deviceTokenSchema = cliSuccessEnvelopeSchema(deviceTokenDataSchema);
14188
- const deviceTokenApprovedSchema = cliSuccessEnvelopeSchema(deviceTokenApprovedDataSchema);
14189
14125
  const authExchangePendingDataSchema = object({ status: literal("authorization_pending") }).strict();
14190
14126
  const authExchangeApprovedDataSchema = object({
14127
+ agentId: string().uuid(),
14191
14128
  agentName: string().min(1),
14192
14129
  apiKey: string().min(1),
14193
- scopeFingerprint: string().min(1),
14130
+ credentialId: string().uuid(),
14194
14131
  status: literal("approved")
14195
14132
  }).strict();
14196
14133
  const authExchangeExpiredDataSchema = object({ status: literal("expired") }).strict();
14197
- const authExchangeDeniedDataSchema = object({ status: literal("denied") }).strict();
14198
- const authExchangeConflictDataSchema = object({ status: literal("conflict") }).strict();
14199
14134
  const authExchangeInvalidDataSchema = object({ status: literal("invalid") }).strict();
14135
+ const authExchangeSupersededDataSchema = object({ status: literal("superseded") }).strict();
14200
14136
  const authExchangeDataSchema = discriminatedUnion("status", [
14201
14137
  authExchangePendingDataSchema,
14202
14138
  authExchangeApprovedDataSchema,
14203
14139
  authExchangeExpiredDataSchema,
14204
- authExchangeDeniedDataSchema,
14205
- authExchangeConflictDataSchema,
14206
- authExchangeInvalidDataSchema
14140
+ authExchangeInvalidDataSchema,
14141
+ authExchangeSupersededDataSchema
14207
14142
  ]);
14208
14143
  const authExchangeSchema = cliSuccessEnvelopeSchema(authExchangeDataSchema);
14209
14144
  const authExchangeApprovedSchema = cliSuccessEnvelopeSchema(authExchangeApprovedDataSchema);
14210
- const revokeSelfDataSchema = object({ success: literal(true) }).strict();
14211
- const revokeSelfSchema = cliSuccessEnvelopeSchema(revokeSelfDataSchema);
14145
+ const authMutationSuccessDataSchema = object({ success: literal(true) }).strict();
14146
+ const authLogoutDataSchema = authMutationSuccessDataSchema;
14147
+ const authLogoutSchema = cliSuccessEnvelopeSchema(authLogoutDataSchema);
14148
+ const authResetDataSchema = authMutationSuccessDataSchema;
14149
+ const authResetSchema = cliSuccessEnvelopeSchema(authResetDataSchema);
14212
14150
 
14213
14151
  //#endregion
14214
14152
  //#region ../../packages/shared/src/cli/endpoints.ts
14215
14153
  const cliEndpoints = {
14216
14154
  accountMe: "/api/v1/cli/me",
14217
- authExchange: "/api/v1/cli/auth/exchange",
14218
14155
  authStart: "/api/v1/cli/auth/start",
14219
- cliRevokeSelf: "/api/v1/cli/revoke-self",
14220
- deviceCode: "/api/v1/cli/device-code",
14221
- deviceToken: "/api/v1/cli/device-token",
14156
+ authExchange: "/api/v1/cli/auth/exchange",
14157
+ authLogout: "/api/v1/cli/auth/logout",
14158
+ authReset: "/api/v1/cli/auth/reset",
14222
14159
  telemetry: "/api/v1/cli/telemetry"
14223
14160
  };
14224
14161
 
14225
14162
  //#endregion
14226
14163
  //#region ../../packages/shared/src/cli/telemetry.ts
14227
14164
  const cliCommandKindSchema = _enum([
14228
- "auth_login",
14229
- "auth_logout",
14230
- "auth_status",
14165
+ "login",
14166
+ "logout",
14167
+ "reset",
14168
+ "catalog_detail",
14231
14169
  "catalog_summary",
14232
- "catalog_tool",
14233
- "catalog_tools",
14234
- "invoke",
14170
+ "catalog_tool_detail",
14171
+ "execute",
14235
14172
  "parse_error",
14236
14173
  "root",
14174
+ "search",
14237
14175
  "runtime_error",
14238
14176
  "status"
14239
14177
  ]);
@@ -14378,28 +14316,29 @@ const exitCodeForError = (error) => {
14378
14316
 
14379
14317
  //#endregion
14380
14318
  //#region src/commands/auth.ts
14381
- const runAuthLoginCommand = async (context, options) => {
14382
- const loginOptions = (() => {
14383
- if (options.mode === "apiKey") return {
14384
- apiKey: options.apiKey,
14385
- mode: "apiKey"
14386
- };
14387
- return {
14388
- mode: "device",
14389
- ...options.onPending === void 0 ? {} : { onPending: options.onPending }
14390
- };
14391
- })();
14319
+ const runLoginCommand = async (context, options) => {
14320
+ const loginOptions = options.onPending === void 0 ? {} : { onPending: options.onPending };
14392
14321
  return context.services.auth.login(loginOptions);
14393
14322
  };
14394
- const runAuthStatusCommand = async (context) => {
14395
- return context.services.auth.status(context.apiKeyOverride);
14396
- };
14397
- const runAuthLogoutCommand = async (context) => {
14323
+ const runLogoutCommand = async (context) => {
14398
14324
  return context.services.auth.logout();
14399
14325
  };
14326
+ const runResetCommand = async (context) => {
14327
+ return context.services.auth.reset();
14328
+ };
14400
14329
 
14401
14330
  //#endregion
14402
14331
  //#region src/commands/server-context.ts
14332
+ const commandNameForSelectorKind = (selectorKind) => {
14333
+ return selectorKind;
14334
+ };
14335
+ const selectorRecoveryCommand = (selectorKind, selector, orgSlug, toolName) => {
14336
+ switch (selectorKind) {
14337
+ case "catalog": return toolName === void 0 ? `ogment catalog ${orgSlug}/${selector}` : `ogment catalog ${orgSlug}/${selector} ${toolName}`;
14338
+ case "search": return `ogment search --org ${orgSlug} ${selector} --code 'return input'`;
14339
+ case "execute": return `ogment execute --org ${orgSlug} ${selector} --code 'return input' --input '{}'`;
14340
+ }
14341
+ };
14403
14342
  const formatCandidateSelectors = (profile, path) => {
14404
14343
  return profile.orgs.flatMap((org) => {
14405
14344
  return org.servers.filter((server) => server.path === path).map((server) => `${org.orgSlug}/${server.path}`);
@@ -14466,8 +14405,9 @@ const findServerByPath = (profile, selector, options) => {
14466
14405
  const [firstCandidate] = sortedCandidates;
14467
14406
  if (firstCandidate !== void 0) {
14468
14407
  const firstCandidateParsed = parseQualifiedSelector(firstCandidate);
14469
- 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}".`;
14470
- 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}`;
14408
+ const commandName = commandNameForSelectorKind(options.selectorKind);
14409
+ const message = `Server "${selector}" is ambiguous across organizations (${sortedCandidates.join(", ")}). Re-run \`ogment ${commandName}\` with --org <org-slug> or use a qualified selector like "${firstCandidate}".`;
14410
+ const recoveryCommand = firstCandidateParsed === null ? `ogment ${commandName} --help` : selectorRecoveryCommand(options.selectorKind, selector, firstCandidateParsed.orgSlug, options.toolName);
14471
14411
  return Result.err(new ValidationError({
14472
14412
  message,
14473
14413
  recovery: { command: recoveryCommand }
@@ -14487,96 +14427,75 @@ const findServerByPath = (profile, selector, options) => {
14487
14427
 
14488
14428
  //#endregion
14489
14429
  //#region src/commands/catalog.ts
14490
- const toServerSummary = (target, toolCount) => {
14430
+ const toServerSummary = (target) => {
14491
14431
  return {
14492
14432
  capabilities: [],
14493
14433
  description: target.server.description,
14494
14434
  name: target.server.name,
14495
14435
  orgSlug: target.orgSlug,
14496
14436
  serverId: target.server.path,
14497
- toolCount,
14498
14437
  version: null
14499
14438
  };
14500
14439
  };
14501
- const toToolSummaries = (tools) => {
14502
- return tools.map((tool) => {
14503
- return {
14504
- description: tool.description ?? null,
14505
- name: tool.name
14506
- };
14507
- });
14508
- };
14509
- const listServerTools = async (context, apiKey, server) => {
14510
- return context.services.mcp.listTools({
14511
- orgSlug: server.orgSlug,
14512
- serverPath: server.server.path
14513
- }, apiKey);
14440
+ const toToolSummary = (tool) => {
14441
+ return {
14442
+ description: tool.description ?? null,
14443
+ name: tool.name
14444
+ };
14514
14445
  };
14515
- const TOOL_COUNT_CONCURRENCY = 4;
14516
- const toCatalogServerFailure = (server, error, includeDebug) => {
14446
+ const toToolDetail = (tool) => {
14517
14447
  return {
14518
- error: presentCatalogFailureError(error, { includeDebug }),
14519
- orgSlug: server.orgSlug,
14520
- serverId: server.server.path
14448
+ description: tool.description ?? null,
14449
+ inputSchema: toJsonValue(tool.inputSchema),
14450
+ name: tool.name,
14451
+ outputSchema: tool.outputSchema === void 0 ? null : toJsonValue(tool.outputSchema)
14521
14452
  };
14522
14453
  };
14523
- const mapWithConcurrency = async (items, concurrency, mapItem) => {
14524
- if (items.length === 0) return [];
14525
- const results = [];
14526
- results.length = items.length;
14527
- let nextIndex = 0;
14528
- const worker = async () => {
14529
- while (true) {
14530
- const currentIndex = nextIndex;
14531
- nextIndex += 1;
14532
- if (currentIndex >= items.length) return;
14533
- const item = items[currentIndex];
14534
- if (item === void 0) return;
14535
- results[currentIndex] = await mapItem(item, currentIndex);
14536
- }
14537
- };
14538
- const workerCount = Math.min(concurrency, items.length);
14539
- await Promise.all(Array.from({ length: workerCount }, async () => worker()));
14540
- return results;
14454
+ const detailCommandForServer = (serverId, orgSlug) => {
14455
+ return `ogment catalog ${orgSlug === void 0 ? serverId : `${orgSlug}/${serverId}`}`;
14456
+ };
14457
+ const resolveCatalogServerTarget = async (context, options) => {
14458
+ const stateResult = await resolveServerState(context);
14459
+ if (Result.isError(stateResult)) return stateResult;
14460
+ const serverResult = findServerByPath(stateResult.value.profile, options.serverId, {
14461
+ ...options.orgSlug === void 0 ? {} : { orgSlug: options.orgSlug },
14462
+ selectorKind: "catalog",
14463
+ ..."toolName" in options ? { toolName: options.toolName } : {}
14464
+ });
14465
+ if (Result.isError(serverResult)) return serverResult;
14466
+ return Result.ok({
14467
+ apiKey: stateResult.value.apiKey,
14468
+ target: {
14469
+ orgSlug: serverResult.value.orgSlug,
14470
+ server: {
14471
+ description: serverResult.value.server.description,
14472
+ name: serverResult.value.server.name,
14473
+ path: serverResult.value.server.path
14474
+ }
14475
+ }
14476
+ });
14477
+ };
14478
+ const listCodeModeTools = async (context, apiKey, target) => {
14479
+ return context.services.codemode.listTools({
14480
+ orgSlug: target.orgSlug,
14481
+ serverPath: target.server.path
14482
+ }, apiKey);
14541
14483
  };
14542
14484
  const runCatalogCommand = async (context, options) => {
14543
14485
  const stateResult = await resolveServerState(context);
14544
14486
  if (Result.isError(stateResult)) return stateResult;
14545
- let targetServers = stateResult.value.profile.orgs.flatMap((org) => {
14546
- return org.servers.map((server) => ({
14487
+ const targetOrgs = options.orgSlug === void 0 ? stateResult.value.profile.orgs : stateResult.value.profile.orgs.filter((org) => org.orgSlug === options.orgSlug);
14488
+ if (options.orgSlug !== void 0 && targetOrgs.length === 0) return Result.err(new ValidationError({
14489
+ code: ERROR_CODE.validationInvalidInput,
14490
+ message: `Organization "${options.orgSlug}" not found`,
14491
+ recovery: { command: "ogment catalog" }
14492
+ }));
14493
+ const summaries = targetOrgs.flatMap((org) => {
14494
+ return org.servers.map((server) => toServerSummary({
14547
14495
  orgSlug: org.orgSlug,
14548
14496
  server
14549
14497
  }));
14550
14498
  });
14551
- if (options.serverId !== void 0) {
14552
- const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
14553
- if (Result.isError(serverResult)) return serverResult;
14554
- targetServers = [{
14555
- orgSlug: serverResult.value.orgSlug,
14556
- server: serverResult.value.server
14557
- }];
14558
- }
14559
- const serverSummaries = await mapWithConcurrency(targetServers, TOOL_COUNT_CONCURRENCY, async (server) => {
14560
- return {
14561
- server,
14562
- toolsResult: await listServerTools(context, stateResult.value.apiKey, server)
14563
- };
14564
- });
14565
- const summaries = [];
14566
- const failures = [];
14567
- for (const serverSummary of serverSummaries) {
14568
- if (Result.isError(serverSummary.toolsResult)) {
14569
- if (options.serverId !== void 0) return serverSummary.toolsResult;
14570
- failures.push(toCatalogServerFailure(serverSummary.server, serverSummary.toolsResult.error, options.includeDebug === true));
14571
- continue;
14572
- }
14573
- summaries.push(toServerSummary(serverSummary.server, serverSummary.toolsResult.value.length));
14574
- }
14575
- if (options.serverId !== void 0) return Result.ok({
14576
- failures: [],
14577
- nextCursor: null,
14578
- servers: summaries
14579
- });
14580
14499
  const limit = Math.max(1, options.limit ?? 20);
14581
14500
  let startIndex = 0;
14582
14501
  if (options.cursor !== void 0) {
@@ -14591,81 +14510,52 @@ const runCatalogCommand = async (context, options) => {
14591
14510
  const servers = summaries.slice(startIndex, startIndex + limit);
14592
14511
  const nextCursor = startIndex + limit < summaries.length ? servers.at(-1)?.serverId ?? null : null;
14593
14512
  return Result.ok({
14594
- failures,
14513
+ failures: [],
14595
14514
  nextCursor,
14596
14515
  servers
14597
14516
  });
14598
14517
  };
14599
- const runCatalogToolsCommand = async (context, options) => {
14600
- const stateResult = await resolveServerState(context);
14601
- if (Result.isError(stateResult)) return stateResult;
14602
- const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
14603
- if (Result.isError(serverResult)) return serverResult;
14604
- const targetServer = {
14605
- orgSlug: serverResult.value.orgSlug,
14606
- server: serverResult.value.server
14607
- };
14608
- const toolsResult = await listServerTools(context, stateResult.value.apiKey, targetServer);
14518
+ const runCatalogServerDetailCommand = async (context, options) => {
14519
+ const targetResult = await resolveCatalogServerTarget(context, options);
14520
+ if (Result.isError(targetResult)) return targetResult;
14521
+ const toolsResult = await listCodeModeTools(context, targetResult.value.apiKey, targetResult.value.target);
14609
14522
  if (Result.isError(toolsResult)) return toolsResult;
14610
14523
  return Result.ok({
14611
- server: toServerSummary(targetServer, toolsResult.value.length),
14612
- tools: toToolSummaries(toolsResult.value)
14524
+ server: toServerSummary(targetResult.value.target),
14525
+ tools: toolsResult.value.map((tool) => toToolSummary(tool))
14613
14526
  });
14614
14527
  };
14615
- const runCatalogToolDetailsCommand = async (context, options) => {
14616
- const stateResult = await resolveServerState(context);
14617
- if (Result.isError(stateResult)) return stateResult;
14618
- const serverResult = findServerByPath(stateResult.value.profile, options.serverId, { selectorKind: "catalog" });
14619
- if (Result.isError(serverResult)) return serverResult;
14620
- const targetServer = {
14621
- orgSlug: serverResult.value.orgSlug,
14622
- server: serverResult.value.server
14623
- };
14624
- const toolsResult = await listServerTools(context, stateResult.value.apiKey, targetServer);
14528
+ const runCatalogToolDetailCommand = async (context, options) => {
14529
+ const targetResult = await resolveCatalogServerTarget(context, options);
14530
+ if (Result.isError(targetResult)) return targetResult;
14531
+ const toolsResult = await listCodeModeTools(context, targetResult.value.apiKey, targetResult.value.target);
14625
14532
  if (Result.isError(toolsResult)) return toolsResult;
14626
- const tool = toolsResult.value.find((item) => item.name === options.toolName);
14533
+ const tool = toolsResult.value.find((candidate) => {
14534
+ return candidate.name === options.toolName;
14535
+ });
14627
14536
  if (tool === void 0) return Result.err(new NotFoundError({
14628
- message: `Tool "${options.toolName}" not found`,
14629
- resource: options.toolName
14537
+ message: `Codemode tool "${options.toolName}" not found on server "${options.serverId}"`,
14538
+ recovery: { command: detailCommandForServer(targetResult.value.target.server.path, targetResult.value.target.orgSlug) },
14539
+ resource: `${options.serverId}/${options.toolName}`
14630
14540
  }));
14631
14541
  return Result.ok({
14632
- description: tool.description ?? null,
14633
- inputSchema: tool.inputSchema,
14634
- name: tool.name,
14635
- outputSchema: tool.outputSchema ?? null,
14636
- server: toServerSummary(targetServer, toolsResult.value.length)
14542
+ server: toServerSummary(targetResult.value.target),
14543
+ tool: toToolDetail(tool)
14637
14544
  });
14638
14545
  };
14639
14546
 
14640
14547
  //#endregion
14641
- //#region src/commands/invoke.ts
14642
- const mapInputFileReadError = (inputFile, cause) => {
14548
+ //#region src/commands/codemode.ts
14549
+ const mapSourceFileReadError = (inputFile, optionName, cause) => {
14643
14550
  const code = cause instanceof Error && "code" in cause && typeof cause.code === "string" ? cause.code : void 0;
14644
- if (code === "ENOENT") return new ValidationError({ message: `Input file not found: ${inputFile}` });
14645
- if (code === "EACCES" || code === "EPERM") return new ValidationError({ message: `Input file is not readable: ${inputFile}` });
14646
- if (code === "EISDIR") return new ValidationError({ message: `Input path must be a file: ${inputFile}` });
14551
+ if (code === "ENOENT") return new ValidationError({ message: `${optionName} file not found: ${inputFile}` });
14552
+ if (code === "EACCES" || code === "EPERM") return new ValidationError({ message: `${optionName} file is not readable: ${inputFile}` });
14553
+ if (code === "EISDIR") return new ValidationError({ message: `${optionName} path must be a file: ${inputFile}` });
14647
14554
  return new UnexpectedError({
14648
14555
  cause,
14649
- message: `Failed to read input file: ${inputFile}`
14556
+ message: `Failed to read ${optionName} file: ${inputFile}`
14650
14557
  });
14651
14558
  };
14652
- const parseInputObject = (raw, context) => {
14653
- const parsed = parseJsonValue(raw, context);
14654
- if (Result.isError(parsed)) return parsed;
14655
- const parsedValue = parsed.value;
14656
- if (!isJsonObject(parsedValue)) return Result.err(new ValidationError({ message: "Invoke input must be a JSON object" }));
14657
- return Result.ok(parsedValue);
14658
- };
14659
- const toToolCallStructuredContent = (result) => {
14660
- if (result.structuredContent !== void 0) return toJsonValue(result.structuredContent);
14661
- const firstContent = (Array.isArray(result.content) ? result.content : [])[0];
14662
- if (firstContent !== void 0 && firstContent.type === "text" && typeof firstContent.text === "string") {
14663
- const parsedText = parseJsonValue(firstContent.text, "MCP text content");
14664
- if (Result.isError(parsedText)) return firstContent.text;
14665
- return parsedText.value;
14666
- }
14667
- return toJsonValue(result);
14668
- };
14669
14559
  const readStdin = async () => {
14670
14560
  return Result.tryPromise({
14671
14561
  catch: (cause) => new UnexpectedError({
@@ -14689,73 +14579,111 @@ const readStdin = async () => {
14689
14579
  }
14690
14580
  });
14691
14581
  };
14692
- const parseInvokeArgs = async (options, deps) => {
14693
- if (options.input === void 0) return Result.ok({});
14694
- if (options.input === "-") {
14695
- const stdinResult = await (deps.readStdin ?? readStdin)();
14696
- if (Result.isError(stdinResult)) return stdinResult;
14697
- return parseInputObject(stdinResult.value, "--input (-)");
14698
- }
14699
- if (options.input.startsWith("@")) {
14700
- const inputFile = options.input.slice(1);
14582
+ const readSourceValue = async (value, optionName, deps) => {
14583
+ if (value === "-") return (deps.readStdin ?? readStdin)();
14584
+ if (value.startsWith("@")) {
14585
+ const inputFile = value.slice(1);
14701
14586
  if (inputFile.length === 0) return Result.err(new ValidationError({
14702
- details: options.input,
14703
- message: "Invalid --input value. Use @<path>, -, or an inline JSON object."
14587
+ details: value,
14588
+ message: `Invalid ${optionName} value. Use @<path>, -, or an inline value.`
14704
14589
  }));
14705
- const fileReadResult = await Result.tryPromise({
14706
- catch: (cause) => mapInputFileReadError(inputFile, cause),
14590
+ return Result.tryPromise({
14591
+ catch: (cause) => mapSourceFileReadError(inputFile, optionName, cause),
14707
14592
  try: async () => readFile$1(inputFile, "utf8")
14708
14593
  });
14709
- if (Result.isError(fileReadResult)) return fileReadResult;
14710
- return parseInputObject(fileReadResult.value, "--input (@file)");
14711
14594
  }
14712
- return parseInputObject(options.input, "--input");
14595
+ return Result.ok(value);
14596
+ };
14597
+ const parseInputObject = (raw, context) => {
14598
+ const parsed = parseJsonValue(raw, context);
14599
+ if (Result.isError(parsed)) return parsed;
14600
+ if (!isJsonObject(parsed.value)) return Result.err(new ValidationError({ message: "Execute input must be a JSON object" }));
14601
+ return Result.ok(parsed.value);
14602
+ };
14603
+ const parseExecuteInput = async (input, deps) => {
14604
+ if (input === void 0) return Result.ok(void 0);
14605
+ const sourceResult = await readSourceValue(input, "--input", deps);
14606
+ if (Result.isError(sourceResult)) return sourceResult;
14607
+ const sourceContext = input === "-" ? "--input (-)" : input.startsWith("@") ? "--input (@file)" : "--input";
14608
+ return parseInputObject(sourceResult.value, sourceContext);
14609
+ };
14610
+ const toToolCallStructuredContent = (result) => {
14611
+ if (result.structuredContent !== void 0) return toJsonValue(result.structuredContent);
14612
+ const firstContent = (Array.isArray(result.content) ? result.content : [])[0];
14613
+ if (firstContent !== void 0 && firstContent.type === "text" && typeof firstContent.text === "string") {
14614
+ const parsedText = parseJsonValue(firstContent.text, "MCP text content");
14615
+ if (Result.isError(parsedText)) return firstContent.text;
14616
+ return parsedText.value;
14617
+ }
14618
+ return toJsonValue(result);
14713
14619
  };
14714
- const runInvokeCommand = async (context, options, deps = {}) => {
14715
- const argsResult = await parseInvokeArgs(options, deps);
14716
- if (Result.isError(argsResult)) return argsResult;
14620
+ const resolveServerTarget = async (context, options, selectorKind) => {
14717
14621
  const stateResult = await resolveServerState(context);
14718
14622
  if (Result.isError(stateResult)) return stateResult;
14719
14623
  const serverResult = findServerByPath(stateResult.value.profile, options.serverId, {
14720
14624
  ...options.orgSlug === void 0 ? {} : { orgSlug: options.orgSlug },
14721
- selectorKind: "invoke",
14722
- toolName: options.toolName
14625
+ selectorKind
14723
14626
  });
14724
14627
  if (Result.isError(serverResult)) return serverResult;
14725
- const mcpTarget = {
14628
+ return Result.ok({
14629
+ apiKey: stateResult.value.apiKey,
14726
14630
  orgSlug: serverResult.value.orgSlug,
14727
14631
  serverPath: serverResult.value.server.path
14728
- };
14729
- const callResult = await context.services.mcp.callTool(mcpTarget, stateResult.value.apiKey, options.toolName, argsResult.value);
14730
- if (Result.isError(callResult)) {
14731
- if (callResult.error._tag === "RemoteRequestError") {
14732
- const toolsResult = await context.services.mcp.listTools(mcpTarget, stateResult.value.apiKey);
14733
- if (Result.isOk(toolsResult)) {
14734
- if (!toolsResult.value.some((tool) => tool.name === options.toolName)) return Result.err(new NotFoundError({
14735
- message: `Tool "${options.toolName}" not found`,
14736
- resource: options.toolName
14737
- }));
14738
- }
14739
- }
14740
- return callResult;
14741
- }
14742
- const structuredContent = toToolCallStructuredContent(callResult.value);
14743
- if (callResult.value.isError) {
14744
- const details = parseRemoteErrorDetails(structuredContent);
14745
- return Result.err(new RemoteRequestError({
14746
- ...details.mcpCode === void 0 ? {} : { mcpCode: details.mcpCode },
14747
- ...details.data === void 0 ? {} : { mcpData: details.data },
14748
- message: details.message ?? "MCP tool call returned an error result",
14749
- operation: "tools/call",
14750
- raw: structuredContent,
14751
- retryable: false,
14752
- source: "mcp_jsonrpc"
14753
- }));
14754
- }
14632
+ });
14633
+ };
14634
+ const codemodeErrorFromToolResult = (result) => {
14635
+ if (!result.isError) return null;
14636
+ const structuredContent = toToolCallStructuredContent(result);
14637
+ const details = parseRemoteErrorDetails(structuredContent);
14638
+ return new RemoteRequestError({
14639
+ ...details.mcpCode === void 0 ? {} : { mcpCode: details.mcpCode },
14640
+ ...details.data === void 0 ? {} : { mcpData: details.data },
14641
+ message: details.message ?? "Codemode tool call returned an error result",
14642
+ operation: "tools/call",
14643
+ raw: structuredContent,
14644
+ retryable: false,
14645
+ source: "mcp_jsonrpc"
14646
+ });
14647
+ };
14648
+ const runSearchCommand = async (context, options, deps = {}) => {
14649
+ const codeResult = await readSourceValue(options.code, "--code", deps);
14650
+ if (Result.isError(codeResult)) return codeResult;
14651
+ const targetResult = await resolveServerTarget(context, options, "search");
14652
+ if (Result.isError(targetResult)) return targetResult;
14653
+ const callResult = await context.services.codemode.callTool({
14654
+ orgSlug: targetResult.value.orgSlug,
14655
+ serverPath: targetResult.value.serverPath
14656
+ }, targetResult.value.apiKey, "search", { code: codeResult.value });
14657
+ if (Result.isError(callResult)) return callResult;
14658
+ const toolError = codemodeErrorFromToolResult(callResult.value);
14659
+ if (toolError !== null) return Result.err(toolError);
14660
+ return Result.ok({
14661
+ result: toToolCallStructuredContent(callResult.value),
14662
+ serverId: options.serverId
14663
+ });
14664
+ };
14665
+ const runExecuteCommand = async (context, options, deps = {}) => {
14666
+ const [codeResult, inputResult, targetResult] = await Promise.all([
14667
+ readSourceValue(options.code, "--code", deps),
14668
+ parseExecuteInput(options.input, deps),
14669
+ resolveServerTarget(context, options, "execute")
14670
+ ]);
14671
+ if (Result.isError(codeResult)) return codeResult;
14672
+ if (Result.isError(inputResult)) return inputResult;
14673
+ if (Result.isError(targetResult)) return targetResult;
14674
+ const callResult = await context.services.codemode.callTool({
14675
+ orgSlug: targetResult.value.orgSlug,
14676
+ serverPath: targetResult.value.serverPath
14677
+ }, targetResult.value.apiKey, "execute", {
14678
+ code: codeResult.value,
14679
+ ...inputResult.value === void 0 ? {} : { input: inputResult.value }
14680
+ });
14681
+ if (Result.isError(callResult)) return callResult;
14682
+ const toolError = codemodeErrorFromToolResult(callResult.value);
14683
+ if (toolError !== null) return Result.err(toolError);
14755
14684
  return Result.ok({
14756
- result: structuredContent,
14757
- serverId: options.serverId,
14758
- toolName: options.toolName
14685
+ result: toToolCallStructuredContent(callResult.value),
14686
+ serverId: options.serverId
14759
14687
  });
14760
14688
  };
14761
14689
 
@@ -14765,149 +14693,116 @@ const runStatusCommand = async (options, deps) => {
14765
14693
  return deps.infoService.collect(options.apiKeyOverride, { includeDebug: options.debug });
14766
14694
  };
14767
14695
 
14768
- //#endregion
14769
- //#region src/shared/schema-example.ts
14770
- const MAX_EXAMPLE_DEPTH = 6;
14771
- const EXAMPLE_PLACEHOLDER = " ... ";
14772
- const isRecord$1 = (value) => {
14773
- return typeof value === "object" && value !== null && !Array.isArray(value);
14774
- };
14775
- const asStringArray = (value) => {
14776
- if (!Array.isArray(value)) return [];
14777
- return value.filter((item) => typeof item === "string");
14778
- };
14779
- const firstKnown = (value) => {
14780
- if (Array.isArray(value) && value.length > 0) return value[0];
14781
- };
14782
- const deriveType = (schema) => {
14783
- const typeValue = schema["type"];
14784
- if (typeof typeValue === "string") return typeValue;
14785
- if (Array.isArray(typeValue)) return typeValue.find((entry) => typeof entry === "string");
14786
- if (isRecord$1(schema["properties"])) return "object";
14787
- if (schema["items"] !== void 0) return "array";
14788
- };
14789
- const baseScalarExample = (_typeName) => {
14790
- switch (_typeName) {
14791
- case "string": return EXAMPLE_PLACEHOLDER;
14792
- case "integer": return EXAMPLE_PLACEHOLDER;
14793
- case "number": return EXAMPLE_PLACEHOLDER;
14794
- case "boolean": return EXAMPLE_PLACEHOLDER;
14795
- case "null": return EXAMPLE_PLACEHOLDER;
14796
- default: return EXAMPLE_PLACEHOLDER;
14797
- }
14798
- };
14799
- const buildExample = (value, depth) => {
14800
- if (!isRecord$1(value)) return {};
14801
- if (depth > MAX_EXAMPLE_DEPTH) return {};
14802
- const oneOfCandidate = firstKnown(value["oneOf"]);
14803
- if (oneOfCandidate !== void 0) return buildExample(oneOfCandidate, depth + 1);
14804
- const anyOfCandidate = firstKnown(value["anyOf"]);
14805
- if (anyOfCandidate !== void 0) return buildExample(anyOfCandidate, depth + 1);
14806
- const allOfCandidate = firstKnown(value["allOf"]);
14807
- if (allOfCandidate !== void 0) return buildExample(allOfCandidate, depth + 1);
14808
- const typeName = deriveType(value);
14809
- if (typeName === "object") {
14810
- const result = {};
14811
- const properties = isRecord$1(value["properties"]) ? value["properties"] : {};
14812
- const required = asStringArray(value["required"]);
14813
- for (const propertyName of required) {
14814
- const propertySchema = properties[propertyName];
14815
- if (propertySchema !== void 0) result[propertyName] = buildExample(propertySchema, depth + 1);
14816
- }
14817
- if (required.length === 0 && isRecord$1(value["additionalProperties"])) result["example"] = buildExample(value["additionalProperties"], depth + 1);
14818
- return result;
14819
- }
14820
- if (typeName === "array") {
14821
- if (value["items"] === void 0) return [EXAMPLE_PLACEHOLDER];
14822
- return [buildExample(value["items"], depth + 1)];
14823
- }
14824
- if (typeName === void 0) return depth === 0 ? {} : EXAMPLE_PLACEHOLDER;
14825
- return baseScalarExample(typeName);
14826
- };
14827
- const buildJsonSchemaExample = (schema) => {
14828
- return buildExample(schema, 0);
14829
- };
14830
-
14831
14696
  //#endregion
14832
14697
  //#region src/cli/commands.ts
14698
+ const withOrg = (orgSlug) => {
14699
+ return orgSlug === void 0 ? [] : [`--org ${orgSlug}`];
14700
+ };
14833
14701
  const cliCommands = {
14834
- auth: {
14835
- help: () => "ogment auth --help",
14836
- login: () => "ogment auth login",
14837
- loginWithApiKeyRedacted: () => "ogment auth login --api-key <redacted>",
14838
- logout: () => "ogment auth logout",
14839
- status: () => "ogment auth status"
14840
- },
14841
14702
  catalog: {
14842
- command: () => "ogment catalog",
14843
- server: (serverId) => `ogment catalog ${serverId}`,
14703
+ command: (serverId, toolName, orgSlug) => [
14704
+ "ogment catalog",
14705
+ ...withOrg(orgSlug),
14706
+ ...serverId === void 0 ? [] : [serverId],
14707
+ ...toolName === void 0 ? [] : [toolName]
14708
+ ].join(" "),
14709
+ detail: (serverId, orgSlug) => [
14710
+ "ogment catalog",
14711
+ ...withOrg(orgSlug),
14712
+ serverId
14713
+ ].join(" "),
14844
14714
  summary: (options) => {
14845
14715
  return [
14846
14716
  "ogment catalog",
14717
+ ...withOrg(options.orgSlug),
14847
14718
  ...options.cursor === void 0 ? [] : [`--cursor ${options.cursor}`],
14848
14719
  ...options.limit === void 0 ? [] : [`--limit ${options.limit}`]
14849
14720
  ].join(" ");
14850
14721
  },
14851
- tool: (serverId, toolName, options) => {
14852
- return [
14853
- "ogment catalog",
14854
- serverId,
14855
- toolName,
14856
- ...options.example ? ["--example"] : []
14857
- ].join(" ");
14858
- }
14859
- },
14860
- helpForScope: (scope) => {
14861
- if (scope === null) return "ogment --help";
14862
- return `ogment ${scope} --help`;
14863
- },
14864
- invoke: {
14865
- command: (serverId, toolName, orgSlug) => [
14866
- "ogment invoke",
14867
- ...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
14722
+ toolDetail: (serverId, toolName, orgSlug) => [
14723
+ "ogment catalog",
14724
+ ...withOrg(orgSlug),
14868
14725
  serverId,
14869
14726
  toolName
14727
+ ].join(" ")
14728
+ },
14729
+ execute: {
14730
+ command: (serverId, orgSlug) => [
14731
+ "ogment execute",
14732
+ ...withOrg(orgSlug),
14733
+ serverId
14870
14734
  ].join(" "),
14871
- inlineJson: (serverId, toolName, orgSlug) => [
14872
- "ogment invoke",
14873
- ...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
14735
+ help: () => "ogment execute --help",
14736
+ inlineCode: (serverId, orgSlug) => [
14737
+ "ogment execute",
14738
+ ...withOrg(orgSlug),
14874
14739
  serverId,
14875
- toolName,
14876
- "--input <json>"
14740
+ "--code <javascript>"
14877
14741
  ].join(" "),
14878
- stdin: (serverId, toolName, orgSlug) => [
14879
- "ogment invoke",
14880
- ...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
14742
+ stdinCode: (serverId, orgSlug) => [
14743
+ "ogment execute",
14744
+ ...withOrg(orgSlug),
14881
14745
  serverId,
14882
- toolName,
14883
- "--input -"
14746
+ "--code -"
14884
14747
  ].join(" "),
14885
- withInputValue: (serverId, toolName, value, orgSlug) => {
14886
- return [
14887
- "ogment invoke",
14888
- ...orgSlug === void 0 ? [] : [`--org ${orgSlug}`],
14889
- serverId,
14890
- toolName,
14891
- `--input ${value}`
14892
- ].join(" ");
14893
- }
14748
+ withCodeAndInputValue: (serverId, code, input, orgSlug) => [
14749
+ "ogment execute",
14750
+ ...withOrg(orgSlug),
14751
+ serverId,
14752
+ `--code ${code}`,
14753
+ ...input === void 0 ? [] : [`--input ${input}`]
14754
+ ].join(" ")
14755
+ },
14756
+ helpForScope: (scope) => {
14757
+ if (scope === null) return "ogment --help";
14758
+ return `ogment ${scope} --help`;
14894
14759
  },
14760
+ login: { command: () => "ogment login" },
14761
+ logout: { command: () => "ogment logout" },
14762
+ reset: { command: () => "ogment reset" },
14895
14763
  root: {
14896
14764
  command: () => "ogment",
14897
14765
  commandsSurface: () => {
14898
14766
  return [
14899
- "auth login",
14900
- "auth status",
14901
- "auth logout",
14767
+ "login",
14768
+ "logout",
14769
+ "reset",
14902
14770
  "catalog",
14903
14771
  "catalog <server-id>",
14904
14772
  "catalog <server-id> <tool-name>",
14905
- "invoke <server-id> <tool-name>",
14773
+ "search <server-id>",
14774
+ "execute <server-id>",
14906
14775
  "status"
14907
14776
  ];
14908
14777
  },
14909
14778
  help: () => "ogment --help"
14910
14779
  },
14780
+ search: {
14781
+ command: (serverId, orgSlug) => [
14782
+ "ogment search",
14783
+ ...withOrg(orgSlug),
14784
+ serverId
14785
+ ].join(" "),
14786
+ help: () => "ogment search --help",
14787
+ inspectAllTools: (serverId, orgSlug) => [
14788
+ "ogment search",
14789
+ ...withOrg(orgSlug),
14790
+ serverId,
14791
+ "--code 'return input'"
14792
+ ].join(" "),
14793
+ stdinCode: (serverId, orgSlug) => [
14794
+ "ogment search",
14795
+ ...withOrg(orgSlug),
14796
+ serverId,
14797
+ "--code -"
14798
+ ].join(" "),
14799
+ withCodeValue: (serverId, code, orgSlug) => [
14800
+ "ogment search",
14801
+ ...withOrg(orgSlug),
14802
+ serverId,
14803
+ `--code ${code}`
14804
+ ].join(" ")
14805
+ },
14911
14806
  status: { command: () => "ogment status" }
14912
14807
  };
14913
14808
 
@@ -14946,296 +14841,268 @@ const ensureSuccess = (result, runtime, context) => {
14946
14841
  }
14947
14842
  return result.unwrap();
14948
14843
  };
14949
- const nextActionsForLogin = (payload, mode) => {
14950
- return [nextAction("check_auth_status", "Check auth status", cliCommands.auth.status(), `Verify persisted credentials after ${mode} login for ${payload.agentName}.`, "immediate"), nextAction("discover_servers", "Discover servers", cliCommands.catalog.command(), `Logged in as ${payload.agentName} via ${mode}; discover available servers.`, "after_auth")];
14844
+ const nextActionsForLogin = (payload) => {
14845
+ return [nextAction("inspect_status", "Inspect status", cliCommands.status.command(), `Verify the connected CLI state for ${payload.agentName}.`, "immediate"), nextAction("discover_servers", "Discover servers", cliCommands.catalog.command(), `Logged in as ${payload.agentName}; discover available servers.`, "after_auth")];
14951
14846
  };
14952
- const nextActionsForPendingLogin = (userCode, verificationUri) => {
14953
- return [nextAction("check_login_status", "Check login status", cliCommands.auth.status(), `Approve ${userCode} at ${verificationUri}, then verify local auth state.`, "immediate"), nextAction("restart_device_login", "Restart login", cliCommands.auth.login(), `Restart login if code ${userCode} expires before approval.`, "if_expired")];
14954
- };
14955
- const nextActionsForAuthStatus = (payload) => {
14956
- if (!payload.loggedIn) return [nextAction("login", "Authenticate", cliCommands.auth.login(), "No API key is configured locally; login is required.", "immediate")];
14957
- return [nextAction("discover_servers", "Discover servers", cliCommands.catalog.command(), `Authenticated via ${payload.apiKeySource}; discover servers next.`, "after_auth")];
14847
+ const nextActionsForPendingLogin = (authRequestId, verificationUrl) => {
14848
+ return [nextAction("complete_login", "Complete login", cliCommands.login.command(), `Approve request ${authRequestId} at ${verificationUrl}, then run login again to finish local sign-in.`, "immediate"), nextAction("inspect_status", "Inspect status", cliCommands.status.command(), "Inspect the current CLI state and diagnostics.", "if_expired")];
14958
14849
  };
14959
14850
  const nextActionsForCatalogSummary = (payload, context) => {
14960
14851
  const actions = [];
14961
- const targetServer = payload.servers.find((server) => server.toolCount > 0);
14962
- 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"));
14852
+ const targetServer = payload.servers[0];
14853
+ if (targetServer !== void 0) actions.push(nextAction("inspect_server", "Inspect server", cliCommands.catalog.detail(targetServer.serverId, targetServer.orgSlug), `Inspect Codemode tools exposed on ${targetServer.serverId}.`, "if_servers_available"));
14963
14854
  if (context.nextCursor !== null) actions.push(nextAction("next_catalog_page", "Load next page", cliCommands.catalog.summary({
14964
14855
  cursor: context.nextCursor,
14965
- ...context.limit === null ? {} : { limit: context.limit }
14856
+ ...context.limit === null ? {} : { limit: context.limit },
14857
+ ...context.orgSlug === null ? {} : { orgSlug: context.orgSlug }
14966
14858
  }), `More servers are available after cursor ${context.nextCursor}.`, "if_more_servers"));
14967
14859
  return actions;
14968
14860
  };
14969
- const nextActionsForCatalogTools = (payload) => {
14970
- const firstTool = payload.tools[0];
14971
- if (firstTool === void 0) return [];
14972
- return [nextAction("inspect_tool", "Inspect tool details", cliCommands.catalog.tool(payload.server.serverId, firstTool.name, { example: false }), `Inspect schema for ${payload.server.serverId}/${firstTool.name} before invoking.`, "if_tools_available")];
14861
+ const nextActionsForCatalogServerDetail = (payload) => {
14862
+ const searchTool = payload.tools.find((tool) => tool.name === "search");
14863
+ if (searchTool !== void 0) return [nextAction("inspect_tool", "Inspect tool details", cliCommands.catalog.toolDetail(payload.server.serverId, searchTool.name, payload.server.orgSlug), `Inspect schema for ${payload.server.serverId}/${searchTool.name} before invoking.`, "if_tools_available")];
14864
+ return [];
14973
14865
  };
14974
- const toInlineJsonTemplateArgument = (value) => {
14975
- const placeholderLiteral = JSON.stringify(EXAMPLE_PLACEHOLDER);
14976
- return `'${JSON.stringify(value).replaceAll(placeholderLiteral, " ... ").replaceAll("'", String.raw`'\''`)}'`;
14866
+ const nextActionsForCatalogToolDetail = (payload) => {
14867
+ if (payload.tool.name === "search") return [nextAction("run_search", "Run search", cliCommands.search.inspectAllTools(payload.server.serverId, payload.server.orgSlug), `Use Codemode search on ${payload.server.serverId} after reviewing the tool contract.`, "after_tool_inspection")];
14868
+ return [nextAction("run_execute", "Run execute", cliCommands.execute.inlineCode(payload.server.serverId, payload.server.orgSlug), `Use Codemode execute on ${payload.server.serverId} after reviewing the tool contract.`, "after_tool_inspection")];
14977
14869
  };
14978
- const nextActionsForCatalogToolDetails = (payload, exampleInput) => {
14979
- const inputArgument = toInlineJsonTemplateArgument(exampleInput);
14980
- 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")];
14870
+ const nextActionsForSearch = (payload) => {
14871
+ return [nextAction("execute_help", "Inspect execute usage", cliCommands.execute.help(), `Run Codemode execute against ${payload.serverId} after choosing a workflow.`, "after_search")];
14981
14872
  };
14982
- const nextActionsForInvoke = (payload) => {
14983
- 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")];
14873
+ const nextActionsForExecute = (payload) => {
14874
+ return [nextAction("search_tools", "Search tools again", cliCommands.search.inspectAllTools(payload.serverId), `Reinspect tool definitions on ${payload.serverId} before the next execution.`, "after_execute")];
14984
14875
  };
14985
14876
  const nextActionsForStatus = (payload) => {
14986
- if (!payload.auth.apiKeyPresent) return [nextAction("login", "Authenticate", cliCommands.auth.login(), "Status detected no API key; authenticate first.", "immediate")];
14877
+ if (!payload.auth.apiKeyPresent) return [nextAction("login", "Authenticate", cliCommands.login.command(), "Status detected no API key; authenticate first.", "immediate")];
14987
14878
  return [nextAction("discover_servers", "Discover servers", cliCommands.catalog.command(), `Connectivity is ${payload.summary.status}; discover available servers.`, "after_status")];
14988
14879
  };
14880
+ const codeSourceFromValue = (value) => {
14881
+ if (value === "-") return "stdin";
14882
+ if (value.startsWith("@")) return "file";
14883
+ return "inline";
14884
+ };
14885
+ const inputSourceFromValue = (value) => {
14886
+ if (value === void 0) return "none";
14887
+ if (value === "-") return "stdin";
14888
+ if (value.startsWith("@")) return "file";
14889
+ return "inline_json";
14890
+ };
14989
14891
  const runLoginFlow = async (runtime, options) => {
14990
- const { commandOptions, invokedCommand, mode } = options.mode === "apiKey" ? {
14991
- commandOptions: options,
14992
- invokedCommand: cliCommands.auth.loginWithApiKeyRedacted(),
14993
- mode: "apiKey"
14994
- } : {
14995
- commandOptions: { mode: "device" },
14996
- invokedCommand: cliCommands.auth.login(),
14997
- mode: "device"
14998
- };
14999
- const data = ensureSuccess(await runAuthLoginCommand(runtime.context, commandOptions), runtime, {
15000
- command: invokedCommand,
15001
- entity: { mode }
15002
- });
14892
+ const invokedCommand = cliCommands.login.command();
14893
+ const data = ensureSuccess(await runLoginCommand(runtime.context, options), runtime, { command: invokedCommand });
15003
14894
  if (!data.loggedIn) {
15004
14895
  const pendingOutput = {
15005
- event: "auth_login.pending",
14896
+ event: "login.pending",
15006
14897
  loggedIn: false,
15007
14898
  verification: data.verification
15008
14899
  };
15009
14900
  runtime.output.success(pendingOutput, {
15010
14901
  command: invokedCommand,
15011
14902
  entity: {
15012
- event: "auth_login.pending",
15013
- mode,
14903
+ event: "login.pending",
15014
14904
  verification: {
15015
- userCode: data.verification.userCode,
15016
- verificationUri: data.verification.verificationUri
14905
+ authRequestId: data.verification.authRequestId,
14906
+ verificationUrl: data.verification.verificationUrl
15017
14907
  }
15018
14908
  },
15019
- nextActions: nextActionsForPendingLogin(data.verification.userCode, data.verification.verificationUri)
14909
+ nextActions: nextActionsForPendingLogin(data.verification.authRequestId, data.verification.verificationUrl)
15020
14910
  });
15021
14911
  return;
15022
14912
  }
15023
14913
  const outputData = {
15024
14914
  ...data,
15025
- event: "auth_login.completed"
14915
+ event: "login.completed"
15026
14916
  };
15027
14917
  runtime.output.success(outputData, {
15028
14918
  command: invokedCommand,
15029
14919
  entity: {
15030
14920
  agentName: data.agentName,
15031
- event: "auth_login.completed",
14921
+ event: "login.completed",
15032
14922
  loggedIn: data.loggedIn,
15033
- mode,
15034
14923
  outcome: data.outcome
15035
14924
  },
15036
- nextActions: nextActionsForLogin(data, mode)
14925
+ nextActions: nextActionsForLogin(data)
15037
14926
  });
15038
14927
  };
15039
- const executeAuthLoginInvocation = async (runtime, invocation) => {
15040
- if (invocation.apiKey !== void 0) {
15041
- await runLoginFlow(runtime, {
15042
- apiKey: invocation.apiKey,
15043
- mode: "apiKey"
15044
- });
15045
- return;
15046
- }
15047
- await runLoginFlow(runtime, { mode: "device" });
14928
+ const executeLoginInvocation = async (runtime, _invocation) => {
14929
+ await runLoginFlow(runtime, {});
15048
14930
  };
15049
- const executeAuthStatusInvocation = async (runtime) => {
15050
- const command = cliCommands.auth.status();
15051
- const data = ensureSuccess(await runAuthStatusCommand(runtime.context), runtime, { command });
15052
- runtime.output.success(data, {
14931
+ const executeLogoutInvocation = async (runtime) => {
14932
+ const command = cliCommands.logout.command();
14933
+ const data = ensureSuccess(await runLogoutCommand(runtime.context), runtime, { command });
14934
+ const outputData = {
14935
+ ...data,
14936
+ event: "logout.completed"
14937
+ };
14938
+ runtime.output.success(outputData, {
15053
14939
  command,
15054
14940
  entity: {
15055
- apiKeySource: data.apiKeySource,
15056
- loggedIn: data.loggedIn
14941
+ event: "logout.completed",
14942
+ localStateCleared: data.localStateCleared,
14943
+ remoteSignedOut: data.remoteSignedOut
15057
14944
  },
15058
- nextActions: nextActionsForAuthStatus(data)
14945
+ nextActions: [nextAction("login", "Authenticate again", cliCommands.login.command(), "Sign-out completed; run login when you want to reconnect this installation.", "after_logout")]
15059
14946
  });
15060
14947
  };
15061
- const executeAuthLogoutInvocation = async (runtime) => {
15062
- const command = cliCommands.auth.logout();
15063
- const data = ensureSuccess(await runAuthLogoutCommand(runtime.context), runtime, { command });
15064
- runtime.output.success(data, {
14948
+ const executeResetInvocation = async (runtime) => {
14949
+ const command = cliCommands.reset.command();
14950
+ const data = ensureSuccess(await runResetCommand(runtime.context), runtime, { command });
14951
+ const outputData = {
14952
+ ...data,
14953
+ event: "reset.completed"
14954
+ };
14955
+ runtime.output.success(outputData, {
15065
14956
  command,
15066
14957
  entity: {
15067
- localCredentialsDeleted: data.localCredentialsDeleted,
15068
- revoked: data.revoked
14958
+ event: "reset.completed",
14959
+ installationReset: data.installationReset,
14960
+ localStateCleared: data.localStateCleared,
14961
+ remoteReset: data.remoteReset
15069
14962
  },
15070
- nextActions: [nextAction("login", "Authenticate again", cliCommands.auth.login(), "Logout completed; authenticate again before further tool calls.", "after_logout")]
14963
+ nextActions: [nextAction("login", "Authenticate this fresh install", cliCommands.login.command(), "Reset completed; run login to create or reconnect this installation.", "after_reset"), nextAction("inspect_status", "Inspect status", cliCommands.status.command(), "Inspect the fresh-install CLI state and diagnostics.", "after_reset")]
15071
14964
  });
15072
14965
  };
15073
14966
  const executeCatalogInvocation = async (runtime, invocation) => {
15074
- const formatPaginationDetails = () => {
15075
- return `${invocation.cursor === void 0 ? "" : `--cursor ${invocation.cursor} `}${invocation.limit === void 0 ? "" : `--limit ${invocation.limit}`}`.trim();
15076
- };
15077
- const toCatalogExecutionPlan = () => {
15078
- if (invocation.serverId === void 0) {
15079
- if (invocation.example) return Result.err(new ValidationError({
15080
- details: "--example without <server-id> <tool-name>",
15081
- message: "Invalid catalog options. --example requires <server-id> <tool-name>.",
15082
- recovery: { command: cliCommands.catalog.command() }
15083
- }));
15084
- return Result.ok({
15085
- cursor: invocation.cursor,
15086
- kind: "summary",
15087
- limit: invocation.limit
15088
- });
15089
- }
15090
- if (invocation.toolName === void 0) {
15091
- if (invocation.cursor !== void 0 || invocation.limit !== void 0) return Result.err(new ValidationError({
15092
- details: formatPaginationDetails(),
15093
- message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
15094
- recovery: { command: cliCommands.catalog.command() }
15095
- }));
15096
- if (invocation.example) return Result.err(new ValidationError({
15097
- details: `--example without tool name for ${invocation.serverId}`,
15098
- message: "Invalid catalog options. --example requires <tool-name>.",
15099
- recovery: { command: cliCommands.catalog.server(invocation.serverId) }
15100
- }));
15101
- return Result.ok({
15102
- kind: "tools",
15103
- serverId: invocation.serverId
15104
- });
15105
- }
15106
- if (invocation.cursor !== void 0 || invocation.limit !== void 0) return Result.err(new ValidationError({
15107
- details: formatPaginationDetails(),
15108
- message: "Invalid catalog options. --cursor and --limit are only valid for `ogment catalog`.",
15109
- recovery: { command: cliCommands.catalog.tool(invocation.serverId, invocation.toolName, { example: invocation.example }) }
15110
- }));
15111
- return Result.ok({
15112
- example: invocation.example,
15113
- kind: "tool",
14967
+ if (invocation.toolName !== void 0 && invocation.serverId !== void 0) {
14968
+ const command = cliCommands.catalog.toolDetail(invocation.serverId, invocation.toolName, invocation.orgSlug);
14969
+ const data = ensureSuccess(await runCatalogToolDetailCommand(runtime.context, {
14970
+ includeDebug: runtime.output.debug,
14971
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15114
14972
  serverId: invocation.serverId,
15115
14973
  toolName: invocation.toolName
14974
+ }), runtime, {
14975
+ command,
14976
+ entity: {
14977
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
14978
+ serverId: invocation.serverId,
14979
+ toolName: invocation.toolName
14980
+ }
15116
14981
  });
15117
- };
15118
- const planResult = toCatalogExecutionPlan();
15119
- if (Result.isError(planResult)) throw planResult.error;
15120
- switch (planResult.value.kind) {
15121
- case "summary": {
15122
- const plan = planResult.value;
15123
- const command = cliCommands.catalog.summary({
15124
- ...plan.cursor === void 0 ? {} : { cursor: plan.cursor },
15125
- ...plan.limit === void 0 ? {} : { limit: plan.limit }
15126
- });
15127
- const data = ensureSuccess(await runCatalogCommand(runtime.context, {
15128
- ...plan.cursor === void 0 ? {} : { cursor: plan.cursor },
15129
- includeDebug: runtime.output.debug,
15130
- ...plan.limit === void 0 ? {} : { limit: plan.limit }
15131
- }), runtime, {
15132
- command,
15133
- entity: {
15134
- cursor: plan.cursor ?? null,
15135
- limit: plan.limit ?? null
15136
- }
15137
- });
15138
- const outputData = {
15139
- failures: data.failures,
15140
- servers: data.servers
15141
- };
15142
- runtime.output.success(outputData, {
15143
- command,
15144
- entity: {
15145
- cursor: plan.cursor ?? null,
15146
- failedServerCount: data.failures.length,
15147
- limit: plan.limit ?? null,
15148
- serverCount: data.servers.length
15149
- },
15150
- nextActions: nextActionsForCatalogSummary(outputData, {
15151
- limit: plan.limit ?? null,
15152
- nextCursor: data.nextCursor
15153
- }),
15154
- pagination: { nextCursor: data.nextCursor }
15155
- });
15156
- return;
15157
- }
15158
- case "tools": {
15159
- const command = cliCommands.catalog.server(planResult.value.serverId);
15160
- const data = ensureSuccess(await runCatalogToolsCommand(runtime.context, { serverId: planResult.value.serverId }), runtime, {
15161
- command,
15162
- entity: { serverId: planResult.value.serverId }
15163
- });
15164
- runtime.output.success(data, {
15165
- command,
15166
- entity: {
15167
- serverId: data.server.serverId,
15168
- toolCount: data.tools.length
15169
- },
15170
- nextActions: nextActionsForCatalogTools(data)
15171
- });
15172
- return;
14982
+ runtime.output.success(data, {
14983
+ command,
14984
+ entity: {
14985
+ orgSlug: data.server.orgSlug,
14986
+ serverId: data.server.serverId,
14987
+ toolName: data.tool.name
14988
+ },
14989
+ nextActions: nextActionsForCatalogToolDetail(data)
14990
+ });
14991
+ return;
14992
+ }
14993
+ if (invocation.serverId !== void 0) {
14994
+ const command = cliCommands.catalog.detail(invocation.serverId, invocation.orgSlug);
14995
+ const data = ensureSuccess(await runCatalogServerDetailCommand(runtime.context, {
14996
+ includeDebug: runtime.output.debug,
14997
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
14998
+ serverId: invocation.serverId
14999
+ }), runtime, {
15000
+ command,
15001
+ entity: {
15002
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15003
+ serverId: invocation.serverId
15004
+ }
15005
+ });
15006
+ runtime.output.success(data, {
15007
+ command,
15008
+ entity: {
15009
+ orgSlug: data.server.orgSlug,
15010
+ serverId: data.server.serverId
15011
+ },
15012
+ nextActions: nextActionsForCatalogServerDetail(data)
15013
+ });
15014
+ return;
15015
+ }
15016
+ const command = cliCommands.catalog.summary({
15017
+ ...invocation.cursor === void 0 ? {} : { cursor: invocation.cursor },
15018
+ ...invocation.limit === void 0 ? {} : { limit: invocation.limit },
15019
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug }
15020
+ });
15021
+ const data = ensureSuccess(await runCatalogCommand(runtime.context, {
15022
+ ...invocation.cursor === void 0 ? {} : { cursor: invocation.cursor },
15023
+ ...invocation.limit === void 0 ? {} : { limit: invocation.limit },
15024
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug }
15025
+ }), runtime, {
15026
+ command,
15027
+ entity: {
15028
+ cursor: invocation.cursor ?? null,
15029
+ limit: invocation.limit ?? null,
15030
+ orgSlug: invocation.orgSlug ?? null
15173
15031
  }
15174
- case "tool": {
15175
- const command = cliCommands.catalog.tool(planResult.value.serverId, planResult.value.toolName, { example: planResult.value.example });
15176
- const data = ensureSuccess(await runCatalogToolDetailsCommand(runtime.context, {
15177
- serverId: planResult.value.serverId,
15178
- toolName: planResult.value.toolName
15179
- }), runtime, {
15180
- command,
15181
- entity: {
15182
- serverId: planResult.value.serverId,
15183
- toolName: planResult.value.toolName
15184
- }
15185
- });
15186
- const exampleInput = toJsonValue(buildJsonSchemaExample(data.inputSchema));
15187
- const outputData = planResult.value.example ? {
15188
- ...data,
15189
- exampleInput
15190
- } : data;
15191
- runtime.output.success(outputData, {
15192
- command,
15193
- entity: {
15194
- serverId: data.server.serverId,
15195
- toolName: data.name
15196
- },
15197
- nextActions: nextActionsForCatalogToolDetails(data, exampleInput)
15198
- });
15199
- return;
15032
+ });
15033
+ const outputData = {
15034
+ failures: data.failures,
15035
+ servers: data.servers
15036
+ };
15037
+ runtime.output.success(outputData, {
15038
+ command,
15039
+ entity: {
15040
+ cursor: invocation.cursor ?? null,
15041
+ failedServerCount: data.failures.length,
15042
+ limit: invocation.limit ?? null,
15043
+ orgSlug: invocation.orgSlug ?? null,
15044
+ serverCount: data.servers.length
15045
+ },
15046
+ nextActions: nextActionsForCatalogSummary(outputData, {
15047
+ limit: invocation.limit ?? null,
15048
+ nextCursor: data.nextCursor,
15049
+ orgSlug: invocation.orgSlug ?? null
15050
+ }),
15051
+ pagination: { nextCursor: data.nextCursor }
15052
+ });
15053
+ };
15054
+ const executeSearchInvocation = async (runtime, invocation) => {
15055
+ const codeSource = codeSourceFromValue(invocation.code);
15056
+ const command = codeSource === "stdin" ? cliCommands.search.stdinCode(invocation.serverId, invocation.orgSlug) : cliCommands.search.withCodeValue(invocation.serverId, invocation.code, invocation.orgSlug);
15057
+ const data = ensureSuccess(await runSearchCommand(runtime.context, {
15058
+ code: invocation.code,
15059
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15060
+ serverId: invocation.serverId
15061
+ }), runtime, {
15062
+ command,
15063
+ entity: {
15064
+ codeSource,
15065
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15066
+ serverId: invocation.serverId
15200
15067
  }
15201
- }
15068
+ });
15069
+ runtime.output.success(data, {
15070
+ command,
15071
+ entity: {
15072
+ codeSource,
15073
+ ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15074
+ serverId: data.serverId
15075
+ },
15076
+ nextActions: nextActionsForSearch(data)
15077
+ });
15202
15078
  };
15203
- const executeInvokeInvocation = async (runtime, invocation) => {
15204
- let inputSource = "none";
15205
- let command = cliCommands.invoke.command(invocation.serverId, invocation.toolName, invocation.orgSlug);
15206
- if (invocation.input !== void 0) if (invocation.input === "-") {
15207
- inputSource = "stdin";
15208
- command = cliCommands.invoke.stdin(invocation.serverId, invocation.toolName, invocation.orgSlug);
15209
- } else if (invocation.input.startsWith("@")) {
15210
- inputSource = "file";
15211
- command = cliCommands.invoke.withInputValue(invocation.serverId, invocation.toolName, invocation.input, invocation.orgSlug);
15212
- } else {
15213
- inputSource = "inline_json";
15214
- command = cliCommands.invoke.inlineJson(invocation.serverId, invocation.toolName, invocation.orgSlug);
15215
- }
15216
- const data = ensureSuccess(await runInvokeCommand(runtime.context, {
15079
+ const executeExecuteInvocation = async (runtime, invocation) => {
15080
+ const codeSource = codeSourceFromValue(invocation.code);
15081
+ const inputSource = inputSourceFromValue(invocation.input);
15082
+ const command = codeSource === "stdin" ? cliCommands.execute.stdinCode(invocation.serverId, invocation.orgSlug) : cliCommands.execute.withCodeAndInputValue(invocation.serverId, invocation.code, invocation.input, invocation.orgSlug);
15083
+ const data = ensureSuccess(await runExecuteCommand(runtime.context, {
15084
+ code: invocation.code,
15217
15085
  input: invocation.input,
15218
15086
  ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15219
- serverId: invocation.serverId,
15220
- toolName: invocation.toolName
15087
+ serverId: invocation.serverId
15221
15088
  }), runtime, {
15222
15089
  command,
15223
15090
  entity: {
15091
+ codeSource,
15224
15092
  inputSource,
15225
15093
  ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15226
- serverId: invocation.serverId,
15227
- toolName: invocation.toolName
15094
+ serverId: invocation.serverId
15228
15095
  }
15229
15096
  });
15230
15097
  runtime.output.success(data, {
15231
15098
  command,
15232
15099
  entity: {
15100
+ codeSource,
15233
15101
  inputSource,
15234
15102
  ...invocation.orgSlug === void 0 ? {} : { orgSlug: invocation.orgSlug },
15235
- serverId: data.serverId,
15236
- toolName: data.toolName
15103
+ serverId: data.serverId
15237
15104
  },
15238
- nextActions: nextActionsForInvoke(data)
15105
+ nextActions: nextActionsForExecute(data)
15239
15106
  });
15240
15107
  };
15241
15108
  const executeStatusInvocation = async (runtime) => {
@@ -15254,29 +15121,32 @@ const executeRootInvocation = (runtime) => {
15254
15121
  runtime.output.success({ commands: cliCommands.root.commandsSurface() }, {
15255
15122
  command: cliCommands.root.command(),
15256
15123
  entity: null,
15257
- 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")]
15124
+ nextActions: [nextAction("login", "Authenticate", cliCommands.login.command(), "Authenticate first so catalog, search, and execute commands can run.", "immediate"), nextAction("catalog", "Discover servers", cliCommands.catalog.command(), "List accessible servers before running Codemode search or execute.", "after_auth")]
15258
15125
  });
15259
15126
  };
15260
15127
  const executeInvocation = async (runtime, invocation) => {
15261
15128
  switch (invocation.kind) {
15262
- case "auth_login":
15263
- await executeAuthLoginInvocation(runtime, invocation);
15129
+ case "login":
15130
+ await executeLoginInvocation(runtime, invocation);
15264
15131
  return;
15265
- case "auth_logout":
15266
- await executeAuthLogoutInvocation(runtime);
15132
+ case "logout":
15133
+ await executeLogoutInvocation(runtime);
15267
15134
  return;
15268
- case "auth_status":
15269
- await executeAuthStatusInvocation(runtime);
15135
+ case "reset":
15136
+ await executeResetInvocation(runtime);
15270
15137
  return;
15271
15138
  case "catalog":
15272
15139
  await executeCatalogInvocation(runtime, invocation);
15273
15140
  return;
15274
- case "invoke":
15275
- await executeInvokeInvocation(runtime, invocation);
15141
+ case "execute":
15142
+ await executeExecuteInvocation(runtime, invocation);
15276
15143
  return;
15277
15144
  case "root":
15278
15145
  executeRootInvocation(runtime);
15279
15146
  return;
15147
+ case "search":
15148
+ await executeSearchInvocation(runtime, invocation);
15149
+ return;
15280
15150
  case "status":
15281
15151
  await executeStatusInvocation(runtime);
15282
15152
  return;
@@ -15339,19 +15209,19 @@ const nextActionForParseError = (scope, helpCommand) => {
15339
15209
  };
15340
15210
  };
15341
15211
  const parseActionsForScope = (scope, helpAction) => {
15342
- if (scope === "auth") return [
15212
+ if (scope === "login" || scope === "logout" || scope === "reset") return [
15343
15213
  {
15344
- command: cliCommands.auth.login(),
15345
- id: "auth_login",
15346
- reason: "Authenticate with device flow.",
15347
- title: "Auth login",
15214
+ command: cliCommands.login.command(),
15215
+ id: "login",
15216
+ reason: "Authenticate this CLI installation.",
15217
+ title: "Login",
15348
15218
  when: "immediate"
15349
15219
  },
15350
15220
  {
15351
- command: cliCommands.auth.status(),
15352
- id: "auth_status",
15353
- reason: "Check current local authentication state.",
15354
- title: "Auth status",
15221
+ command: cliCommands.status.command(),
15222
+ id: "status",
15223
+ reason: "Inspect the current CLI state and diagnostics.",
15224
+ title: "Status",
15355
15225
  when: "immediate"
15356
15226
  },
15357
15227
  helpAction
@@ -15359,15 +15229,22 @@ const parseActionsForScope = (scope, helpAction) => {
15359
15229
  if (scope === "catalog") return [{
15360
15230
  command: cliCommands.catalog.command(),
15361
15231
  id: "catalog_summary",
15362
- reason: "List available servers and follow progressive discovery.",
15232
+ reason: "List available servers before selecting a Codemode target.",
15363
15233
  title: "Catalog servers",
15364
15234
  when: "immediate"
15365
15235
  }, helpAction];
15366
- if (scope === "invoke") return [{
15236
+ if (scope === "search") return [{
15367
15237
  command: cliCommands.catalog.command(),
15368
- id: "invoke_prepare",
15369
- reason: "Discover servers and tools before invoking a target command.",
15370
- title: "Discover tools",
15238
+ id: "search_prepare",
15239
+ reason: "Discover servers before running Codemode search.",
15240
+ title: "Discover servers",
15241
+ when: "immediate"
15242
+ }, helpAction];
15243
+ if (scope === "execute") return [{
15244
+ command: cliCommands.catalog.command(),
15245
+ id: "execute_prepare",
15246
+ reason: "Discover servers before running Codemode execute.",
15247
+ title: "Discover servers",
15371
15248
  when: "immediate"
15372
15249
  }, helpAction];
15373
15250
  if (scope === null) return [helpAction];
@@ -60807,8 +60684,8 @@ const createAccountService = (deps) => {
60807
60684
  mapStatusError: (response, body) => {
60808
60685
  if (response.status === 401) return new AuthError({
60809
60686
  code: ERROR_CODE.authInvalidCredentials,
60810
- message: "Authentication failed. Run `ogment auth login` again.",
60811
- recovery: { command: "ogment auth login" }
60687
+ message: "Authentication failed. Run `ogment login` again.",
60688
+ recovery: { command: "ogment login" }
60812
60689
  });
60813
60690
  return new RemoteRequestError({
60814
60691
  body,
@@ -60829,7 +60706,6 @@ const createAccountService = (deps) => {
60829
60706
 
60830
60707
  //#endregion
60831
60708
  //#region src/services/auth.ts
60832
- const DEFAULT_NAMESPACE_KEY = "default";
60833
60709
  const toEndpointUrl = (baseUrl, endpoint) => {
60834
60710
  return `${baseUrl}${endpoint}`;
60835
60711
  };
@@ -60839,85 +60715,138 @@ const authStartUrl = (baseUrl) => {
60839
60715
  const authExchangeUrl = (baseUrl) => {
60840
60716
  return toEndpointUrl(baseUrl, cliEndpoints.authExchange);
60841
60717
  };
60842
- const isExpiredPendingRequest = (request, nowMs) => {
60718
+ const authLogoutUrl = (baseUrl) => {
60719
+ return toEndpointUrl(baseUrl, cliEndpoints.authLogout);
60720
+ };
60721
+ const authResetUrl = (baseUrl) => {
60722
+ return toEndpointUrl(baseUrl, cliEndpoints.authReset);
60723
+ };
60724
+ const accountMeUrl = (baseUrl) => {
60725
+ return toEndpointUrl(baseUrl, cliEndpoints.accountMe);
60726
+ };
60727
+ const toLoginPendingInfo = (request) => {
60728
+ if (request === null) return null;
60729
+ return {
60730
+ authRequestId: request.authRequestId,
60731
+ verificationUrl: request.verificationUrl
60732
+ };
60733
+ };
60734
+ const isExpiredCurrentAuthRequest = (request, nowMs) => {
60843
60735
  const parsedExpiresAt = Date.parse(request.expiresAt);
60844
60736
  return !Number.isNaN(parsedExpiresAt) && parsedExpiresAt <= nowMs;
60845
60737
  };
60846
60738
  const createAuthService = (deps) => {
60847
60739
  const now = deps.now ?? Date.now;
60848
- const storeApprovedAuth = (approvedAuth, namespaceKey = DEFAULT_NAMESPACE_KEY) => {
60849
- return deps.credentialsStore.storeApprovedAuth({
60850
- agentName: approvedAuth.agentName,
60851
- apiKey: approvedAuth.apiKey
60852
- }, namespaceKey);
60853
- };
60854
- const saveApiKeyAuth = (approvedAuth) => {
60740
+ const storeApprovedAuth = (approvedAuth) => {
60855
60741
  return deps.credentialsStore.save({
60742
+ agentId: approvedAuth.agentId,
60856
60743
  agentName: approvedAuth.agentName,
60857
- apiKey: approvedAuth.apiKey
60744
+ apiKey: approvedAuth.apiKey,
60745
+ credentialId: approvedAuth.credentialId,
60746
+ signedInAt: new Date(now()).toISOString()
60858
60747
  });
60859
60748
  };
60860
- const tryExchangePendingRequests = async () => {
60861
- const installationIdResult = deps.credentialsStore.getInstallationId();
60862
- if (Result.isError(installationIdResult)) return installationIdResult;
60863
- const pendingRequestsResult = deps.credentialsStore.listPendingRequests();
60864
- if (Result.isError(pendingRequestsResult)) return pendingRequestsResult;
60865
- const pendingRequests = [...pendingRequestsResult.value].toSorted((a, b) => {
60866
- return a.createdAt.localeCompare(b.createdAt);
60749
+ const loadLocalAuthSnapshot = () => {
60750
+ const installationId = deps.credentialsStore.getInstallationId();
60751
+ if (Result.isError(installationId)) return installationId;
60752
+ const session = deps.credentialsStore.load();
60753
+ if (Result.isError(session)) return session;
60754
+ const currentAuthRequest = deps.credentialsStore.getCurrentAuthRequest();
60755
+ if (Result.isError(currentAuthRequest)) return currentAuthRequest;
60756
+ return Result.ok({
60757
+ currentAuthRequest: currentAuthRequest.value,
60758
+ installationId: installationId.value,
60759
+ session: session.value
60867
60760
  });
60868
- for (const pendingRequest of pendingRequests) {
60869
- if (isExpiredPendingRequest(pendingRequest, now())) {
60870
- const deleteResult = deps.credentialsStore.deletePendingRequest(pendingRequest.authRequestId);
60871
- if (Result.isError(deleteResult)) return deleteResult;
60872
- continue;
60873
- }
60874
- const exchangePayload = await requestJson(deps.httpClient, authExchangeUrl(deps.baseUrl), authExchangeSchema, {
60875
- body: JSON.stringify({
60876
- authRequestId: pendingRequest.authRequestId,
60877
- installationId: installationIdResult.value,
60878
- namespaceKey: pendingRequest.namespaceKey
60879
- }),
60880
- headers: { "Content-Type": "application/json" },
60881
- method: "POST"
60882
- }, {
60883
- context: "auth exchange response",
60884
- mapStatusError: (response, body) => new RemoteRequestError({
60761
+ };
60762
+ const clearCurrentAuthRequest = () => {
60763
+ return deps.credentialsStore.clearCurrentAuthRequest();
60764
+ };
60765
+ const toStoredAuthorizationHeader = (session) => {
60766
+ return session === null ? null : `Bearer ${session.apiKey}`;
60767
+ };
60768
+ const validateStoredCredentials = async (apiKey) => {
60769
+ const response = await requestJson(deps.httpClient, accountMeUrl(deps.baseUrl), accountMeSchema, { headers: { Authorization: `Bearer ${apiKey}` } }, {
60770
+ context: "account response",
60771
+ mapStatusError: (httpResponse, body) => {
60772
+ if (httpResponse.status === 401) return new AuthError({
60773
+ code: ERROR_CODE.authInvalidCredentials,
60774
+ message: "Stored CLI session is invalid. Run `ogment login` to sign in again.",
60775
+ recovery: { command: "ogment login" }
60776
+ });
60777
+ return new RemoteRequestError({
60885
60778
  body,
60886
- httpStatus: response.status,
60887
- message: "Failed to exchange pending CLI auth",
60888
- operation: "auth/exchange",
60779
+ httpStatus: httpResponse.status,
60780
+ message: "Failed to validate current CLI session",
60781
+ operation: "account/fetch",
60889
60782
  raw: body,
60890
60783
  source: "http"
60891
- }),
60892
- operation: "auth/exchange"
60893
- });
60894
- if (Result.isError(exchangePayload)) return exchangePayload;
60895
- const exchangeData = exchangePayload.value.data;
60896
- if (exchangeData.status === "authorization_pending") continue;
60897
- if (exchangeData.status === "approved") {
60898
- const storeResult = storeApprovedAuth({
60899
- agentName: exchangeData.agentName,
60900
- apiKey: exchangeData.apiKey
60901
- }, pendingRequest.namespaceKey);
60902
- if (Result.isError(storeResult)) return storeResult;
60903
- return Result.ok({
60904
- agentName: exchangeData.agentName,
60905
- apiKey: exchangeData.apiKey
60906
60784
  });
60907
- }
60908
- const deleteResult = deps.credentialsStore.deletePendingRequest(pendingRequest.authRequestId);
60909
- if (Result.isError(deleteResult)) return deleteResult;
60785
+ },
60786
+ operation: "account/fetch"
60787
+ });
60788
+ if (Result.isError(response)) {
60789
+ if (response.error instanceof AuthError && response.error.code === ERROR_CODE.authInvalidCredentials) return Result.ok(false);
60790
+ return response;
60910
60791
  }
60911
- return Result.ok(null);
60792
+ return Result.ok(true);
60912
60793
  };
60913
- const loginWithDevice = async (options) => {
60914
- const installationIdResult = deps.credentialsStore.getInstallationId();
60915
- if (Result.isError(installationIdResult)) return installationIdResult;
60794
+ const exchangeCurrentAuthRequest = async (snapshot) => {
60795
+ const currentAuthRequest = snapshot.currentAuthRequest;
60796
+ if (currentAuthRequest === null) return Result.ok({ kind: "none" });
60797
+ if (isExpiredCurrentAuthRequest(currentAuthRequest, now())) {
60798
+ const clearResult = clearCurrentAuthRequest();
60799
+ if (Result.isError(clearResult)) return clearResult;
60800
+ return Result.ok({ kind: "none" });
60801
+ }
60802
+ const exchangePayload = await requestJson(deps.httpClient, authExchangeUrl(deps.baseUrl), authExchangeSchema, {
60803
+ body: JSON.stringify({
60804
+ authRequestId: currentAuthRequest.authRequestId,
60805
+ installationId: snapshot.installationId
60806
+ }),
60807
+ headers: { "Content-Type": "application/json" },
60808
+ method: "POST"
60809
+ }, {
60810
+ context: "auth exchange response",
60811
+ mapStatusError: (response, body) => new RemoteRequestError({
60812
+ body,
60813
+ httpStatus: response.status,
60814
+ message: "Failed to exchange current CLI auth request",
60815
+ operation: "auth/exchange",
60816
+ raw: body,
60817
+ source: "http"
60818
+ }),
60819
+ operation: "auth/exchange"
60820
+ });
60821
+ if (Result.isError(exchangePayload)) return exchangePayload;
60822
+ const exchangeData = exchangePayload.value.data;
60823
+ if (exchangeData.status === "authorization_pending") return Result.ok({
60824
+ kind: "pending",
60825
+ request: currentAuthRequest
60826
+ });
60827
+ if (exchangeData.status === "approved") {
60828
+ const approvedAuth = {
60829
+ agentId: exchangeData.agentId,
60830
+ agentName: exchangeData.agentName,
60831
+ apiKey: exchangeData.apiKey,
60832
+ credentialId: exchangeData.credentialId
60833
+ };
60834
+ const storeResult = storeApprovedAuth(approvedAuth);
60835
+ if (Result.isError(storeResult)) return storeResult;
60836
+ return Result.ok({
60837
+ auth: approvedAuth,
60838
+ kind: "approved"
60839
+ });
60840
+ }
60841
+ const clearResult = clearCurrentAuthRequest();
60842
+ if (Result.isError(clearResult)) return clearResult;
60843
+ return Result.ok({ kind: "none" });
60844
+ };
60845
+ const startOrRecoverLogin = async (installationId, options) => {
60916
60846
  const startPayload = await requestJson(deps.httpClient, authStartUrl(deps.baseUrl), authStartSchema, {
60917
60847
  body: JSON.stringify({
60918
60848
  ...deps.executionEnvironment === void 0 ? {} : { executionEnvironment: deps.executionEnvironment },
60919
- installationId: installationIdResult.value,
60920
- namespaceKey: DEFAULT_NAMESPACE_KEY
60849
+ installationId
60921
60850
  }),
60922
60851
  headers: { "Content-Type": "application/json" },
60923
60852
  method: "POST"
@@ -60934,76 +60863,140 @@ const createAuthService = (deps) => {
60934
60863
  operation: "auth/start"
60935
60864
  });
60936
60865
  if (Result.isError(startPayload)) return startPayload;
60937
- const savePendingRequestResult = deps.credentialsStore.savePendingRequest({
60866
+ const currentAuthRequest = {
60938
60867
  authRequestId: startPayload.value.data.authRequestId,
60939
- code: startPayload.value.data.userCode,
60940
- createdAt: new Date(now()).toISOString(),
60941
60868
  expiresAt: startPayload.value.data.expiresAt,
60942
- namespaceKey: DEFAULT_NAMESPACE_KEY,
60943
60869
  verificationUrl: startPayload.value.data.verificationUrl
60944
- });
60945
- if (Result.isError(savePendingRequestResult)) return savePendingRequestResult;
60946
- const verification = {
60947
- userCode: startPayload.value.data.userCode,
60948
- verificationUri: startPayload.value.data.verificationUrl
60949
60870
  };
60950
- options.onPending?.(verification);
60871
+ const saveCurrentAuthRequestResult = deps.credentialsStore.saveCurrentAuthRequest(currentAuthRequest);
60872
+ if (Result.isError(saveCurrentAuthRequestResult)) return saveCurrentAuthRequestResult;
60873
+ if (startPayload.value.data.disposition === "reused_approved") {
60874
+ const exchangedCurrentAuthRequest = await exchangeCurrentAuthRequest({
60875
+ currentAuthRequest,
60876
+ installationId,
60877
+ session: null
60878
+ });
60879
+ if (Result.isError(exchangedCurrentAuthRequest)) return exchangedCurrentAuthRequest;
60880
+ if (exchangedCurrentAuthRequest.value.kind === "approved") return Result.ok({
60881
+ agentName: exchangedCurrentAuthRequest.value.auth.agentName,
60882
+ loggedIn: true,
60883
+ outcome: "authenticated"
60884
+ });
60885
+ }
60886
+ const verification = toLoginPendingInfo(currentAuthRequest);
60887
+ if (verification !== null) options.onPending?.(verification);
60951
60888
  return Result.ok({
60952
60889
  agentName: null,
60953
60890
  loggedIn: false,
60954
60891
  outcome: "pending_approval",
60955
- verification
60892
+ verification: verification ?? {
60893
+ authRequestId: currentAuthRequest.authRequestId,
60894
+ verificationUrl: currentAuthRequest.verificationUrl
60895
+ }
60956
60896
  });
60957
60897
  };
60958
60898
  return {
60959
60899
  login: async (options) => {
60960
- if (options.mode === "apiKey" && options.apiKey.length > 0) {
60961
- const saveResult = saveApiKeyAuth({
60962
- agentName: "CLI Agent",
60963
- apiKey: options.apiKey
60964
- });
60965
- if (Result.isError(saveResult)) return saveResult;
60966
- return Result.ok({
60967
- agentName: "CLI Agent",
60900
+ const snapshot = loadLocalAuthSnapshot();
60901
+ if (Result.isError(snapshot)) return snapshot;
60902
+ if (snapshot.value.session !== null) {
60903
+ const validationResult = await validateStoredCredentials(snapshot.value.session.apiKey);
60904
+ if (Result.isError(validationResult)) return validationResult;
60905
+ if (validationResult.value) return Result.ok({
60906
+ agentName: snapshot.value.session.agentName ?? "CLI Agent",
60968
60907
  loggedIn: true,
60969
- outcome: "authenticated"
60908
+ outcome: "already_authenticated"
60970
60909
  });
60910
+ const deleteResult = deps.credentialsStore.delete();
60911
+ if (Result.isError(deleteResult)) return deleteResult;
60971
60912
  }
60972
- if (options.mode === "apiKey") return Result.err(new ValidationError({
60973
- code: ERROR_CODE.validationInvalidInput,
60974
- message: "Missing API key value. Provide a non-empty API key.",
60975
- recovery: { command: "ogment auth login --api-key <key>" }
60976
- }));
60977
- const stored = deps.credentialsStore.load();
60978
- if (Result.isError(stored)) return stored;
60979
- if (stored.value !== null) return Result.ok({
60980
- agentName: stored.value.agentName ?? "CLI Agent",
60981
- loggedIn: true,
60982
- outcome: "already_authenticated"
60983
- });
60984
- const exchangedPendingAuth = await tryExchangePendingRequests();
60985
- if (Result.isError(exchangedPendingAuth)) return exchangedPendingAuth;
60986
- if (exchangedPendingAuth.value !== null) return Result.ok({
60987
- agentName: exchangedPendingAuth.value.agentName,
60913
+ const exchangedCurrentAuthRequest = await exchangeCurrentAuthRequest(snapshot.value);
60914
+ if (Result.isError(exchangedCurrentAuthRequest)) return exchangedCurrentAuthRequest;
60915
+ if (exchangedCurrentAuthRequest.value.kind === "approved") return Result.ok({
60916
+ agentName: exchangedCurrentAuthRequest.value.auth.agentName,
60988
60917
  loggedIn: true,
60989
60918
  outcome: "authenticated"
60990
60919
  });
60991
- return loginWithDevice(options);
60920
+ if (exchangedCurrentAuthRequest.value.kind === "pending") {
60921
+ const verification = toLoginPendingInfo(exchangedCurrentAuthRequest.value.request);
60922
+ if (verification !== null) options.onPending?.(verification);
60923
+ return Result.ok({
60924
+ agentName: null,
60925
+ loggedIn: false,
60926
+ outcome: "pending_approval",
60927
+ verification: verification ?? {
60928
+ authRequestId: exchangedCurrentAuthRequest.value.request.authRequestId,
60929
+ verificationUrl: exchangedCurrentAuthRequest.value.request.verificationUrl
60930
+ }
60931
+ });
60932
+ }
60933
+ return startOrRecoverLogin(snapshot.value.installationId, options);
60992
60934
  },
60993
60935
  logout: async () => {
60994
- const stored = deps.credentialsStore.load();
60995
- if (Result.isError(stored)) return stored;
60996
- const pendingRequestsResult = deps.credentialsStore.listPendingRequests();
60997
- if (Result.isError(pendingRequestsResult)) return pendingRequestsResult;
60998
- if (!(stored.value !== null || pendingRequestsResult.value.length > 0)) return Result.ok({
60999
- localCredentialsDeleted: false,
61000
- revoked: false
60936
+ const snapshot = loadLocalAuthSnapshot();
60937
+ if (Result.isError(snapshot)) return snapshot;
60938
+ if (snapshot.value.session === null) return Result.ok({
60939
+ localStateCleared: false,
60940
+ remoteSignedOut: false
61001
60941
  });
60942
+ const storedAuthorizationHeader = toStoredAuthorizationHeader(snapshot.value.session);
60943
+ let remoteSignedOut = false;
60944
+ if (storedAuthorizationHeader !== null) {
60945
+ const logoutPayload = await requestJson(deps.httpClient, authLogoutUrl(deps.baseUrl), authLogoutSchema, {
60946
+ headers: { Authorization: storedAuthorizationHeader },
60947
+ method: "POST"
60948
+ }, {
60949
+ context: "auth logout response",
60950
+ mapStatusError: (response, body) => new RemoteRequestError({
60951
+ body,
60952
+ httpStatus: response.status,
60953
+ message: "Failed to sign out current CLI session",
60954
+ operation: "auth/logout",
60955
+ raw: body,
60956
+ source: "http"
60957
+ }),
60958
+ operation: "auth/logout"
60959
+ });
60960
+ if (Result.isOk(logoutPayload)) remoteSignedOut = true;
60961
+ }
61002
60962
  const deleteResult = deps.credentialsStore.delete();
61003
60963
  if (Result.isError(deleteResult)) return deleteResult;
61004
60964
  return Result.ok({
61005
- localCredentialsDeleted: true,
61006
- revoked: false
60965
+ localStateCleared: true,
60966
+ remoteSignedOut
60967
+ });
60968
+ },
60969
+ reset: async () => {
60970
+ const snapshot = loadLocalAuthSnapshot();
60971
+ if (Result.isError(snapshot)) return snapshot;
60972
+ const storedAuthorizationHeader = toStoredAuthorizationHeader(snapshot.value.session);
60973
+ const remoteResetResult = await requestJson(deps.httpClient, authResetUrl(deps.baseUrl), authResetSchema, {
60974
+ body: JSON.stringify({ installationId: snapshot.value.installationId }),
60975
+ headers: {
60976
+ "Content-Type": "application/json",
60977
+ ...storedAuthorizationHeader === null ? {} : { Authorization: storedAuthorizationHeader }
60978
+ },
60979
+ method: "POST"
60980
+ }, {
60981
+ context: "auth reset response",
60982
+ mapStatusError: (response, body) => new RemoteRequestError({
60983
+ body,
60984
+ httpStatus: response.status,
60985
+ message: "Failed to reset current CLI installation",
60986
+ operation: "auth/reset",
60987
+ raw: body,
60988
+ source: "http"
60989
+ }),
60990
+ operation: "auth/reset"
60991
+ });
60992
+ const remoteReset = Result.isOk(remoteResetResult);
60993
+ const localStateCleared = snapshot.value.session !== null || snapshot.value.currentAuthRequest !== null;
60994
+ const resetLocalStateResult = deps.credentialsStore.reset();
60995
+ if (Result.isError(resetLocalStateResult)) return resetLocalStateResult;
60996
+ return Result.ok({
60997
+ installationReset: true,
60998
+ localStateCleared,
60999
+ remoteReset
61007
61000
  });
61008
61001
  },
61009
61002
  resolveApiKey: async (overrideApiKey) => {
@@ -61014,42 +61007,16 @@ const createAuthService = (deps) => {
61014
61007
  });
61015
61008
  if (resolution.apiKey !== null) return Result.ok(resolution.apiKey);
61016
61009
  if (resolution.source === "credentialsError" && resolution.loadError) return Result.err(resolution.loadError);
61017
- const exchangedPendingAuth = await tryExchangePendingRequests();
61018
- if (Result.isError(exchangedPendingAuth)) return exchangedPendingAuth;
61019
- if (exchangedPendingAuth.value !== null) return Result.ok(exchangedPendingAuth.value.apiKey);
61010
+ const snapshot = loadLocalAuthSnapshot();
61011
+ if (Result.isError(snapshot)) return snapshot;
61012
+ const exchangedCurrentAuthRequest = await exchangeCurrentAuthRequest(snapshot.value);
61013
+ if (Result.isError(exchangedCurrentAuthRequest)) return exchangedCurrentAuthRequest;
61014
+ if (exchangedCurrentAuthRequest.value.kind === "approved") return Result.ok(exchangedCurrentAuthRequest.value.auth.apiKey);
61020
61015
  return Result.err(new AuthError({
61021
61016
  code: ERROR_CODE.authRequired,
61022
- message: "Not logged in. Run `ogment auth login` or set OGMENT_API_KEY.",
61023
- recovery: { command: "ogment auth login" }
61017
+ message: "Not logged in. Run `ogment login` or set OGMENT_API_KEY.",
61018
+ recovery: { command: "ogment login" }
61024
61019
  }));
61025
- },
61026
- status: async (overrideApiKey) => {
61027
- const resolution = resolveApiKey({
61028
- apiKeyOverride: overrideApiKey,
61029
- credentialsStore: deps.credentialsStore,
61030
- envApiKey: deps.envApiKey
61031
- });
61032
- if (resolution.source === "credentialsError" && resolution.loadError) return Result.err(resolution.loadError);
61033
- if (resolution.apiKey !== null) {
61034
- const apiKeySource = resolution.source === "credentialsFile" ? "credentialsFile" : resolution.source === "apiKeyOption" ? "apiKeyOption" : "env";
61035
- return Result.ok({
61036
- agentName: resolution.agentName,
61037
- apiKeySource,
61038
- loggedIn: true
61039
- });
61040
- }
61041
- const exchangedPendingAuth = await tryExchangePendingRequests();
61042
- if (Result.isError(exchangedPendingAuth)) return exchangedPendingAuth;
61043
- if (exchangedPendingAuth.value !== null) return Result.ok({
61044
- agentName: exchangedPendingAuth.value.agentName,
61045
- apiKeySource: "credentialsFile",
61046
- loggedIn: true
61047
- });
61048
- return Result.ok({
61049
- agentName: null,
61050
- apiKeySource: "none",
61051
- loggedIn: false
61052
- });
61053
61020
  }
61054
61021
  };
61055
61022
  };
@@ -61062,9 +61029,9 @@ const maskApiKey = (apiKey) => {
61062
61029
  };
61063
61030
  const nextActionByIssueCode = (includeDebug) => {
61064
61031
  return {
61065
- auth_failed: "Run `ogment auth login` to refresh credentials.",
61032
+ auth_failed: "Run `ogment login` to refresh credentials.",
61066
61033
  credentials_load_failed: "Check file permissions and contents of `~/.config/ogment/auth-state.json`.",
61067
- no_api_key: "Run `ogment auth login` or set `OGMENT_API_KEY`.",
61034
+ no_api_key: "Run `ogment login` or set `OGMENT_API_KEY`.",
61068
61035
  unreachable: includeDebug ? "Verify `OGMENT_BASE_URL` and network connectivity." : "Verify network connectivity."
61069
61036
  };
61070
61037
  };
@@ -61103,6 +61070,8 @@ const createInfoService = (deps) => {
61103
61070
  credentialsStore: deps.credentialsStore,
61104
61071
  envApiKey: deps.envApiKey
61105
61072
  });
61073
+ const installationIdResult = deps.credentialsStore.getInstallationId();
61074
+ const installationId = Result.isOk(installationIdResult) ? installationIdResult.value : null;
61106
61075
  const selectedApiKey = apiKeyResolution.apiKey;
61107
61076
  const credentialsFileExists = existsSyncFn(deps.credentialsPath);
61108
61077
  const endpoint = `${deps.baseUrl}${cliEndpoints.accountMe}`;
@@ -61127,6 +61096,7 @@ const createInfoService = (deps) => {
61127
61096
  };
61128
61097
  const collectAccount = async () => {
61129
61098
  if (selectedApiKey === null) return {
61099
+ actingAgent: null,
61130
61100
  ...emptyAccountErrorDetails(),
61131
61101
  errorType: null,
61132
61102
  latencyMs: null,
@@ -61144,6 +61114,12 @@ const createInfoService = (deps) => {
61144
61114
  return organization.servers.map((server) => server.path);
61145
61115
  });
61146
61116
  return {
61117
+ actingAgent: accountResult.value.actingAgent === null ? null : {
61118
+ agentId: accountResult.value.actingAgent.agentId,
61119
+ agentName: accountResult.value.actingAgent.agentName,
61120
+ boundInstallationId: accountResult.value.actingAgent.boundInstallationId,
61121
+ boundToCurrentInstallation: installationId === null || accountResult.value.actingAgent.boundInstallationId === null ? null : accountResult.value.actingAgent.boundInstallationId === installationId
61122
+ },
61147
61123
  ...emptyAccountErrorDetails(),
61148
61124
  errorType: null,
61149
61125
  latencyMs: accountElapsedMs,
@@ -61170,6 +61146,7 @@ const createInfoService = (deps) => {
61170
61146
  break;
61171
61147
  }
61172
61148
  return {
61149
+ actingAgent: null,
61173
61150
  ..."code" in accountResult.error ? { errorCode: String(accountResult.error.code) } : { errorCode: null },
61174
61151
  ..."httpStatus" in accountResult.error ? { errorHttpStatus: typeof accountResult.error.httpStatus === "number" ? accountResult.error.httpStatus : null } : { errorHttpStatus: null },
61175
61152
  ..."mcpCode" in accountResult.error ? { errorMcpCode: typeof accountResult.error.mcpCode === "number" ? accountResult.error.mcpCode : null } : { errorMcpCode: null },
@@ -61215,13 +61192,18 @@ const createInfoService = (deps) => {
61215
61192
  code: "unexpected_diagnostic_error",
61216
61193
  message: `Unexpected diagnostic error: ${account.message ?? "unknown error"}`
61217
61194
  });
61195
+ if (Result.isError(installationIdResult)) issues.push({
61196
+ code: "credentials_load_failed",
61197
+ message: `Failed to load installation identity: ${installationIdResult.error.message}`
61198
+ });
61218
61199
  return {
61219
61200
  auth: {
61220
61201
  apiKeyPresent: selectedApiKey !== null,
61221
61202
  apiKeyPreview: selectedApiKey === null ? null : maskApiKey(selectedApiKey),
61222
61203
  apiKeySource: apiKeyResolution.source,
61223
61204
  credentialsFileExists,
61224
- credentialsFileLoadError: apiKeyResolution.loadError?.message ?? null
61205
+ credentialsFileLoadError: apiKeyResolution.loadError?.message ?? null,
61206
+ installationId
61225
61207
  },
61226
61208
  config: {
61227
61209
  baseUrl: deps.baseUrl,
@@ -61238,11 +61220,12 @@ const createInfoService = (deps) => {
61238
61220
  ],
61239
61221
  quickCommands: [
61240
61222
  "ogment status",
61241
- "ogment auth login",
61223
+ "ogment login",
61224
+ "ogment logout",
61225
+ "ogment reset",
61242
61226
  "ogment catalog",
61243
- "ogment catalog <server-id>",
61244
- "ogment catalog <server-id> <tool-name>",
61245
- "ogment invoke <server-id> <tool-name> --input '{}'"
61227
+ "ogment search <server-id> --code 'return input'",
61228
+ "ogment execute <server-id> --code 'return input' --input '{}'"
61246
61229
  ]
61247
61230
  },
61248
61231
  generatedAt: new Date(now()).toISOString(),
@@ -71951,6 +71934,25 @@ const createRemoteRequestErrorFromMcpCause = (options) => {
71951
71934
  const MCP_CONNECT_TIMEOUT_MS = 1e4;
71952
71935
  const MCP_DISCOVERY_TIMEOUT_MS = 1e4;
71953
71936
  const MCP_INVOKE_TIMEOUT_MS = 45e3;
71937
+ const DEFAULT_PATH_PREFIX = "/api/v1/mcp";
71938
+ const normalizePathPrefix = (value) => {
71939
+ const candidate = value?.trim() || DEFAULT_PATH_PREFIX;
71940
+ if (candidate.startsWith("/")) return candidate;
71941
+ return `/${candidate}`;
71942
+ };
71943
+ const isLocalhost = (hostname) => {
71944
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.startsWith("192.168.") || hostname.endsWith(".local");
71945
+ };
71946
+ const buildMcpEndpointUrl = (baseUrl, pathPrefix, target) => {
71947
+ const base = new URL(baseUrl);
71948
+ if (isLocalhost(base.hostname)) return new URL(`${pathPrefix}/${target.orgSlug}/${target.serverPath}`, `${base.origin}/`);
71949
+ if (base.hostname.startsWith("dashboard.")) {
71950
+ const rootDomain = base.hostname.slice(10);
71951
+ const toolPath = pathPrefix === "/code" ? `/code/${target.serverPath}` : `/${target.serverPath}`;
71952
+ return new URL(`${base.protocol}//${target.orgSlug}.mcp.${rootDomain}${toolPath}`);
71953
+ }
71954
+ return new URL(`${pathPrefix}/${target.orgSlug}/${target.serverPath}`, `${base.origin}/`);
71955
+ };
71954
71956
  const defaultCreateClient = (version) => {
71955
71957
  return new Client({
71956
71958
  name: APP_NAME,
@@ -71963,9 +71965,9 @@ const defaultCreateTransport = (url, apiKey) => {
71963
71965
  const createMcpService = (deps) => {
71964
71966
  const createClient = deps.createClient ?? (() => defaultCreateClient(deps.version));
71965
71967
  const createTransport = deps.createTransport ?? defaultCreateTransport;
71968
+ const pathPrefix = normalizePathPrefix(deps.pathPrefix);
71966
71969
  const withClient = async (target, apiKey, handler) => {
71967
- const endpoint = `${deps.baseUrl}/api/v1/mcp/${target.orgSlug}/${target.serverPath}`;
71968
- const transport = createTransport(new URL(endpoint), apiKey);
71970
+ const transport = createTransport(buildMcpEndpointUrl(deps.baseUrl, pathPrefix, target), apiKey);
71969
71971
  const client = createClient();
71970
71972
  const connectResult = await Result.tryPromise({
71971
71973
  catch: (cause) => createRemoteRequestErrorFromMcpCause({
@@ -72030,9 +72032,7 @@ const createRuntime = () => {
72030
72032
  const output = new OutputManager();
72031
72033
  const authStateStore = createFileCredentialsStore({
72032
72034
  configDir: runtimeConfig.configDir,
72033
- credentialsPath: runtimeConfig.credentialsPath,
72034
- legacyCredentialsPath: runtimeConfig.legacyCredentialsPath,
72035
- telemetryPath: runtimeConfig.telemetryPath
72035
+ credentialsPath: runtimeConfig.credentialsPath
72036
72036
  });
72037
72037
  const httpClient = createHttpClient();
72038
72038
  const services = {
@@ -72047,6 +72047,11 @@ const createRuntime = () => {
72047
72047
  executionEnvironment,
72048
72048
  httpClient
72049
72049
  }),
72050
+ codemode: createMcpService({
72051
+ baseUrl: runtimeConfig.baseUrl,
72052
+ pathPrefix: "/code",
72053
+ version: runtimeConfig.version
72054
+ }),
72050
72055
  mcp: createMcpService({
72051
72056
  baseUrl: runtimeConfig.baseUrl,
72052
72057
  version: runtimeConfig.version
@@ -72152,9 +72157,12 @@ const createProgram = (runtime, parseState) => {
72152
72157
  return [
72153
72158
  "",
72154
72159
  "Examples:",
72155
- " $ ogment auth login",
72156
- " $ ogment catalog billing create_invoice --example",
72157
- " $ ogment invoke billing create_invoice --input '{\"amount\":100}'",
72160
+ " $ ogment login",
72161
+ " $ ogment catalog",
72162
+ " $ ogment catalog billing",
72163
+ " $ ogment catalog billing execute",
72164
+ " $ ogment search billing --code 'return input'",
72165
+ " $ ogment execute billing --code 'return input' --input '{}'",
72158
72166
  "",
72159
72167
  "Run `ogment help <command>` for command-specific usage."
72160
72168
  ].join("\n");
@@ -72164,48 +72172,44 @@ const createProgram = (runtime, parseState) => {
72164
72172
  runtime.output.configure(mapGlobalOutputOptions(options));
72165
72173
  runtime.context.apiKeyOverride = options.apiKey;
72166
72174
  });
72167
- const authCommand = program.command("auth").summary("Authenticate, inspect auth state, and logout").description("Authentication workflows").helpGroup("Authentication Commands:").helpCommand("help [command]", "Display help for auth commands").addHelpText("after", ({ error }) => {
72168
- if (error) return "";
72169
- return [
72170
- "",
72171
- "Examples:",
72172
- " $ ogment auth login",
72173
- " $ ogment auth status"
72174
- ].join("\n");
72175
+ program.command("login").summary("Authenticate this CLI installation").description("Start or complete browser-based login for this installation").helpGroup("Authentication Commands:").action(() => {
72176
+ setInvocation({ kind: "login" });
72175
72177
  });
72176
- authCommand.command("login").summary("Login with device flow (default)").description("Authenticate with Ogment using device flow (recommended)").action((_, command) => {
72177
- const { apiKey } = asGlobalOptions(command);
72178
- setInvocation({
72179
- apiKey,
72180
- kind: "auth_login"
72181
- });
72178
+ program.command("logout").summary("Sign this CLI installation out").description("Sign out the current local CLI session").helpGroup("Authentication Commands:").action(() => {
72179
+ setInvocation({ kind: "logout" });
72182
72180
  });
72183
- authCommand.command("status").summary("Show current auth state").description("Show local authentication status").action(() => {
72184
- setInvocation({ kind: "auth_status" });
72181
+ program.command("reset").summary("Reset this CLI installation").description("Wipe local state and create a fresh CLI installation identity").helpGroup("Authentication Commands:").action(() => {
72182
+ setInvocation({ kind: "reset" });
72185
72183
  });
72186
- authCommand.command("logout").summary("Delete local credentials and revoke token").description("Revoke token and delete local credentials").action(() => {
72187
- setInvocation({ kind: "auth_logout" });
72188
- });
72189
- 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) => {
72184
+ program.command("catalog").summary("Discover servers or inspect Codemode tools").description("Discover servers or inspect Codemode tools on a server").helpGroup("Discovery Commands:").argument("[serverId]", "Server id").argument("[toolName]", "Codemode tool name").addOption(new Option("--org <orgSlug>", "Organization slug").hideHelp()).addOption(new Option("--cursor <cursor>", "Pagination cursor for server discovery")).addOption(new Option("--limit <limit>", "Maximum servers to return").argParser(parseCatalogLimitOption)).action((serverId, toolName, options) => {
72185
+ if (serverId !== void 0 && (options.cursor !== void 0 || options.limit !== void 0)) throw new InvalidArgumentError("--cursor and --limit are only supported for `ogment catalog`.");
72190
72186
  setInvocation({
72191
- example: options.example === true,
72192
72187
  kind: "catalog",
72193
72188
  ...options.cursor === void 0 ? {} : { cursor: options.cursor },
72194
72189
  ...options.limit === void 0 ? {} : { limit: options.limit },
72190
+ ...options.org === void 0 ? {} : { orgSlug: options.org },
72195
72191
  ...serverId === void 0 ? {} : { serverId },
72196
72192
  ...toolName === void 0 ? {} : { toolName }
72197
72193
  });
72198
72194
  });
72199
- 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) => {
72195
+ program.command("search").summary("Search tools on a server via Codemode").description("Run Codemode search JavaScript against a server tool catalog").helpGroup("Execution Commands:").argument("<serverId>", "Server id").addOption(new Option("--org <orgSlug>", "Organization slug").hideHelp()).requiredOption("--code <value>", "JavaScript source: inline code, @path, or - for stdin").action((serverId, options) => {
72200
72196
  setInvocation({
72197
+ code: options.code,
72198
+ kind: "search",
72199
+ ...options.org === void 0 ? {} : { orgSlug: options.org },
72200
+ serverId
72201
+ });
72202
+ });
72203
+ program.command("execute").summary("Execute Codemode JavaScript on a server").description("Run Codemode execute JavaScript with optional JSON input").helpGroup("Execution Commands:").argument("<serverId>", "Server id").addOption(new Option("--org <orgSlug>", "Organization slug").hideHelp()).requiredOption("--code <value>", "JavaScript source: inline code, @path, or - for stdin").option("--input <value>", "Input payload: inline JSON object, @path, or - for stdin").action((serverId, options) => {
72204
+ setInvocation({
72205
+ code: options.code,
72206
+ kind: "execute",
72201
72207
  input: options.input,
72202
- kind: "invoke",
72203
72208
  ...options.org === void 0 ? {} : { orgSlug: options.org },
72204
- serverId,
72205
- toolName
72209
+ serverId
72206
72210
  });
72207
72211
  });
72208
- program.command("status").summary("Show runtime diagnostics").description("Show runtime configuration and connectivity diagnostics").helpGroup("Diagnostics Commands:").action(() => {
72212
+ program.command("status").summary("Show runtime diagnostics and auth state").description("Show runtime configuration, connectivity, and auth diagnostics").helpGroup("Diagnostics Commands:").action(() => {
72209
72213
  setInvocation({ kind: "status" });
72210
72214
  });
72211
72215
  program.action(() => {
@@ -72232,9 +72236,13 @@ const RUNTIME_ERROR_COMMAND_PATH = "ogment <runtime_error>";
72232
72236
  const PARSE_ERROR_COMMAND_PATH = "ogment <parse_error>";
72233
72237
  const CLI_PACKAGE_NAME = "@ogment-ai/cli";
72234
72238
  const PARSE_ERROR_SCOPE_COMMAND_PATHS = {
72235
- auth: "ogment auth <parse_error>",
72239
+ login: "ogment login <parse_error>",
72240
+ logout: "ogment logout <parse_error>",
72241
+ reset: "ogment reset <parse_error>",
72236
72242
  catalog: "ogment catalog <parse_error>",
72237
- invoke: "ogment invoke <parse_error>"
72243
+ execute: "ogment execute <parse_error>",
72244
+ search: "ogment search <parse_error>",
72245
+ status: "ogment status <parse_error>"
72238
72246
  };
72239
72247
  const isParseErrorTelemetryScope = (value) => {
72240
72248
  return value in PARSE_ERROR_SCOPE_COMMAND_PATHS;
@@ -72245,56 +72253,63 @@ const parseErrorCommandPath = (scope) => {
72245
72253
  if (rootScope === void 0 || !isParseErrorTelemetryScope(rootScope)) return PARSE_ERROR_COMMAND_PATH;
72246
72254
  return PARSE_ERROR_SCOPE_COMMAND_PATHS[rootScope];
72247
72255
  };
72248
- const telemetryInputModeFromInvoke = (input) => {
72256
+ const telemetryInputModeFromExecute = (input) => {
72249
72257
  if (input === void 0) return "none";
72250
72258
  if (input === "-") return "stdin";
72251
72259
  if (input.startsWith("@")) return "file";
72252
72260
  return "inline_json";
72253
72261
  };
72254
72262
  const telemetryContextResolvers = {
72255
- auth_login: (_) => {
72263
+ login: (_) => {
72256
72264
  return {
72257
- commandKind: "auth_login",
72258
- commandPath: "ogment auth login",
72265
+ commandKind: "login",
72266
+ commandPath: "ogment login",
72259
72267
  inputMode: null
72260
72268
  };
72261
72269
  },
72262
- auth_logout: (_) => {
72270
+ logout: (_) => {
72263
72271
  return {
72264
- commandKind: "auth_logout",
72265
- commandPath: "ogment auth logout",
72272
+ commandKind: "logout",
72273
+ commandPath: "ogment logout",
72266
72274
  inputMode: null
72267
72275
  };
72268
72276
  },
72269
- auth_status: (_) => {
72277
+ reset: (_) => {
72270
72278
  return {
72271
- commandKind: "auth_status",
72272
- commandPath: "ogment auth status",
72279
+ commandKind: "reset",
72280
+ commandPath: "ogment reset",
72273
72281
  inputMode: null
72274
72282
  };
72275
72283
  },
72276
72284
  catalog: (invocation) => {
72277
- if (invocation.serverId === void 0) return {
72278
- commandKind: "catalog_summary",
72279
- commandPath: "ogment catalog",
72285
+ if (invocation.toolName !== void 0 && invocation.serverId !== void 0) return {
72286
+ commandKind: "catalog_tool_detail",
72287
+ commandPath: "ogment catalog <server-id> <tool-name>",
72280
72288
  inputMode: null
72281
72289
  };
72282
- if (invocation.toolName === void 0) return {
72283
- commandKind: "catalog_tools",
72290
+ if (invocation.serverId !== void 0) return {
72291
+ commandKind: "catalog_detail",
72284
72292
  commandPath: "ogment catalog <server-id>",
72285
72293
  inputMode: null
72286
72294
  };
72287
72295
  return {
72288
- commandKind: "catalog_tool",
72289
- commandPath: "ogment catalog <server-id> <tool-name>",
72296
+ commandKind: "catalog_summary",
72297
+ commandPath: "ogment catalog",
72290
72298
  inputMode: null
72291
72299
  };
72292
72300
  },
72293
- invoke: (invocation) => {
72301
+ execute: (invocation) => {
72294
72302
  return {
72295
- commandKind: "invoke",
72296
- commandPath: "ogment invoke <server-id> <tool-name>",
72297
- inputMode: telemetryInputModeFromInvoke(invocation.input)
72303
+ commandKind: "execute",
72304
+ commandPath: "ogment execute <server-id>",
72305
+ inputMode: telemetryInputModeFromExecute(invocation.input)
72306
+ };
72307
+ },
72308
+ search: (_) => {
72309
+ return {
72310
+ commandKind: "search",
72311
+ commandPath: "ogment search <server-id>",
72312
+ inputMode: null
72298
72313
  };
72299
72314
  },
72300
72315
  root: (_) => {
@@ -72314,12 +72329,13 @@ const telemetryContextResolvers = {
72314
72329
  };
72315
72330
  const telemetryContextFromInvocation = (invocation) => {
72316
72331
  switch (invocation.kind) {
72317
- case "auth_login": return telemetryContextResolvers.auth_login(invocation);
72318
- case "auth_logout": return telemetryContextResolvers.auth_logout(invocation);
72319
- case "auth_status": return telemetryContextResolvers.auth_status(invocation);
72332
+ case "login": return telemetryContextResolvers.login(invocation);
72333
+ case "logout": return telemetryContextResolvers.logout(invocation);
72334
+ case "reset": return telemetryContextResolvers.reset(invocation);
72320
72335
  case "catalog": return telemetryContextResolvers.catalog(invocation);
72321
- case "invoke": return telemetryContextResolvers.invoke(invocation);
72336
+ case "execute": return telemetryContextResolvers.execute(invocation);
72322
72337
  case "root": return telemetryContextResolvers.root(invocation);
72338
+ case "search": return telemetryContextResolvers.search(invocation);
72323
72339
  case "status": return telemetryContextResolvers.status(invocation);
72324
72340
  }
72325
72341
  };
@@ -72353,9 +72369,7 @@ const emitRuntimeErrorTelemetry = async (output, input) => {
72353
72369
  const telemetry = createTelemetryService({
72354
72370
  authStateStore: createFileCredentialsStore({
72355
72371
  configDir: telemetryConfig.configDir,
72356
- credentialsPath: telemetryConfig.credentialsPath,
72357
- legacyCredentialsPath: telemetryConfig.legacyCredentialsPath,
72358
- telemetryPath: telemetryConfig.telemetryPath
72372
+ credentialsPath: telemetryConfig.credentialsPath
72359
72373
  }),
72360
72374
  baseUrl: telemetryConfig.baseUrl,
72361
72375
  cliVersion: telemetryConfig.version,
@@ -72394,21 +72408,19 @@ const commandContextFromInvocation = (invocation, apiKeyOverride) => {
72394
72408
  const withBase = (commandName, invocationKind, subcommand = void 0) => {
72395
72409
  return {
72396
72410
  commandName,
72397
- hasApiKeyOverride: invocation.kind === "auth_login" ? hasApiKeyOverride(invocation.apiKey) : hasApiKeyOverride(apiKeyOverride),
72411
+ hasApiKeyOverride: hasApiKeyOverride(apiKeyOverride),
72398
72412
  invocationKind,
72399
72413
  subcommand
72400
72414
  };
72401
72415
  };
72402
72416
  switch (invocation.kind) {
72403
- case "auth_login": return withBase("auth", "auth_login", "login");
72404
- case "auth_logout": return withBase("auth", "auth_logout", "logout");
72405
- case "auth_status": return withBase("auth", "auth_status", "status");
72406
- case "catalog":
72407
- if (invocation.toolName !== void 0) return withBase("catalog", "catalog", "tool");
72408
- if (invocation.serverId !== void 0) return withBase("catalog", "catalog", "server");
72409
- return withBase("catalog", "catalog", "summary");
72410
- case "invoke": return withBase("invoke", "invoke");
72417
+ case "login": return withBase("login", "login");
72418
+ case "logout": return withBase("logout", "logout");
72419
+ case "reset": return withBase("reset", "reset");
72420
+ case "catalog": return withBase("catalog", "catalog", "summary");
72421
+ case "execute": return withBase("execute", "execute");
72411
72422
  case "root": return withBase("ogment", "root");
72423
+ case "search": return withBase("search", "search");
72412
72424
  case "status": return withBase("status", "status");
72413
72425
  default: return assertNever(invocation);
72414
72426
  }
@@ -72560,4 +72572,4 @@ if (shouldExecuteCli(import.meta.url, process.argv[1])) await executeCli();
72560
72572
 
72561
72573
  //#endregion
72562
72574
  export { executeCli, runCli, shouldExecuteCli };
72563
- //# debugId=75a9f438-9e34-4abd-88d2-6cd8a68d9950
72575
+ //# debugId=38b5ce38-06fe-4ef8-9580-b9d5110652a6