@indexnetwork/cli 0.10.12 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +3 -0
  2. package/dist/index.js +91 -13
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -245,6 +245,9 @@ index opportunity show <id>
245
245
  # Accept — starts a conversation thread
246
246
  index opportunity accept <id>
247
247
 
248
+ # If preparatory questions are returned, resolve them first or explicitly continue
249
+ index opportunity accept <id> --acknowledge-uptake <question-id[,question-id...]>
250
+
248
251
  # Or reject
249
252
  index opportunity reject <id>
250
253
  ```
package/dist/index.js CHANGED
@@ -130,6 +130,9 @@ function parseArgs(args) {
130
130
  } else if (arg === "--since") {
131
131
  result.since = args[i + 1];
132
132
  i += 2;
133
+ } else if (arg === "--acknowledge-uptake") {
134
+ result.acknowledgeUptake = (args[i + 1] ?? "").split(",").map((id) => id.trim()).filter(Boolean);
135
+ i += 2;
133
136
  } else if (arg.startsWith("--")) {
134
137
  i++;
135
138
  } else {
@@ -289,6 +292,17 @@ class CredentialStore {
289
292
  }
290
293
 
291
294
  // src/api.client.ts
295
+ class ApiError extends Error {
296
+ status;
297
+ response;
298
+ constructor(message, status, response) {
299
+ super(message);
300
+ this.status = status;
301
+ this.response = response;
302
+ this.name = "ApiError";
303
+ }
304
+ }
305
+
292
306
  class ApiClient {
293
307
  baseUrl;
294
308
  token;
@@ -327,6 +341,13 @@ class ApiClient {
327
341
  const res = await this.get(`/api/opportunities/${id}`);
328
342
  return await res.json();
329
343
  }
344
+ async acceptOpportunity(id, acknowledgedUptakeQuestionIds) {
345
+ const res = await this.patch(`/api/opportunities/${id}/status`, {
346
+ status: "accepted",
347
+ ...acknowledgedUptakeQuestionIds ? { acknowledgedUptakeQuestionIds } : {}
348
+ });
349
+ return await res.json();
350
+ }
330
351
  async streamChat(params) {
331
352
  const res = await fetch(`${this.baseUrl}/api/chat/stream`, {
332
353
  method: "POST",
@@ -507,6 +528,19 @@ class ApiClient {
507
528
  }
508
529
  return res;
509
530
  }
531
+ async patch(path, body) {
532
+ const res = await fetch(`${this.baseUrl}${path}`, {
533
+ method: "PATCH",
534
+ headers: {
535
+ "Content-Type": "application/json",
536
+ Authorization: `Bearer ${this.token}`
537
+ },
538
+ ...body !== undefined ? { body: JSON.stringify(body) } : {}
539
+ });
540
+ if (!res.ok)
541
+ await this.handleError(res);
542
+ return res;
543
+ }
510
544
  async del(path) {
511
545
  const res = await fetch(`${this.baseUrl}${path}`, {
512
546
  method: "DELETE",
@@ -521,15 +555,19 @@ class ApiClient {
521
555
  }
522
556
  async handleError(res) {
523
557
  if (res.status === 401) {
524
- throw new Error("Session expired or invalid. Run `index login` to re-authenticate.");
558
+ throw new ApiError("Session expired or invalid. Run `index login` to re-authenticate.", res.status);
525
559
  }
526
560
  let message = `HTTP ${res.status}`;
561
+ let response;
527
562
  try {
528
- const body = await res.json();
529
- if (body.error)
530
- message = body.error;
563
+ response = await res.json();
564
+ if (typeof response === "object" && response !== null && "error" in response) {
565
+ const error = response.error;
566
+ if (typeof error === "string")
567
+ message = error;
568
+ }
531
569
  } catch {}
532
- throw new Error(message);
570
+ throw new ApiError(message, res.status, response);
533
571
  }
534
572
  }
535
573
 
@@ -735,7 +773,7 @@ function info(message) {
735
773
  console.log(`${CYAN}${message}${RESET}`);
736
774
  }
737
775
  function warn(message) {
738
- console.log(`${YELLOW}${message}${RESET}`);
776
+ console.warn(`${YELLOW}${message}${RESET}`);
739
777
  }
740
778
  function dim(message) {
741
779
  console.log(`${GRAY}${message}${RESET}`);
@@ -1784,6 +1822,7 @@ Usage:
1784
1822
  index opportunity list --limit <n> Limit results
1785
1823
  index opportunity show <id> Show full opportunity details (accepts short ID)
1786
1824
  index opportunity accept <id> Accept an opportunity (accepts short ID)
1825
+ index opportunity accept <id> --acknowledge-uptake <id,id> Continue after an uptake advisory
1787
1826
  index opportunity reject <id> Reject an opportunity (accepts short ID)
1788
1827
  index opportunity discover <query> Discover opportunities by search query
1789
1828
  index opportunity discover --target <uid> <q> Discover for a specific user
@@ -1814,7 +1853,7 @@ async function handleOpportunity(client, subcommand, options) {
1814
1853
  error("Missing opportunity ID. Usage: index opportunity accept <id>", 1);
1815
1854
  return;
1816
1855
  }
1817
- await opportunityStatusUpdate(client, options.targetId, "accepted", options.json);
1856
+ await opportunityStatusUpdate(client, options.targetId, "accepted", options.json, options.acknowledgeUptake);
1818
1857
  return;
1819
1858
  case "reject":
1820
1859
  if (!options.targetId) {
@@ -1881,8 +1920,40 @@ async function opportunityShow(client, id, json) {
1881
1920
  }
1882
1921
  opportunityCard(opportunity);
1883
1922
  }
1884
- async function opportunityStatusUpdate(client, id, status2, json) {
1923
+ async function opportunityStatusUpdate(client, id, status2, json, acknowledgedUptakeQuestionIds) {
1885
1924
  const opportunity = await client.getOpportunity(id);
1925
+ if (status2 === "accepted") {
1926
+ try {
1927
+ const result2 = await client.acceptOpportunity(opportunity.id, acknowledgedUptakeQuestionIds);
1928
+ if (json) {
1929
+ console.log(JSON.stringify(result2));
1930
+ return;
1931
+ }
1932
+ success("Opportunity accepted.");
1933
+ } catch (error2) {
1934
+ const advisory = uptakeAdvisoryFromError(error2);
1935
+ if (json && error2 instanceof ApiError) {
1936
+ console.log(JSON.stringify(error2.response ?? { error: error2.message }));
1937
+ return;
1938
+ }
1939
+ if (!advisory)
1940
+ throw error2;
1941
+ heading("Questions before accepting");
1942
+ for (const question of advisory.advisory.questions) {
1943
+ console.log(`
1944
+ ${question.title}`);
1945
+ console.log(question.prompt);
1946
+ for (const option of question.options) {
1947
+ console.log(` - ${option.label}${option.description ? ` — ${option.description}` : ""}`);
1948
+ }
1949
+ dim(` Question ID: ${question.id}`);
1950
+ }
1951
+ const ids = advisory.advisory.questions.map((question) => question.id).join(",");
1952
+ info(`Answer or dismiss these questions, then retry. To continue anyway, run:
1953
+ index opportunity accept ${opportunity.id} --acknowledge-uptake ${ids}`);
1954
+ }
1955
+ return;
1956
+ }
1886
1957
  const result = await client.callTool("update_opportunity", {
1887
1958
  opportunityId: opportunity.id,
1888
1959
  status: status2
@@ -1892,10 +1963,16 @@ async function opportunityStatusUpdate(client, id, status2, json) {
1892
1963
  return;
1893
1964
  }
1894
1965
  if (!result.success) {
1895
- error(result.error ?? `Failed to ${status2 === "accepted" ? "accept" : "reject"} opportunity`, 1);
1966
+ error(result.error ?? "Failed to reject opportunity", 1);
1896
1967
  return;
1897
1968
  }
1898
- success(`Opportunity ${status2 === "accepted" ? "accepted" : "rejected"}.`);
1969
+ success("Opportunity rejected.");
1970
+ }
1971
+ function uptakeAdvisoryFromError(error2) {
1972
+ if (!(error2 instanceof ApiError) || error2.status !== 409)
1973
+ return null;
1974
+ const body = error2.response;
1975
+ return body?.advisory?.code === "unresolved_uptake_questions" ? body : null;
1899
1976
  }
1900
1977
  async function discoverIntroduction(client, userA, userB, hint, json) {
1901
1978
  if (!json)
@@ -1918,7 +1995,7 @@ async function discoverIntroduction(client, userA, userB, hint, json) {
1918
1995
  const idsA = new Set(indexesA.map((m) => m.networkId));
1919
1996
  const shared = indexesB.filter((m) => idsA.has(m.networkId));
1920
1997
  if (shared.length === 0) {
1921
- const err = "No shared indexes found between these users. They must be members of at least one common network.";
1998
+ const err = "No shared networks found between these users. They must be members of at least one common network.";
1922
1999
  if (json) {
1923
2000
  console.log(JSON.stringify({ success: false, error: err }));
1924
2001
  return;
@@ -2966,7 +3043,7 @@ async function onboardingComplete(client, json) {
2966
3043
  // src/main.ts
2967
3044
  var DEFAULT_API_URL = "https://protocol.index.network";
2968
3045
  var DEFAULT_APP_URL = "https://index.network";
2969
- var VERSION = "0.10.12";
3046
+ var VERSION = "0.11.0";
2970
3047
  var BOX = { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│" };
2971
3048
  function visualLen(s) {
2972
3049
  return stripAnsi(s).length;
@@ -3243,7 +3320,8 @@ async function main() {
3243
3320
  json: args.json,
3244
3321
  positionals: args.positionals,
3245
3322
  target: args.target,
3246
- introduce: args.introduce
3323
+ introduce: args.introduce,
3324
+ acknowledgeUptake: args.acknowledgeUptake
3247
3325
  });
3248
3326
  return;
3249
3327
  case "negotiation":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indexnetwork/cli",
3
- "version": "0.10.12",
3
+ "version": "0.11.0",
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.10.12",
24
- "@indexnetwork/cli-linux-arm64": "0.10.12",
25
- "@indexnetwork/cli-darwin-x64": "0.10.12",
26
- "@indexnetwork/cli-darwin-arm64": "0.10.12"
23
+ "@indexnetwork/cli-linux-x64": "0.11.0",
24
+ "@indexnetwork/cli-linux-arm64": "0.11.0",
25
+ "@indexnetwork/cli-darwin-x64": "0.11.0",
26
+ "@indexnetwork/cli-darwin-arm64": "0.11.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/bun": "latest"