@indexnetwork/cli 0.13.3-rc.62.1 → 0.15.0-rc.64.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 +70 -459
  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.15.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.15.0",
43
+ "@indexnetwork/cli-linux-arm64": "0.15.0",
44
+ "@indexnetwork/cli-darwin-x64": "0.15.0",
45
+ "@indexnetwork/cli-darwin-arm64": "0.15.0"
46
46
  },
47
47
  devDependencies: {
48
48
  "@types/bun": "1.3.14"
@@ -54,7 +54,7 @@ var KNOWN_COMMANDS = new Set(["login", "logout", "profile", "intent", "opportuni
54
54
  var OPPORTUNITY_SUBCOMMANDS = new Set(["list", "show", "accept", "reject"]);
55
55
  var NEGOTIATION_SUBCOMMANDS = new Set(["list", "show"]);
56
56
  var NETWORK_SUBCOMMANDS = new Set(["list", "create", "show", "join", "leave", "invite", "update", "delete"]);
57
- var CONVERSATION_SUBCOMMANDS = new Set(["list", "with", "show", "send", "stream", "sessions", "help"]);
57
+ var CONVERSATION_SUBCOMMANDS = new Set(["list", "with", "show", "send", "stream", "help"]);
58
58
  function parseArgs(args) {
59
59
  const result = {
60
60
  command: "help",
@@ -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";
@@ -103,7 +101,6 @@ function parseArgs(args) {
103
101
  result.list = true;
104
102
  i++;
105
103
  } else if (arg === "--session" || arg === "-s") {
106
- result.sessionId = args[i + 1];
107
104
  i += 2;
108
105
  } else if (arg === "--api-url") {
109
106
  result.apiUrl = args[i + 1];
@@ -111,9 +108,6 @@ function parseArgs(args) {
111
108
  } else if (arg === "--app-url") {
112
109
  result.appUrl = args[i + 1];
113
110
  i += 2;
114
- } else if (arg === "--token" || arg === "-t") {
115
- result.token = args[i + 1];
116
- i += 2;
117
111
  } else if (arg === "--archived") {
118
112
  result.archived = true;
119
113
  i++;
@@ -241,8 +235,6 @@ function parseArgs(args) {
241
235
  if (positionals.length > 0 && CONVERSATION_SUBCOMMANDS.has(positionals[0])) {
242
236
  result.subcommand = positionals[0];
243
237
  result.positionals = positionals.slice(1);
244
- } else if (positionals.length > 0) {
245
- result.message = positionals.join(" ");
246
238
  }
247
239
  }
248
240
  return result;
@@ -280,6 +272,48 @@ function parseIntentArgs(positionals, result) {
280
272
  }
281
273
  }
282
274
 
275
+ // src/auth.store.ts
276
+ import { join } from "node:path";
277
+ import { homedir } from "node:os";
278
+ import { mkdir, readFile, writeFile, unlink } from "node:fs/promises";
279
+ var CREDENTIALS_FILE = "credentials.json";
280
+
281
+ class CredentialStore {
282
+ dir;
283
+ filePath;
284
+ constructor(dir) {
285
+ this.dir = dir ?? join(homedir(), ".index");
286
+ this.filePath = join(this.dir, CREDENTIALS_FILE);
287
+ }
288
+ async load() {
289
+ try {
290
+ const raw = await readFile(this.filePath, "utf-8");
291
+ const parsed = JSON.parse(raw);
292
+ if (parsed.token && parsed.apiUrl && parsed.authKind === "api_key" && parsed.keyId) {
293
+ return parsed;
294
+ }
295
+ return null;
296
+ } catch {
297
+ return null;
298
+ }
299
+ }
300
+ async save(credentials) {
301
+ await mkdir(this.dir, { recursive: true });
302
+ await writeFile(this.filePath, JSON.stringify(credentials, null, 2), {
303
+ mode: 384
304
+ });
305
+ }
306
+ async clear() {
307
+ try {
308
+ await unlink(this.filePath);
309
+ } catch (error) {
310
+ if (error.code === "ENOENT")
311
+ return;
312
+ throw error;
313
+ }
314
+ }
315
+ }
316
+
283
317
  // src/api.client.ts
284
318
  class ApiError extends Error {
285
319
  status;
@@ -301,27 +335,12 @@ function isEarlyAccessNetworkCreationError(error) {
301
335
  class ApiClient {
302
336
  baseUrl;
303
337
  token;
304
- authKind;
305
- constructor(baseUrl, token, authKind = "session") {
338
+ constructor(baseUrl, token) {
306
339
  this.baseUrl = baseUrl.replace(/\/$/, "");
307
340
  this.token = token;
308
- this.authKind = authKind;
309
341
  }
310
342
  authHeaders() {
311
- return this.authKind === "api_key" ? { "x-api-key": this.token } : { Authorization: `Bearer ${this.token}` };
312
- }
313
- async listSessions() {
314
- const res = await this.get("/api/chat/sessions");
315
- const body = await res.json();
316
- return body.sessions;
317
- }
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 };
343
+ return { "x-api-key": this.token };
325
344
  }
326
345
  async revokeApiKey(keyId, targetKey = this.token) {
327
346
  const res = await this.post("/api/auth/cli-credential/revoke", { keyId, targetKey });
@@ -363,23 +382,6 @@ class ApiClient {
363
382
  });
364
383
  return await res.json();
365
384
  }
366
- async streamChat(params) {
367
- const res = await fetch(`${this.baseUrl}/api/chat/stream`, {
368
- method: "POST",
369
- headers: {
370
- "Content-Type": "application/json",
371
- ...this.authHeaders()
372
- },
373
- body: JSON.stringify({
374
- message: params.message,
375
- ...params.sessionId ? { sessionId: params.sessionId } : {}
376
- })
377
- });
378
- if (!res.ok) {
379
- await this.handleError(res);
380
- }
381
- return res;
382
- }
383
385
  async listIntents(options = {}) {
384
386
  const body = {};
385
387
  if (options.limit !== undefined)
@@ -603,23 +605,21 @@ class ApiClient {
603
605
  }
604
606
  }
605
607
 
608
+ // src/login.command.ts
609
+ import { randomBytes } from "node:crypto";
610
+ import { createServer } from "node:http";
611
+
606
612
  // src/auth.lifecycle.ts
607
613
  async function storeReplacementCredentials(store, previous, replacement, options = {}) {
608
614
  await store.save(replacement);
609
- if (previous?.authKind !== "api_key")
615
+ if (!previous)
610
616
  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) {
617
+ if (replacement.keyId === previous.keyId) {
617
618
  return {};
618
619
  }
619
- const authKind = replacement.authKind ?? "session";
620
- const createClient = options.clientFactory ?? ((apiUrl, token, kind) => new ApiClient(apiUrl, token, kind));
620
+ const createClient = options.clientFactory ?? ((apiUrl, token) => new ApiClient(apiUrl, token));
621
621
  try {
622
- await createClient(replacement.apiUrl, replacement.token, authKind).revokeApiKey(previous.keyId, previous.token);
622
+ await createClient(replacement.apiUrl, replacement.token).revokeApiKey(previous.keyId, previous.token);
623
623
  return {};
624
624
  } catch (error) {
625
625
  const detail = error instanceof Error ? ` ${error.message}` : "";
@@ -629,51 +629,7 @@ async function storeReplacementCredentials(store, previous, replacement, options
629
629
  }
630
630
  }
631
631
 
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
632
  // src/login.command.ts
675
- import { randomBytes } from "node:crypto";
676
- import { createServer } from "node:http";
677
633
  function closeServer(server) {
678
634
  return new Promise((resolve) => {
679
635
  let resolved = false;
@@ -728,7 +684,6 @@ async function handleLogin(apiUrl, appUrl, store, options = {}) {
728
684
  stateConsumed = true;
729
685
  const apiKey = url.searchParams.get("api_key");
730
686
  const keyId = url.searchParams.get("key_id");
731
- const sessionToken = url.searchParams.get("session_token");
732
687
  if (apiKey && keyId) {
733
688
  try {
734
689
  const cleanup = await storeReplacementCredentials(store, previousCredentials, {
@@ -748,24 +703,6 @@ async function handleLogin(apiUrl, appUrl, store, options = {}) {
748
703
  res.end(callbackHtml("CLI authorized", "You can close this window and return to the terminal.", true));
749
704
  return;
750
705
  }
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
706
  resolveCallback({
770
707
  success: false,
771
708
  error: apiKey ? "CLI API-key callback did not include its key ID." : "No CLI credential received in callback."
@@ -887,17 +824,7 @@ async function handleLogout(store, options = {}) {
887
824
  if (!credentials) {
888
825
  return { success: true, message: "Already logged out." };
889
826
  }
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"));
827
+ const createClient = options.clientFactory ?? ((apiUrl, token) => new ApiClient(apiUrl, token));
901
828
  try {
902
829
  await createClient(credentials.apiUrl, credentials.token).revokeApiKey(credentials.keyId, credentials.token);
903
830
  } catch (error) {
@@ -927,7 +854,6 @@ __export(exports_output, {
927
854
  success: () => success,
928
855
  stripAnsi: () => stripAnsi,
929
856
  status: () => status,
930
- sessionTable: () => sessionTable,
931
857
  raw: () => raw,
932
858
  profileCard: () => profileCard,
933
859
  padTo: () => padTo,
@@ -1361,28 +1287,6 @@ function contactTable(contacts) {
1361
1287
  console.log(` ${c.name.padEnd(nameWidth)} ${c.email}${ghost}`);
1362
1288
  }
1363
1289
  }
1364
- function sessionTable(sessions) {
1365
- if (sessions.length === 0) {
1366
- dim(" No chat sessions found.");
1367
- return;
1368
- }
1369
- const idWidth = 36;
1370
- const titleWidth = 40;
1371
- const dateWidth = 20;
1372
- console.log(` ${BOLD}${"ID".padEnd(idWidth)} ${"Title".padEnd(titleWidth)} ${"Created".padEnd(dateWidth)}${RESET}`);
1373
- console.log(` ${GRAY}${"-".repeat(idWidth)} ${"-".repeat(titleWidth)} ${"-".repeat(dateWidth)}${RESET}`);
1374
- for (const s of sessions) {
1375
- const title = (s.title ?? "(untitled)").slice(0, titleWidth);
1376
- const date = new Date(s.createdAt).toLocaleDateString("en-US", {
1377
- year: "numeric",
1378
- month: "short",
1379
- day: "numeric",
1380
- hour: "2-digit",
1381
- minute: "2-digit"
1382
- });
1383
- console.log(` ${GRAY}${s.id.padEnd(idWidth)}${RESET} ${title.padEnd(titleWidth)} ${GRAY}${date}${RESET}`);
1384
- }
1385
- }
1386
1290
  function intentTable(intents) {
1387
1291
  if (intents.length === 0) {
1388
1292
  dim(" No signals found.");
@@ -2488,122 +2392,9 @@ async function networkInvite(client, id, email, json) {
2488
2392
  }
2489
2393
 
2490
2394
  // src/conversation.command.ts
2491
- import { createInterface } from "node:readline/promises";
2492
- async function renderSSEStream(response, callbacks) {
2493
- const { onToken, onStatus, onToolActivity, onResponseReset } = callbacks;
2494
- const result = {};
2495
- if (!response.body) {
2496
- result.error = "No response body";
2497
- return result;
2498
- }
2499
- const reader = response.body.getReader();
2500
- const decoder = new TextDecoder;
2501
- let buffer = "";
2502
- let insideToolCall = false;
2503
- const toolDescriptions = new Map;
2504
- try {
2505
- while (true) {
2506
- const { done, value } = await reader.read();
2507
- if (done)
2508
- break;
2509
- buffer += decoder.decode(value, { stream: true });
2510
- while (buffer.includes(`
2511
-
2512
- `)) {
2513
- const idx = buffer.indexOf(`
2514
-
2515
- `);
2516
- const raw2 = buffer.slice(0, idx);
2517
- buffer = buffer.slice(idx + 2);
2518
- for (const line of raw2.split(`
2519
- `)) {
2520
- if (!line.startsWith("data:"))
2521
- continue;
2522
- const jsonStr = line.slice("data:".length).trim();
2523
- if (!jsonStr)
2524
- continue;
2525
- try {
2526
- const event = JSON.parse(jsonStr);
2527
- const type = event.type;
2528
- switch (type) {
2529
- case "token": {
2530
- if (typeof event.content !== "string")
2531
- break;
2532
- if (insideToolCall)
2533
- break;
2534
- onToken(event.content);
2535
- break;
2536
- }
2537
- case "status":
2538
- if (onStatus && typeof event.message === "string") {
2539
- onStatus(event.message);
2540
- }
2541
- break;
2542
- case "tool_activity": {
2543
- const phase = event.phase;
2544
- const toolName = typeof event.toolName === "string" ? event.toolName : "";
2545
- const desc = typeof event.description === "string" ? event.description : undefined;
2546
- if (phase === "start") {
2547
- insideToolCall = true;
2548
- if (desc && toolName) {
2549
- toolDescriptions.set(toolName, desc);
2550
- }
2551
- if (onToolActivity && desc) {
2552
- onToolActivity(desc, "start");
2553
- }
2554
- } else if (phase === "end") {
2555
- insideToolCall = false;
2556
- const startDesc = toolName ? toolDescriptions.get(toolName) : undefined;
2557
- if (onToolActivity) {
2558
- onToolActivity(startDesc ?? desc ?? toolName, "end", event.success !== false);
2559
- }
2560
- if (toolName)
2561
- toolDescriptions.delete(toolName);
2562
- }
2563
- break;
2564
- }
2565
- case "tool_start":
2566
- insideToolCall = true;
2567
- break;
2568
- case "tool_end":
2569
- insideToolCall = false;
2570
- break;
2571
- case "llm_start":
2572
- insideToolCall = false;
2573
- break;
2574
- case "response_reset":
2575
- result.response = undefined;
2576
- if (onResponseReset) {
2577
- onResponseReset(typeof event.reason === "string" ? event.reason : undefined);
2578
- }
2579
- break;
2580
- case "done":
2581
- result.sessionId = typeof event.sessionId === "string" ? event.sessionId : undefined;
2582
- result.response = typeof event.response === "string" ? event.response : undefined;
2583
- result.title = typeof event.title === "string" ? event.title : undefined;
2584
- break;
2585
- case "error":
2586
- result.error = typeof event.message === "string" ? event.message : "Unknown stream error";
2587
- break;
2588
- default:
2589
- break;
2590
- }
2591
- } catch {}
2592
- }
2593
- }
2594
- }
2595
- } finally {
2596
- reader.releaseLock();
2597
- }
2598
- return result;
2599
- }
2600
2395
  var CONVERSATION_HELP = `
2601
2396
  Conversation Commands:
2602
- index conversation Start an interactive AI chat (REPL)
2603
- index conversation "message" One-shot message to the AI agent
2604
- index conversation --session <id> Resume a specific chat session
2605
- index conversation sessions List AI chat sessions
2606
- index conversation list List all conversations (H2A + H2H)
2397
+ index conversation list List all conversations
2607
2398
  index conversation with <user-id|key> Open or resume a DM with a user
2608
2399
  index conversation show <id> Show messages (accepts short ID)
2609
2400
  index conversation show <id> --limit <n> Limit number of messages
@@ -2612,21 +2403,10 @@ Conversation Commands:
2612
2403
  `;
2613
2404
  async function handleConversation(client, subcommand, positionals, options) {
2614
2405
  if (!subcommand) {
2615
- if (options?.json) {
2616
- error("`--json` requires an explicit conversation subcommand.", 1);
2617
- return;
2618
- }
2619
- if (options?.message) {
2620
- await chatOneShot(client, options.message, options.sessionId);
2621
- } else {
2622
- await chatRepl(client, options?.sessionId);
2623
- }
2406
+ error("Agent chat is no longer available from the CLI. Use `index conversation list` " + "for your conversations, or chat in the Index app.", 1);
2624
2407
  return;
2625
2408
  }
2626
2409
  switch (subcommand) {
2627
- case "sessions":
2628
- await chatSessionsList(client, options?.json);
2629
- return;
2630
2410
  case "list":
2631
2411
  await conversationList(client, options?.json);
2632
2412
  return;
@@ -2752,132 +2532,6 @@ async function conversationStream(client) {
2752
2532
  reader.releaseLock();
2753
2533
  }
2754
2534
  }
2755
- async function chatSessionsList(client, json) {
2756
- const sessions = await client.listSessions();
2757
- if (json) {
2758
- console.log(JSON.stringify(sessions));
2759
- return;
2760
- }
2761
- heading("Chat Sessions");
2762
- sessionTable(sessions);
2763
- console.log();
2764
- }
2765
- async function chatOneShot(client, message, sessionId) {
2766
- const response = await client.streamChat({ message, sessionId });
2767
- if (!response.ok) {
2768
- handleStreamError(response);
2769
- return;
2770
- }
2771
- const result = await streamToTerminal(response);
2772
- if (result.error) {
2773
- error(result.error, 1);
2774
- return;
2775
- }
2776
- if (result.sessionId) {
2777
- dim(`
2778
- Session: ${result.sessionId}`);
2779
- }
2780
- }
2781
- async function chatRepl(client, sessionId) {
2782
- let currentSessionId = sessionId;
2783
- chatHeader();
2784
- const PROMPT_STR2 = PROMPT_STR;
2785
- const rl = createInterface({
2786
- input: process.stdin,
2787
- output: process.stderr,
2788
- terminal: true
2789
- });
2790
- rl.setPrompt(PROMPT_STR2);
2791
- rl.prompt();
2792
- try {
2793
- for await (const line of rl) {
2794
- const input = line.trim();
2795
- if (!input) {
2796
- rl.prompt();
2797
- continue;
2798
- }
2799
- if (input === "exit" || input === "quit")
2800
- break;
2801
- const response = await client.streamChat({
2802
- message: input,
2803
- sessionId: currentSessionId
2804
- });
2805
- if (!response.ok) {
2806
- if (response.status === 401) {
2807
- error("Session expired. Run `index login` to re-authenticate.", 1);
2808
- return;
2809
- }
2810
- const body = await response.json().catch(() => ({}));
2811
- error(body.error ?? `HTTP ${response.status}`);
2812
- rl.prompt();
2813
- continue;
2814
- }
2815
- const result = await streamToTerminal(response);
2816
- if (result.error) {
2817
- error(result.error);
2818
- }
2819
- if (result.sessionId) {
2820
- currentSessionId = result.sessionId;
2821
- }
2822
- process.stderr.write(`
2823
- `);
2824
- rl.prompt();
2825
- }
2826
- } finally {
2827
- rl.close();
2828
- }
2829
- process.stderr.write(`
2830
- `);
2831
- dim("Goodbye!");
2832
- }
2833
- async function streamToTerminal(response) {
2834
- let hasTokens = false;
2835
- const md = new MarkdownRenderer;
2836
- let lastToolDesc = "";
2837
- const result = await renderSSEStream(response, {
2838
- onToken(text) {
2839
- if (!hasTokens) {
2840
- clearStatus();
2841
- hasTokens = true;
2842
- }
2843
- md.write(text);
2844
- lastToolDesc = "";
2845
- },
2846
- onStatus(msg) {
2847
- if (!hasTokens) {
2848
- status(msg);
2849
- }
2850
- },
2851
- onToolActivity(description, phase) {
2852
- if (phase === "start") {
2853
- const friendly = humanizeToolName(description);
2854
- if (friendly === lastToolDesc)
2855
- return;
2856
- lastToolDesc = friendly;
2857
- md.finalize();
2858
- hasTokens = false;
2859
- toolActivity(friendly);
2860
- }
2861
- },
2862
- onResponseReset(reason) {
2863
- md.reset(reason);
2864
- hasTokens = false;
2865
- }
2866
- });
2867
- md.finalize();
2868
- clearStatus();
2869
- if (hasTokens) {
2870
- console.log();
2871
- }
2872
- return result;
2873
- }
2874
- async function handleStreamError(response) {
2875
- if (response.status === 401) {
2876
- error("Session expired or invalid. Run `index login` to re-authenticate.", 1);
2877
- }
2878
- const body = await response.json().catch(() => ({}));
2879
- error(body.error ?? `HTTP ${response.status}`, 1);
2880
- }
2881
2535
 
2882
2536
  // src/contact.command.ts
2883
2537
  var CONTACT_HELP = `
@@ -3113,7 +2767,6 @@ function helpRowCont(leftW, right) {
3113
2767
  function renderHelp() {
3114
2768
  const gsLefts = [
3115
2769
  "index login",
3116
- "index login --token <token>",
3117
2770
  "index logout",
3118
2771
  'index intent create "..."',
3119
2772
  "index negotiation list",
@@ -3121,8 +2774,7 @@ function renderHelp() {
3121
2774
  ];
3122
2775
  const gsLW = Math.max(...gsLefts.map((s) => s.length));
3123
2776
  const formsLefts = [
3124
- 'index conversation "message"',
3125
- "index conversation --session <id>",
2777
+ "index conversation list",
3126
2778
  "index sync --json",
3127
2779
  "index profile create",
3128
2780
  "index profile update",
@@ -3149,8 +2801,6 @@ function renderHelp() {
3149
2801
  const optLefts = [
3150
2802
  "--api-url <url>",
3151
2803
  "--app-url <url>",
3152
- "--token <token>",
3153
- "--session <id>",
3154
2804
  "--archived",
3155
2805
  "--status <status>",
3156
2806
  "--limit <n>",
@@ -3174,15 +2824,13 @@ function renderHelp() {
3174
2824
  `);
3175
2825
  panel("getting started", [
3176
2826
  helpRowCmd(gsLW, "index login", "authenticate via browser"),
3177
- helpRowCmd(gsLW, "index login --token <token>", "authenticate with a bearer token"),
3178
2827
  helpRowCmd(gsLW, "index logout", "clear stored session"),
3179
2828
  helpRowCmd(gsLW, 'index intent create "..."', "describe what you're looking for"),
3180
2829
  helpRowCmd(gsLW, "index negotiation list", "see agent debates in progress"),
3181
2830
  helpRowCmd(gsLW, "index opportunity list", "see what was found for you")
3182
2831
  ]);
3183
2832
  panel("common forms", [
3184
- helpRowCmd(formsLW, 'index conversation "message"', "send a one-shot agent message"),
3185
- helpRowCmd(formsLW, "index conversation --session <id>", "resume an agent chat session"),
2833
+ helpRowCmd(formsLW, "index conversation list", "list your conversations"),
3186
2834
  helpRowCmd(formsLW, "index sync --json", "print synced context as JSON"),
3187
2835
  "",
3188
2836
  helpRowCmd(formsLW, "index profile create", "use social URL flags"),
@@ -3200,7 +2848,7 @@ function renderHelp() {
3200
2848
  helpRowCmd(cmdLW, "negotiation", "list · show"),
3201
2849
  "",
3202
2850
  helpRowCmd(cmdLW, "profile", "show · sync · search · create · update"),
3203
- helpRowCmd(cmdLW, "conversation", "sessions · list · with · show · send · stream"),
2851
+ helpRowCmd(cmdLW, "conversation", "list · with · show · send · stream"),
3204
2852
  helpRowCmd(cmdLW, "network", "list · create · show · update · delete"),
3205
2853
  helpRowCont(cmdLW, "join · leave · invite"),
3206
2854
  helpRowCmd(cmdLW, "contact", "list · add · remove · import"),
@@ -3212,8 +2860,6 @@ function renderHelp() {
3212
2860
  panel("options", [
3213
2861
  helpRowDim(optLW, "--api-url <url>", "override API server URL"),
3214
2862
  helpRowDim(optLW, "--app-url <url>", "override app URL for login"),
3215
- helpRowDim(optLW, "--token <token>", "provide bearer token directly"),
3216
- helpRowDim(optLW, "--session <id>", "resume a chat session"),
3217
2863
  helpRowDim(optLW, "--archived", "include archived signals"),
3218
2864
  helpRowDim(optLW, "--status <status>", "filter opportunities by status"),
3219
2865
  helpRowDim(optLW, "--limit <n>", "limit number of results"),
@@ -3239,45 +2885,12 @@ async function requireAuth(apiUrlOverride) {
3239
2885
  process.exit(1);
3240
2886
  }
3241
2887
  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);
2888
+ return new ApiClient(apiUrl, creds.token);
3255
2889
  }
3256
- async function runLogin(apiUrlOverride, appUrlOverride, manualToken) {
2890
+ async function runLogin(apiUrlOverride, appUrlOverride) {
3257
2891
  const store = new CredentialStore;
3258
2892
  const apiUrl = apiUrlOverride ?? DEFAULT_API_URL;
3259
2893
  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
2894
  info(`Authenticating with ${apiUrl}...`);
3282
2895
  const { authUrl, callbackPromise } = await handleLogin(apiUrl, appUrl, store);
3283
2896
  info("Opening browser for authentication...");
@@ -3308,7 +2921,7 @@ async function runLogin(apiUrlOverride, appUrlOverride, manualToken) {
3308
2921
  try {
3309
2922
  const creds = await store.load();
3310
2923
  if (creds) {
3311
- const client = new ApiClient(creds.apiUrl, creds.token, creds.authKind);
2924
+ const client = new ApiClient(creds.apiUrl, creds.token);
3312
2925
  const user = await client.getMe();
3313
2926
  success(`Logged in as ${user.name} (${user.email})`);
3314
2927
  }
@@ -3343,7 +2956,7 @@ async function main() {
3343
2956
  error(`Unknown command: ${args.unknown}`, 1);
3344
2957
  return;
3345
2958
  case "login":
3346
- await runLogin(args.apiUrl, args.appUrl, args.token);
2959
+ await runLogin(args.apiUrl, args.appUrl);
3347
2960
  return;
3348
2961
  case "logout":
3349
2962
  await runLogout();
@@ -3398,8 +3011,6 @@ async function main() {
3398
3011
  case "conversation":
3399
3012
  await handleConversation(client, args.subcommand, args.positionals ?? [], {
3400
3013
  limit: args.limit,
3401
- sessionId: args.sessionId,
3402
- message: args.message,
3403
3014
  json: args.json
3404
3015
  });
3405
3016
  return;
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.15.0-rc.64.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.15.0-rc.64.1",
24
+ "@indexnetwork/cli-linux-arm64": "0.15.0-rc.64.1",
25
+ "@indexnetwork/cli-darwin-x64": "0.15.0-rc.64.1",
26
+ "@indexnetwork/cli-darwin-arm64": "0.15.0-rc.64.1"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/bun": "1.3.14"