sim 2.1.8-preview.97.1 → 2.1.8-preview.98.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.
Files changed (3) hide show
  1. package/README.md +16 -5
  2. package/dist/index.js +20 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -33,16 +33,27 @@ Sign in to the default profile:
33
33
  sim login
34
34
  ```
35
35
 
36
- The CLI opens Sim in your browser, asks you to approve the requested access,
36
+ With no `--method`, the CLI prefers OAuth when the server offers it and a local
37
+ browser callback is possible. It selects API-key pairing for remote terminals
38
+ or servers without OAuth. Use `sim login --method oauth` to require OAuth;
39
+ if the server does not offer it, login fails without creating an API key.
40
+
41
+ OAuth login opens Sim in your browser, asks you to approve the requested access,
37
42
  and receives the one-time authorization code on a loopback callback. It stores
38
43
  a short-lived OAuth login that renews automatically and can be revoked under
39
44
  **Settings → General → Authorized apps**. Choose a default workspace afterward with
40
45
  `sim configure --set-workspace <id>`.
41
46
 
42
- Use `sim login --no-browser` to print the OAuth URL without opening it. The
43
- browser must still be able to reach the CLI's loopback callback. Over SSH or in
44
- a container without port forwarding, use `sim login --browserless`; that
45
- pairing-code fallback creates a permanent personal API key instead.
47
+ Use `--no-browser` with either method to print the approval URL without opening
48
+ it. OAuth still needs the browser to reach the CLI's loopback callback. Over SSH
49
+ or in a container without port forwarding, use
50
+ `sim login --method api-key --no-browser` to approve from another device and
51
+ create a permanent personal API key. `--method api-key` creates a new key;
52
+ set `SIM_API_KEY` to supply an existing one.
53
+
54
+ Pairing requires a server that supports `platform` API keys. Upgrade older
55
+ deployments that only issue `copilot` keys before login; they are not compatible
56
+ with the platform CLI. OAuth discovery does not check pairing compatibility.
46
57
 
47
58
  Check the active profile and verify that its endpoint, credential, and workspace
48
59
  work together:
package/dist/index.js CHANGED
@@ -8140,12 +8140,12 @@ function createAuthRequest() {
8140
8140
  pairing: pairingCode()
8141
8141
  };
8142
8142
  }
8143
- function buildApprovalUrl(endpoint, auth, scope, workspaceId) {
8143
+ function buildApprovalUrl(endpoint, auth, workspaceId) {
8144
8144
  return buildUrl(endpoint, APPROVAL_PATH, {
8145
8145
  request: auth.request,
8146
8146
  challenge: auth.challenge,
8147
8147
  pairing: auth.pairing,
8148
- scope,
8148
+ scope: "platform",
8149
8149
  workspace: workspaceId
8150
8150
  });
8151
8151
  }
@@ -8451,7 +8451,7 @@ function listenForCallback(server, expectedState, completionUrl, signal, timeout
8451
8451
  const onAbort = () => finish({ ok: false, error: new SimApiError("Login cancelled.", 0) });
8452
8452
  const timer = setTimeout(() => finish({
8453
8453
  ok: false,
8454
- error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --browserless if this terminal's browser cannot reach it.`, 0)
8454
+ error: new SimApiError(`Timed out after ${Math.round(timeoutMs / 60000)} minutes waiting for the browser. Run sim login again, or use --method api-key if this terminal's browser cannot reach it.`, 0)
8455
8455
  }), timeoutMs);
8456
8456
  signal?.addEventListener("abort", onAbort, { once: true });
8457
8457
  server.on("request", (request, response) => {
@@ -13944,12 +13944,12 @@ function addProfileCommand() {
13944
13944
  console.log(source_default.dim(` Try: sim --profile ${safeOneLine(profileName)} whoami`));
13945
13945
  });
13946
13946
  }
13947
- async function chooseLoginFlow(profile, options, scope) {
13947
+ async function chooseLoginFlow(profile, options) {
13948
13948
  requireSecureEndpoint(profile.endpoint);
13949
- if (options.browserless || scope === "copilot")
13949
+ if (options.method === "api-key")
13950
13950
  return "handoff";
13951
- if (isLikelyRemoteSession() && options.callbackPort === undefined) {
13952
- console.log(source_default.dim(`This looks like a remote session, so the browser on this machine cannot finish an OAuth login; using the pairing code instead. Forward a port and pass --callback-port <port> to sign in through the browser anyway.
13951
+ if (options.method === undefined && isLikelyRemoteSession() && options.callbackPort === undefined) {
13952
+ console.log(source_default.dim(`This looks like a remote session; using the pairing code to create a personal API key. To use OAuth, forward a port and pass --method oauth --callback-port <port>.
13953
13953
  `));
13954
13954
  return "handoff";
13955
13955
  }
@@ -13958,7 +13958,10 @@ async function chooseLoginFlow(profile, options, scope) {
13958
13958
  throw new SimApiError(`Could not reach ${profile.endpoint}. Check the endpoint.`, 0);
13959
13959
  }
13960
13960
  if (status === "unavailable") {
13961
- console.log(source_default.dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code instead.
13961
+ if (options.method === "oauth") {
13962
+ throw new SimApiError(`${profile.endpoint} does not offer OAuth sign-in. Enable OAuth on the server or explicitly choose sim login --method api-key.`, 0);
13963
+ }
13964
+ console.log(source_default.dim(`${profile.endpoint} does not offer OAuth sign-in; using the pairing code to create a personal API key.
13962
13965
  `));
13963
13966
  return "handoff";
13964
13967
  }
@@ -14036,16 +14039,12 @@ Waiting for you to approve in the browser…`));
14036
14039
  }
14037
14040
  }
14038
14041
  function loginCommand() {
14039
- return new Command("login").description("Sign in through the browser and store the login for the profile").option("--scope <scope>", 'Key space for the pairing-code handoff; only "copilot" changes anything, and it forces that flow', "platform").option("--no-browser", "Print the URL instead of opening a browser").option("--browserless", "Use the pairing-code handoff for a terminal whose browser cannot reach it (SSH, containers)").option("--read-only", "Ask only for permission to read, never to change anything").option("--callback-port <port>", "Pin the local port the browser returns to").option("-y, --yes", "Overwrite an existing API-key profile without prompting").action(async (options, command) => {
14042
+ return new Command("login").description("Sign in through the browser and store the login for the profile").addOption(new Option("--method <method>", "Credential to obtain: oauth requires OAuth support; api-key creates a permanent key through pairing (auto-selects when omitted)").choices(["oauth", "api-key"])).option("--no-browser", "Print the approval URL without opening it (either login method)").option("--read-only", "Ask only for permission to read, never to change anything").option("--callback-port <port>", "Pin the local port the browser returns to").option("-y, --yes", "Overwrite an existing API-key profile without prompting").action(async (options, command) => {
14040
14043
  const profile = profileFrom(command, { allowUnknownProfile: true });
14041
14044
  const authProfile = resolveAuthenticationProfileName(profile.name);
14042
14045
  if (authProfile !== profile.name) {
14043
14046
  throw new SimApiError(`Profile "${redact(profile.name)}" shares authentication with "${redact(authProfile)}". Run: sim login --profile ${redact(authProfile)}`, 0);
14044
14047
  }
14045
- if (options.scope !== "platform" && options.scope !== "copilot") {
14046
- throw new SimApiError(`Unknown scope "${options.scope}". Use platform or copilot.`, 0);
14047
- }
14048
- const scope = options.scope;
14049
14048
  const snapshot = readLoginProfileSnapshot(profile.name);
14050
14049
  const storedCredential = snapshot.credential;
14051
14050
  if (storedCredential?.kind === "oauth") {
@@ -14059,13 +14058,13 @@ function loginCommand() {
14059
14058
  }
14060
14059
  }
14061
14060
  const callbackPort = parseCallbackPort(options.callbackPort);
14062
- const loginFlow = await chooseLoginFlow(profile, options, scope);
14061
+ const loginFlow = await chooseLoginFlow(profile, options);
14063
14062
  if (loginFlow === "handoff") {
14064
14063
  if (options.readOnly) {
14065
- throw new SimApiError("The pairing-code handoff cannot issue a read-only login; it mints a full API key. Drop --read-only, or sign in through the browser.", 0);
14064
+ throw new SimApiError("API-key login cannot issue a read-only login. Use --method oauth, or drop --read-only.", 0);
14066
14065
  }
14067
14066
  if (callbackPort !== undefined) {
14068
- throw new SimApiError("The pairing-code handoff has no local callback, so --callback-port does not apply. Drop it, or sign in through the browser.", 0);
14067
+ throw new SimApiError("API-key login has no local callback, so --callback-port does not apply. Use --method oauth, or drop --callback-port.", 0);
14069
14068
  }
14070
14069
  }
14071
14070
  await withProfileLoginLease(profile.name, async () => {
@@ -14074,13 +14073,13 @@ function loginCommand() {
14074
14073
  await loginWithOAuth(profile, options, callbackPort, snapshot);
14075
14074
  return;
14076
14075
  }
14077
- await loginWithHandoff(profile, options, scope, snapshot);
14076
+ await loginWithHandoff(profile, options, snapshot);
14078
14077
  });
14079
14078
  });
14080
14079
  }
14081
- async function loginWithHandoff(profile, options, scope, expected) {
14080
+ async function loginWithHandoff(profile, options, expected) {
14082
14081
  const auth = createAuthRequest();
14083
- const url = buildApprovalUrl(profile.endpoint, auth, scope, profile.workspaceId ?? undefined);
14082
+ const url = buildApprovalUrl(profile.endpoint, auth, profile.workspaceId ?? undefined);
14084
14083
  console.log(`Signing in to ${source_default.bold(profile.endpoint)} as profile ${source_default.bold(safeOneLine(profile.name))}`);
14085
14084
  console.log(`
14086
14085
  Pairing code: ${source_default.bold(auth.pairing)}`);
@@ -14093,8 +14092,8 @@ Pairing code: ${source_default.bold(auth.pairing)}`);
14093
14092
  Waiting for approval…`));
14094
14093
  const key = await pollForKey(profile.endpoint, auth);
14095
14094
  try {
14096
- if (key.scope !== scope) {
14097
- throw new SimApiError(`Server issued a ${key.scope} key but this profile needs a ${scope} key. Update the Sim deployment, or run: sim login --scope ${key.scope}`, 0);
14095
+ if (key.scope !== "platform") {
14096
+ throw new SimApiError(`Server issued a ${key.scope} key, but the CLI requires a platform API key. Update the Sim deployment and try again.`, 0);
14098
14097
  }
14099
14098
  const settings = {
14100
14099
  endpoint: profile.endpoint,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sim",
3
- "version": "2.1.8-preview.97.1",
3
+ "version": "2.1.8-preview.98.1",
4
4
  "description": "Sim CLI - talk to the Sim API from your terminal",
5
5
  "type": "module",
6
6
  "bin": {