@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 +5 -1
- package/dist/index.js +59 -2
- package/package.json +1 -1
- package/src/commands/consume.ts +1 -0
- package/src/commands/feedback.ts +44 -0
- package/src/index.ts +49 -2
- package/src/lib/output.ts +18 -0
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
package/src/commands/consume.ts
CHANGED
|
@@ -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
|
);
|