@lidianai/cli 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -13,6 +13,7 @@ bunx @lidianai/cli --help
13
13
  ```bash
14
14
  lidian discover --q "<term>" [--page 1] [--pageSize 1..3] [--category <name>] [--auth-type none|api_key|bearer|basic|oauth2|custom] [--min-price <cents>] [--max-price <cents>] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]
15
15
  lidian consume --endpoint-id <uuid> --params '<json>' [--payment-rail prepaid_credits|x402] [--network base|ethereum] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]
16
+ lidian feedback --execution-id <uuid> --rank <0..10> [--feedback "<text>"] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]
16
17
  lidian account [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]
17
18
  lidian login [--key ld_...] [--json]
18
19
  lidian --help
@@ -37,7 +38,10 @@ lidian --help
37
38
  When `--payment-rail x402` is used, CLI performs:
38
39
  1. `POST /v1/payments/requirements`
39
40
  2. `POST /v1/payments/verify`
40
- 3. `POST /v1/consume`
41
+ 3. `POST /v1/consume` (returns `executionId`)
42
+
43
+ Submit feedback later:
44
+ 4. `POST /v1/consume/feedback` with `executionId`, `rank`, optional `feedback`
41
45
 
42
46
  ## Dev
43
47
 
package/dist/index.js CHANGED
@@ -70,6 +70,23 @@ var runDiscoverCommand = async (http, apiKey, input) => {
70
70
  return http.get(`/v1/discover?${params.toString()}`, apiKey);
71
71
  };
72
72
 
73
+ // src/commands/feedback.ts
74
+ var runFeedbackCommand = async (http, apiKey, input) => {
75
+ if (!isUuid2(input.executionId)) {
76
+ throw new CliError("executionId must be a valid UUID.");
77
+ }
78
+ if (!Number.isInteger(input.rank) || input.rank < 0 || input.rank > 10) {
79
+ throw new CliError("rank must be an integer between 0 and 10.");
80
+ }
81
+ if (typeof input.feedback === "string" && input.feedback.length > 1000) {
82
+ throw new CliError("feedback cannot exceed 1000 characters.");
83
+ }
84
+ return http.post("/v1/consume/feedback", input, apiKey);
85
+ };
86
+ var isUuid2 = (value) => {
87
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
88
+ };
89
+
73
90
  // src/commands/login.ts
74
91
  import { stdin, stdout } from "process";
75
92
  import { createInterface } from "readline/promises";
@@ -148,7 +165,18 @@ var printAccountResult = (result, asJson) => {
148
165
  print(`Account: ${result.user.id}`);
149
166
  print(`Balance: ${result.balance.balance} cents (${formatUsd(result.balance.balance)})`);
150
167
  };
168
+ var printFeedbackResult = (result, asJson) => {
169
+ if (asJson) {
170
+ printResult(result, true);
171
+ return;
172
+ }
173
+ const feedback = result.feedback ?? "<none>";
174
+ print(`Feedback saved for execution=${result.executionId} rank=${result.rank} submittedBy=${result.submittedBy}`);
175
+ print(`Updated at: ${result.updatedAt}`);
176
+ print(`Comment: ${feedback}`);
177
+ };
151
178
  var printExecutionResult = (result) => {
179
+ print(`Execution ID: ${result.executionId}`);
152
180
  print(`Execution succeeded. Spent=${result.credits.spent} cents (${formatUsd(result.credits.spent)}) balance=${result.credits.balance} cents (${formatUsd(result.credits.balance)})`);
153
181
  print(JSON.stringify(result.data, null, 2));
154
182
  };
@@ -293,6 +321,7 @@ var COMMAND_OPTIONS = {
293
321
  "max-price"
294
322
  ]),
295
323
  consume: new Set(["endpoint-id", "params", "payment-rail", "network"]),
324
+ feedback: new Set(["execution-id", "rank", "feedback"]),
296
325
  account: new Set([]),
297
326
  login: new Set(["key"])
298
327
  };
@@ -364,15 +393,35 @@ var main = async () => {
364
393
  printAccountResult(result, asJson);
365
394
  return;
366
395
  }
396
+ case "feedback": {
397
+ const apiKey = await resolveApiKey(asString(parsed.options["api-key"]));
398
+ const executionId = asString(parsed.options["execution-id"]);
399
+ if (!executionId) {
400
+ throw new CliError("Missing --execution-id for feedback command.");
401
+ }
402
+ const rankRaw = asString(parsed.options.rank);
403
+ if (!rankRaw) {
404
+ throw new CliError("Missing --rank for feedback command.");
405
+ }
406
+ const rank = toIntInRange(rankRaw, "rank", 0, 10);
407
+ const feedback = asString(parsed.options.feedback);
408
+ const result = await runFeedbackCommand(http, apiKey, {
409
+ executionId,
410
+ rank,
411
+ ...feedback ? { feedback } : {}
412
+ });
413
+ printFeedbackResult(result, asJson);
414
+ return;
415
+ }
367
416
  default:
368
417
  throw new CliError("Unknown command.", 1);
369
418
  }
370
419
  };
371
420
  var parseArgs = (argv) => {
372
421
  const command = argv[0];
373
- if (command !== "discover" && command !== "consume" && command !== "account" && command !== "login") {
422
+ if (command !== "discover" && command !== "consume" && command !== "feedback" && command !== "account" && command !== "login") {
374
423
  printUsage();
375
- throw new CliError("Invalid command. Use one of: login, discover, consume, account.", 1);
424
+ throw new CliError("Invalid command. Use one of: login, discover, consume, feedback, account.", 1);
376
425
  }
377
426
  const options = {};
378
427
  let index = 1;
@@ -410,6 +459,7 @@ var printUsage = () => {
410
459
  print(" [--min-price <cents>] [--max-price <cents>] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
411
460
  print(" lidian consume --endpoint-id <uuid> --params '<json>' [--payment-rail prepaid_credits|x402] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
412
461
  print(" [--network base|ethereum]");
462
+ print(' lidian feedback --execution-id <uuid> --rank <0..10> [--feedback "<text>"] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]');
413
463
  print(" lidian account [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
414
464
  print("");
415
465
  print("Env resolution:");
@@ -431,6 +481,13 @@ var toInt = (value, fallback) => {
431
481
  }
432
482
  return parsed;
433
483
  };
484
+ var toIntInRange = (value, flagName, min, max) => {
485
+ const parsed = Number.parseInt(value, 10);
486
+ if (Number.isNaN(parsed) || String(parsed) !== value || parsed < min || parsed > max) {
487
+ throw new CliError(`Invalid --${flagName} value: ${value}. Expected integer ${min}..${max}.`);
488
+ }
489
+ return parsed;
490
+ };
434
491
  var toNumber = (value, flagName) => {
435
492
  if (!value)
436
493
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lidianai/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -16,6 +16,7 @@ export interface ConsumeCommandInput {
16
16
  }
17
17
 
18
18
  export interface ConsumeApiResponse {
19
+ executionId: string;
19
20
  data: unknown;
20
21
  credits: {
21
22
  spent: number;
@@ -0,0 +1,44 @@
1
+ import { CliError } from "@/lib/errors";
2
+ import type { HttpClient } from "@/lib/http";
3
+
4
+ export interface FeedbackCommandInput {
5
+ executionId: string;
6
+ rank: number;
7
+ feedback?: string;
8
+ }
9
+
10
+ export interface FeedbackApiResponse {
11
+ executionId: string;
12
+ rank: number;
13
+ feedback: string | null;
14
+ submittedBy: "agent" | "human";
15
+ updatedAt: string;
16
+ }
17
+
18
+ export const runFeedbackCommand = async (
19
+ http: HttpClient,
20
+ apiKey: string,
21
+ input: FeedbackCommandInput,
22
+ ): Promise<FeedbackApiResponse> => {
23
+ if (!isUuid(input.executionId)) {
24
+ throw new CliError("executionId must be a valid UUID.");
25
+ }
26
+ if (!Number.isInteger(input.rank) || input.rank < 0 || input.rank > 10) {
27
+ throw new CliError("rank must be an integer between 0 and 10.");
28
+ }
29
+ if (typeof input.feedback === "string" && input.feedback.length > 1000) {
30
+ throw new CliError("feedback cannot exceed 1000 characters.");
31
+ }
32
+
33
+ return http.post<FeedbackApiResponse, FeedbackCommandInput>(
34
+ "/v1/consume/feedback",
35
+ input,
36
+ apiKey,
37
+ );
38
+ };
39
+
40
+ const isUuid = (value: string): boolean => {
41
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
42
+ value,
43
+ );
44
+ };
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  import { runAccountCommand } from "@/commands/account";
4
4
  import { type PaymentRail, runConsumeCommand } from "@/commands/consume";
5
5
  import { runDiscoverCommand } from "@/commands/discover";
6
+ import { runFeedbackCommand } from "@/commands/feedback";
6
7
  import { runLoginCommand } from "@/commands/login";
7
8
  import { resolveApiKey } from "@/lib/auth";
8
9
  import { CliError } from "@/lib/errors";
@@ -13,10 +14,11 @@ import {
13
14
  printAccountResult,
14
15
  printConsumeResult,
15
16
  printDiscoverResult,
17
+ printFeedbackResult,
16
18
  } from "@/lib/output";
17
19
 
18
20
  interface ParsedArgs {
19
- command: "discover" | "consume" | "account" | "login";
21
+ command: "discover" | "consume" | "feedback" | "account" | "login";
20
22
  options: Record<string, string | boolean>;
21
23
  }
22
24
 
@@ -40,6 +42,7 @@ const COMMAND_OPTIONS: Record<ParsedArgs["command"], Set<string>> = {
40
42
  "max-price",
41
43
  ]),
42
44
  consume: new Set(["endpoint-id", "params", "payment-rail", "network"]),
45
+ feedback: new Set(["execution-id", "rank", "feedback"]),
43
46
  account: new Set([]),
44
47
  login: new Set(["key"]),
45
48
  };
@@ -124,6 +127,26 @@ const main = async (): Promise<void> => {
124
127
  printAccountResult(result, asJson);
125
128
  return;
126
129
  }
130
+ case "feedback": {
131
+ const apiKey = await resolveApiKey(asString(parsed.options["api-key"]));
132
+ const executionId = asString(parsed.options["execution-id"]);
133
+ if (!executionId) {
134
+ throw new CliError("Missing --execution-id for feedback command.");
135
+ }
136
+ const rankRaw = asString(parsed.options.rank);
137
+ if (!rankRaw) {
138
+ throw new CliError("Missing --rank for feedback command.");
139
+ }
140
+ const rank = toIntInRange(rankRaw, "rank", 0, 10);
141
+ const feedback = asString(parsed.options.feedback);
142
+ const result = await runFeedbackCommand(http, apiKey, {
143
+ executionId,
144
+ rank,
145
+ ...(feedback ? { feedback } : {}),
146
+ });
147
+ printFeedbackResult(result, asJson);
148
+ return;
149
+ }
127
150
  default:
128
151
  throw new CliError("Unknown command.", 1);
129
152
  }
@@ -134,12 +157,13 @@ const parseArgs = (argv: string[]): ParsedArgs => {
134
157
  if (
135
158
  command !== "discover" &&
136
159
  command !== "consume" &&
160
+ command !== "feedback" &&
137
161
  command !== "account" &&
138
162
  command !== "login"
139
163
  ) {
140
164
  printUsage();
141
165
  throw new CliError(
142
- "Invalid command. Use one of: login, discover, consume, account.",
166
+ "Invalid command. Use one of: login, discover, consume, feedback, account.",
143
167
  1,
144
168
  );
145
169
  }
@@ -190,6 +214,9 @@ const printUsage = (): void => {
190
214
  " lidian consume --endpoint-id <uuid> --params '<json>' [--payment-rail prepaid_credits|x402] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]",
191
215
  );
192
216
  print(" [--network base|ethereum]");
217
+ print(
218
+ ' lidian feedback --execution-id <uuid> --rank <0..10> [--feedback "<text>"] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]',
219
+ );
193
220
  print(
194
221
  " lidian account [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]",
195
222
  );
@@ -214,6 +241,26 @@ const toInt = (value: string | undefined, fallback: number): number => {
214
241
  return parsed;
215
242
  };
216
243
 
244
+ const toIntInRange = (
245
+ value: string,
246
+ flagName: string,
247
+ min: number,
248
+ max: number,
249
+ ): number => {
250
+ const parsed = Number.parseInt(value, 10);
251
+ if (
252
+ Number.isNaN(parsed) ||
253
+ String(parsed) !== value ||
254
+ parsed < min ||
255
+ parsed > max
256
+ ) {
257
+ throw new CliError(
258
+ `Invalid --${flagName} value: ${value}. Expected integer ${min}..${max}.`,
259
+ );
260
+ }
261
+ return parsed;
262
+ };
263
+
217
264
  const toNumber = (
218
265
  value: string | undefined,
219
266
  flagName: string,
package/src/lib/output.ts CHANGED
@@ -4,6 +4,7 @@ import type {
4
4
  ConsumeCommandResult,
5
5
  } from "@/commands/consume";
6
6
  import type { DiscoverApiResponse } from "@/commands/discover";
7
+ import type { FeedbackApiResponse } from "@/commands/feedback";
7
8
  import { CliError } from "@/lib/errors";
8
9
 
9
10
  export const print = (message: string): void => {
@@ -77,7 +78,24 @@ export const printAccountResult = (
77
78
  );
78
79
  };
79
80
 
81
+ export const printFeedbackResult = (
82
+ result: FeedbackApiResponse,
83
+ asJson: boolean,
84
+ ): void => {
85
+ if (asJson) {
86
+ printResult(result, true);
87
+ return;
88
+ }
89
+ const feedback = result.feedback ?? "<none>";
90
+ print(
91
+ `Feedback saved for execution=${result.executionId} rank=${result.rank} submittedBy=${result.submittedBy}`,
92
+ );
93
+ print(`Updated at: ${result.updatedAt}`);
94
+ print(`Comment: ${feedback}`);
95
+ };
96
+
80
97
  const printExecutionResult = (result: ConsumeApiResponse): void => {
98
+ print(`Execution ID: ${result.executionId}`);
81
99
  print(
82
100
  `Execution succeeded. Spent=${result.credits.spent} cents (${formatUsd(result.credits.spent)}) balance=${result.credits.balance} cents (${formatUsd(result.credits.balance)})`,
83
101
  );