@indexnetwork/cli 0.13.3-rc.62.1 → 0.14.0-rc.63.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 +2 -4
  2. package/dist/index.js +64 -149
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -40,8 +40,7 @@ Words you will see elsewhere in this doc: **network** = a community you are in;
40
40
  Authenticate with Index Network. Opens a browser window that uses your existing session (or a fresh OAuth flow) to call the session-only, fixed-shape CLI credential endpoint, which mints a 90-day API key while keeping CLI requests on the non-web compatibility surface.
41
41
 
42
42
  ```bash
43
- index login # Browser-based auth (default)
44
- index login --token <jwt> # Legacy manual session token (skip browser)
43
+ index login # Browser-based auth
45
44
  index login --api-url <url> # Custom server URL
46
45
  ```
47
46
 
@@ -49,7 +48,7 @@ Credentials are stored in `~/.index/credentials.json`. Current browser login exp
49
48
 
50
49
  **Rolling deploy order:** v2 clients require the v2 web bridge and intentionally reject callbacks from older web deployments that cannot return the bound state. On dev, this CLI is an RC: wait for both the API and web deployments to succeed before testing v2 login. Do not relax state validation to make a new CLI work against old web.
51
50
 
52
- **Temporary compatibility:** the already-released v1 CLI can still recover with `index login`; the web bridge asks the custom session-only endpoint for a separately tagged 90-day v1 API key and returns it under the old `session_token` callback field, and the API accepts only that tag as a Bearer fallback. An upgraded v2 CLI transparently exchanges a still-valid stored browser JWT through the same endpoint for a tagged v2 key before making any compatibility request; an old binary must re-login because its ordinary session JWT must remain on the web/Signal surface. Remove the v1 bridge only after released clients have aged out.
51
+ The v1 login contract (`session_token` callback, Bearer API-key fallback, `--token` manual flow) is removed. Released v1 binaries and legacy `credentials.json` files without a key ID are treated as signed out; upgrade and run `index login`.
53
52
 
54
53
  ### `index logout`
55
54
 
@@ -205,7 +204,6 @@ index opportunity reject <id>
205
204
  | -------------------- | ----- | --------------------------------------------------------------- |
206
205
  | `--api-url <url>` | | Override API server (default: `https://protocol.index.network`) |
207
206
  | `--app-url <url>` | | Override app URL for login (default: `https://index.network`) |
208
- | `--token <token>` | `-t` | Provide bearer token directly |
209
207
  | `--session <id>` | `-s` | Resume a specific chat session |
210
208
  | `--archived` | | Include archived signals (intent list) |
211
209
  | `--status <status>` | | Filter opportunities by status |
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import { spawn } from "node:child_process";
19
19
  // package.json
20
20
  var package_default = {
21
21
  name: "@indexnetwork/cli",
22
- version: "0.13.3",
22
+ version: "0.14.0",
23
23
  description: "Command-line interface for Index Network",
24
24
  license: "MIT",
25
25
  type: "module",
@@ -39,10 +39,10 @@ var package_default = {
39
39
  "publish:all": "bun scripts/publish.ts"
40
40
  },
41
41
  optionalDependencies: {
42
- "@indexnetwork/cli-linux-x64": "0.13.3",
43
- "@indexnetwork/cli-linux-arm64": "0.13.3",
44
- "@indexnetwork/cli-darwin-x64": "0.13.3",
45
- "@indexnetwork/cli-darwin-arm64": "0.13.3"
42
+ "@indexnetwork/cli-linux-x64": "0.14.0",
43
+ "@indexnetwork/cli-linux-arm64": "0.14.0",
44
+ "@indexnetwork/cli-darwin-x64": "0.14.0",
45
+ "@indexnetwork/cli-darwin-arm64": "0.14.0"
46
46
  },
47
47
  devDependencies: {
48
48
  "@types/bun": "1.3.14"
@@ -66,13 +66,11 @@ function parseArgs(args) {
66
66
  let commandIndex = -1;
67
67
  for (let j = 0;j < args.length; j++) {
68
68
  const a = args[j];
69
- if (a === "--api-url" || a === "--app-url" || a === "--token" || a === "-t") {
69
+ if (a === "--api-url" || a === "--app-url") {
70
70
  if (a === "--api-url")
71
71
  result.apiUrl = args[j + 1];
72
- else if (a === "--app-url")
73
- result.appUrl = args[j + 1];
74
72
  else
75
- result.token = args[j + 1];
73
+ result.appUrl = args[j + 1];
76
74
  j++;
77
75
  } else if (a === "--help" || a === "-h") {
78
76
  result.command = "help";
@@ -111,9 +109,6 @@ function parseArgs(args) {
111
109
  } else if (arg === "--app-url") {
112
110
  result.appUrl = args[i + 1];
113
111
  i += 2;
114
- } else if (arg === "--token" || arg === "-t") {
115
- result.token = args[i + 1];
116
- i += 2;
117
112
  } else if (arg === "--archived") {
118
113
  result.archived = true;
119
114
  i++;
@@ -280,6 +275,48 @@ function parseIntentArgs(positionals, result) {
280
275
  }
281
276
  }
282
277
 
278
+ // src/auth.store.ts
279
+ import { join } from "node:path";
280
+ import { homedir } from "node:os";
281
+ import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
282
+ var CREDENTIALS_FILE = "credentials.json";
283
+
284
+ class CredentialStore {
285
+ dir;
286
+ filePath;
287
+ constructor(dir) {
288
+ this.dir = dir ?? join(homedir(), ".index");
289
+ this.filePath = join(this.dir, CREDENTIALS_FILE);
290
+ }
291
+ async load() {
292
+ try {
293
+ const raw = await readFile(this.filePath, "utf-8");
294
+ const parsed = JSON.parse(raw);
295
+ if (parsed.token && parsed.apiUrl && parsed.authKind === "api_key" && parsed.keyId) {
296
+ return parsed;
297
+ }
298
+ return null;
299
+ } catch {
300
+ return null;
301
+ }
302
+ }
303
+ async save(credentials) {
304
+ await mkdir(this.dir, { recursive: true });
305
+ await writeFile(this.filePath, JSON.stringify(credentials, null, 2), {
306
+ mode: 384
307
+ });
308
+ }
309
+ async clear() {
310
+ try {
311
+ await unlink(this.filePath);
312
+ } catch (error) {
313
+ if (error.code === "ENOENT")
314
+ return;
315
+ throw error;
316
+ }
317
+ }
318
+ }
319
+
283
320
  // src/api.client.ts
284
321
  class ApiError extends Error {
285
322
  status;
@@ -301,28 +338,18 @@ function isEarlyAccessNetworkCreationError(error) {
301
338
  class ApiClient {
302
339
  baseUrl;
303
340
  token;
304
- authKind;
305
- constructor(baseUrl, token, authKind = "session") {
341
+ constructor(baseUrl, token) {
306
342
  this.baseUrl = baseUrl.replace(/\/$/, "");
307
343
  this.token = token;
308
- this.authKind = authKind;
309
344
  }
310
345
  authHeaders() {
311
- return this.authKind === "api_key" ? { "x-api-key": this.token } : { Authorization: `Bearer ${this.token}` };
346
+ return { "x-api-key": this.token };
312
347
  }
313
348
  async listSessions() {
314
349
  const res = await this.get("/api/chat/sessions");
315
350
  const body = await res.json();
316
351
  return body.sessions;
317
352
  }
318
- async mintCliApiKey(protocolVersion = 2) {
319
- const res = await this.post("/api/auth/cli-credential", { protocolVersion });
320
- const body = await res.json();
321
- if (typeof body.key !== "string" || !body.key || typeof body.id !== "string" || !body.id || typeof body.expiresAt !== "string" || !body.expiresAt) {
322
- throw new Error("CLI credential response did not include a key, key ID, and expiry");
323
- }
324
- return { key: body.key, keyId: body.id };
325
- }
326
353
  async revokeApiKey(keyId, targetKey = this.token) {
327
354
  const res = await this.post("/api/auth/cli-credential/revoke", { keyId, targetKey });
328
355
  const body = await res.json();
@@ -603,23 +630,21 @@ class ApiClient {
603
630
  }
604
631
  }
605
632
 
633
+ // src/login.command.ts
634
+ import { randomBytes } from "node:crypto";
635
+ import { createServer } from "node:http";
636
+
606
637
  // src/auth.lifecycle.ts
607
638
  async function storeReplacementCredentials(store, previous, replacement, options = {}) {
608
639
  await store.save(replacement);
609
- if (previous?.authKind !== "api_key")
640
+ if (!previous)
610
641
  return {};
611
- if (!previous.keyId) {
612
- return {
613
- warning: "Login succeeded, but the previous CLI API key has no exact revocation ID and may remain active. It should be removed in Index web settings."
614
- };
615
- }
616
- if (replacement.authKind === "api_key" && replacement.keyId === previous.keyId) {
642
+ if (replacement.keyId === previous.keyId) {
617
643
  return {};
618
644
  }
619
- const authKind = replacement.authKind ?? "session";
620
- const createClient = options.clientFactory ?? ((apiUrl, token, kind) => new ApiClient(apiUrl, token, kind));
645
+ const createClient = options.clientFactory ?? ((apiUrl, token) => new ApiClient(apiUrl, token));
621
646
  try {
622
- await createClient(replacement.apiUrl, replacement.token, authKind).revokeApiKey(previous.keyId, previous.token);
647
+ await createClient(replacement.apiUrl, replacement.token).revokeApiKey(previous.keyId, previous.token);
623
648
  return {};
624
649
  } catch (error) {
625
650
  const detail = error instanceof Error ? ` ${error.message}` : "";
@@ -629,51 +654,7 @@ async function storeReplacementCredentials(store, previous, replacement, options
629
654
  }
630
655
  }
631
656
 
632
- // src/auth.store.ts
633
- import { join } from "node:path";
634
- import { homedir } from "node:os";
635
- import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
636
- var CREDENTIALS_FILE = "credentials.json";
637
-
638
- class CredentialStore {
639
- dir;
640
- filePath;
641
- constructor(dir) {
642
- this.dir = dir ?? join(homedir(), ".index");
643
- this.filePath = join(this.dir, CREDENTIALS_FILE);
644
- }
645
- async load() {
646
- try {
647
- const raw = await readFile(this.filePath, "utf-8");
648
- const parsed = JSON.parse(raw);
649
- if (parsed.token && parsed.apiUrl) {
650
- return parsed;
651
- }
652
- return null;
653
- } catch {
654
- return null;
655
- }
656
- }
657
- async save(credentials) {
658
- await mkdir(this.dir, { recursive: true });
659
- await writeFile(this.filePath, JSON.stringify(credentials, null, 2), {
660
- mode: 384
661
- });
662
- }
663
- async clear() {
664
- try {
665
- await unlink(this.filePath);
666
- } catch (error) {
667
- if (error.code === "ENOENT")
668
- return;
669
- throw error;
670
- }
671
- }
672
- }
673
-
674
657
  // src/login.command.ts
675
- import { randomBytes } from "node:crypto";
676
- import { createServer } from "node:http";
677
658
  function closeServer(server) {
678
659
  return new Promise((resolve) => {
679
660
  let resolved = false;
@@ -728,7 +709,6 @@ async function handleLogin(apiUrl, appUrl, store, options = {}) {
728
709
  stateConsumed = true;
729
710
  const apiKey = url.searchParams.get("api_key");
730
711
  const keyId = url.searchParams.get("key_id");
731
- const sessionToken = url.searchParams.get("session_token");
732
712
  if (apiKey && keyId) {
733
713
  try {
734
714
  const cleanup = await storeReplacementCredentials(store, previousCredentials, {
@@ -748,24 +728,6 @@ async function handleLogin(apiUrl, appUrl, store, options = {}) {
748
728
  res.end(callbackHtml("CLI authorized", "You can close this window and return to the terminal.", true));
749
729
  return;
750
730
  }
751
- if (!apiKey && sessionToken) {
752
- try {
753
- const cleanup = await storeReplacementCredentials(store, previousCredentials, {
754
- token: sessionToken,
755
- apiUrl: baseUrl,
756
- authKind: "session"
757
- }, { clientFactory: options.credentialClientFactory });
758
- resolveCallback({ success: true, ...cleanup });
759
- } catch {
760
- resolveCallback({ success: false, error: "Failed to save CLI credentials." });
761
- res.writeHead(500, { "Content-Type": "text/html" });
762
- res.end(callbackHtml("Authorization failed", "CLI credentials could not be saved. Return to the terminal and try again."));
763
- return;
764
- }
765
- res.writeHead(200, { "Content-Type": "text/html" });
766
- res.end(callbackHtml("CLI authorized", "You can close this window and return to the terminal.", true));
767
- return;
768
- }
769
731
  resolveCallback({
770
732
  success: false,
771
733
  error: apiKey ? "CLI API-key callback did not include its key ID." : "No CLI credential received in callback."
@@ -887,17 +849,7 @@ async function handleLogout(store, options = {}) {
887
849
  if (!credentials) {
888
850
  return { success: true, message: "Already logged out." };
889
851
  }
890
- if (credentials.authKind !== "api_key") {
891
- await store.clear();
892
- return { success: true, message: "Logged out. Session cleared." };
893
- }
894
- if (!credentials.keyId) {
895
- return {
896
- success: false,
897
- warning: "Stored API-key credentials do not include a revocation ID and were retained. Remove the old key in Index web settings first, then delete the local credentials and sign in again."
898
- };
899
- }
900
- const createClient = options.clientFactory ?? ((apiUrl, token) => new ApiClient(apiUrl, token, "api_key"));
852
+ const createClient = options.clientFactory ?? ((apiUrl, token) => new ApiClient(apiUrl, token));
901
853
  try {
902
854
  await createClient(credentials.apiUrl, credentials.token).revokeApiKey(credentials.keyId, credentials.token);
903
855
  } catch (error) {
@@ -3113,7 +3065,6 @@ function helpRowCont(leftW, right) {
3113
3065
  function renderHelp() {
3114
3066
  const gsLefts = [
3115
3067
  "index login",
3116
- "index login --token <token>",
3117
3068
  "index logout",
3118
3069
  'index intent create "..."',
3119
3070
  "index negotiation list",
@@ -3149,7 +3100,6 @@ function renderHelp() {
3149
3100
  const optLefts = [
3150
3101
  "--api-url <url>",
3151
3102
  "--app-url <url>",
3152
- "--token <token>",
3153
3103
  "--session <id>",
3154
3104
  "--archived",
3155
3105
  "--status <status>",
@@ -3174,7 +3124,6 @@ function renderHelp() {
3174
3124
  `);
3175
3125
  panel("getting started", [
3176
3126
  helpRowCmd(gsLW, "index login", "authenticate via browser"),
3177
- helpRowCmd(gsLW, "index login --token <token>", "authenticate with a bearer token"),
3178
3127
  helpRowCmd(gsLW, "index logout", "clear stored session"),
3179
3128
  helpRowCmd(gsLW, 'index intent create "..."', "describe what you're looking for"),
3180
3129
  helpRowCmd(gsLW, "index negotiation list", "see agent debates in progress"),
@@ -3212,7 +3161,6 @@ function renderHelp() {
3212
3161
  panel("options", [
3213
3162
  helpRowDim(optLW, "--api-url <url>", "override API server URL"),
3214
3163
  helpRowDim(optLW, "--app-url <url>", "override app URL for login"),
3215
- helpRowDim(optLW, "--token <token>", "provide bearer token directly"),
3216
3164
  helpRowDim(optLW, "--session <id>", "resume a chat session"),
3217
3165
  helpRowDim(optLW, "--archived", "include archived signals"),
3218
3166
  helpRowDim(optLW, "--status <status>", "filter opportunities by status"),
@@ -3239,45 +3187,12 @@ async function requireAuth(apiUrlOverride) {
3239
3187
  process.exit(1);
3240
3188
  }
3241
3189
  const apiUrl = apiUrlOverride ?? creds.apiUrl;
3242
- if (creds.authKind !== "api_key") {
3243
- try {
3244
- const sessionClient = new ApiClient(apiUrl, creds.token, "session");
3245
- const { key, keyId } = await sessionClient.mintCliApiKey();
3246
- const migrated = { token: key, apiUrl, authKind: "api_key", keyId };
3247
- await store.save(migrated);
3248
- return new ApiClient(apiUrl, migrated.token, migrated.authKind);
3249
- } catch {
3250
- error("Stored CLI credentials need to be refreshed. Run `index login` again.", 1);
3251
- process.exit(1);
3252
- }
3253
- }
3254
- return new ApiClient(apiUrl, creds.token, creds.authKind);
3190
+ return new ApiClient(apiUrl, creds.token);
3255
3191
  }
3256
- async function runLogin(apiUrlOverride, appUrlOverride, manualToken) {
3192
+ async function runLogin(apiUrlOverride, appUrlOverride) {
3257
3193
  const store = new CredentialStore;
3258
3194
  const apiUrl = apiUrlOverride ?? DEFAULT_API_URL;
3259
3195
  const appUrl = appUrlOverride ?? DEFAULT_APP_URL;
3260
- if (manualToken) {
3261
- const previousCredentials = await store.load();
3262
- try {
3263
- const sessionClient = new ApiClient(apiUrl, manualToken, "session");
3264
- const user = await sessionClient.getMe();
3265
- const { key, keyId } = await sessionClient.mintCliApiKey();
3266
- const cleanup = await storeReplacementCredentials(store, previousCredentials, {
3267
- token: key,
3268
- apiUrl,
3269
- authKind: "api_key",
3270
- keyId
3271
- });
3272
- success(`Logged in as ${user.name} (${user.email})`);
3273
- if (cleanup.warning)
3274
- warn(cleanup.warning);
3275
- } catch {
3276
- error("Could not exchange that session token. Run `index login` instead.", 1);
3277
- process.exitCode = 1;
3278
- }
3279
- return;
3280
- }
3281
3196
  info(`Authenticating with ${apiUrl}...`);
3282
3197
  const { authUrl, callbackPromise } = await handleLogin(apiUrl, appUrl, store);
3283
3198
  info("Opening browser for authentication...");
@@ -3308,7 +3223,7 @@ async function runLogin(apiUrlOverride, appUrlOverride, manualToken) {
3308
3223
  try {
3309
3224
  const creds = await store.load();
3310
3225
  if (creds) {
3311
- const client = new ApiClient(creds.apiUrl, creds.token, creds.authKind);
3226
+ const client = new ApiClient(creds.apiUrl, creds.token);
3312
3227
  const user = await client.getMe();
3313
3228
  success(`Logged in as ${user.name} (${user.email})`);
3314
3229
  }
@@ -3343,7 +3258,7 @@ async function main() {
3343
3258
  error(`Unknown command: ${args.unknown}`, 1);
3344
3259
  return;
3345
3260
  case "login":
3346
- await runLogin(args.apiUrl, args.appUrl, args.token);
3261
+ await runLogin(args.apiUrl, args.appUrl);
3347
3262
  return;
3348
3263
  case "logout":
3349
3264
  await runLogout();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indexnetwork/cli",
3
- "version": "0.13.3-rc.62.1",
3
+ "version": "0.14.0-rc.63.1",
4
4
  "description": "Command-line interface for Index Network",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,10 +20,10 @@
20
20
  "publish:all": "bun scripts/publish.ts"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@indexnetwork/cli-linux-x64": "0.13.3-rc.62.1",
24
- "@indexnetwork/cli-linux-arm64": "0.13.3-rc.62.1",
25
- "@indexnetwork/cli-darwin-x64": "0.13.3-rc.62.1",
26
- "@indexnetwork/cli-darwin-arm64": "0.13.3-rc.62.1"
23
+ "@indexnetwork/cli-linux-x64": "0.14.0-rc.63.1",
24
+ "@indexnetwork/cli-linux-arm64": "0.14.0-rc.63.1",
25
+ "@indexnetwork/cli-darwin-x64": "0.14.0-rc.63.1",
26
+ "@indexnetwork/cli-darwin-arm64": "0.14.0-rc.63.1"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/bun": "1.3.14"