@lidianai/cli 0.1.1 → 0.1.3
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 +9 -1
- package/dist/index.js +81 -11
- package/package.json +1 -1
- package/src/commands/account.ts +1 -1
- package/src/commands/consume.ts +2 -1
- package/src/commands/discover.ts +1 -1
- package/src/commands/feedback.ts +44 -0
- package/src/index.ts +62 -4
- package/src/lib/auth.ts +2 -9
- package/src/lib/http.ts +34 -8
- package/src/lib/output.ts +18 -0
- package/src/lib/x402.ts +2 -2
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,14 @@ 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`
|
|
45
|
+
|
|
46
|
+
Default payment rail behavior when `--payment-rail` is omitted:
|
|
47
|
+
- with API key/token: `prepaid_credits`
|
|
48
|
+
- without auth: `x402`
|
|
41
49
|
|
|
42
50
|
## Dev
|
|
43
51
|
|
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
|
};
|
|
@@ -226,11 +254,7 @@ var openUrl = (url) => {
|
|
|
226
254
|
// src/lib/auth.ts
|
|
227
255
|
var resolveApiKey = async (argsApiKey) => {
|
|
228
256
|
const config = await readConfig();
|
|
229
|
-
|
|
230
|
-
if (!key) {
|
|
231
|
-
throw new CliError("Missing API key. Use `lidian login --key ld_...`, pass --api-key, or set LIDIAN_API_KEY.");
|
|
232
|
-
}
|
|
233
|
-
return key;
|
|
257
|
+
return argsApiKey ?? process.env.LIDIAN_API_KEY ?? config.apiKey;
|
|
234
258
|
};
|
|
235
259
|
|
|
236
260
|
// src/lib/http.ts
|
|
@@ -257,15 +281,26 @@ var createHttpClient = (baseUrl) => {
|
|
|
257
281
|
}
|
|
258
282
|
};
|
|
259
283
|
};
|
|
260
|
-
var authHeaders = (apiKey) =>
|
|
261
|
-
|
|
262
|
-
}
|
|
284
|
+
var authHeaders = (apiKey) => {
|
|
285
|
+
if (!apiKey || apiKey.trim().length === 0) {
|
|
286
|
+
return {};
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
Authorization: `Bearer ${apiKey}`
|
|
290
|
+
};
|
|
291
|
+
};
|
|
263
292
|
var handleResponse = async (response) => {
|
|
264
293
|
const json = await response.json().catch(() => null);
|
|
265
294
|
if (!response.ok) {
|
|
266
295
|
if (json && "success" in json && json.success === false) {
|
|
267
296
|
throw new CliError(`${json.error.code}: ${json.error.message}`, 1);
|
|
268
297
|
}
|
|
298
|
+
if (json && typeof json === "object" && "error" in json && typeof json.error === "string") {
|
|
299
|
+
throw new CliError(json.error, 1);
|
|
300
|
+
}
|
|
301
|
+
if (json && typeof json === "object" && "message" in json && typeof json.message === "string") {
|
|
302
|
+
throw new CliError(json.message, 1);
|
|
303
|
+
}
|
|
269
304
|
throw new CliError(`Request failed with status ${response.status}`, 1);
|
|
270
305
|
}
|
|
271
306
|
if (!json || !("success" in json) || json.success !== true) {
|
|
@@ -293,6 +328,7 @@ var COMMAND_OPTIONS = {
|
|
|
293
328
|
"max-price"
|
|
294
329
|
]),
|
|
295
330
|
consume: new Set(["endpoint-id", "params", "payment-rail", "network"]),
|
|
331
|
+
feedback: new Set(["execution-id", "rank", "feedback"]),
|
|
296
332
|
account: new Set([]),
|
|
297
333
|
login: new Set(["key"])
|
|
298
334
|
};
|
|
@@ -347,7 +383,7 @@ var main = async () => {
|
|
|
347
383
|
}
|
|
348
384
|
const paramsRaw = asString(parsed.options.params) ?? "{}";
|
|
349
385
|
const params = parseJsonObject(paramsRaw, "--params");
|
|
350
|
-
const paymentRail =
|
|
386
|
+
const paymentRail = resolvePaymentRail(asString(parsed.options["payment-rail"]), apiKey);
|
|
351
387
|
const network = asNetwork(asString(parsed.options.network));
|
|
352
388
|
const result = await runConsumeCommand(http, apiKey, {
|
|
353
389
|
endpointId: endpointIdValue,
|
|
@@ -364,15 +400,35 @@ var main = async () => {
|
|
|
364
400
|
printAccountResult(result, asJson);
|
|
365
401
|
return;
|
|
366
402
|
}
|
|
403
|
+
case "feedback": {
|
|
404
|
+
const apiKey = await resolveApiKey(asString(parsed.options["api-key"]));
|
|
405
|
+
const executionId = asString(parsed.options["execution-id"]);
|
|
406
|
+
if (!executionId) {
|
|
407
|
+
throw new CliError("Missing --execution-id for feedback command.");
|
|
408
|
+
}
|
|
409
|
+
const rankRaw = asString(parsed.options.rank);
|
|
410
|
+
if (!rankRaw) {
|
|
411
|
+
throw new CliError("Missing --rank for feedback command.");
|
|
412
|
+
}
|
|
413
|
+
const rank = toIntInRange(rankRaw, "rank", 0, 10);
|
|
414
|
+
const feedback = asString(parsed.options.feedback);
|
|
415
|
+
const result = await runFeedbackCommand(http, apiKey, {
|
|
416
|
+
executionId,
|
|
417
|
+
rank,
|
|
418
|
+
...feedback ? { feedback } : {}
|
|
419
|
+
});
|
|
420
|
+
printFeedbackResult(result, asJson);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
367
423
|
default:
|
|
368
424
|
throw new CliError("Unknown command.", 1);
|
|
369
425
|
}
|
|
370
426
|
};
|
|
371
427
|
var parseArgs = (argv) => {
|
|
372
428
|
const command = argv[0];
|
|
373
|
-
if (command !== "discover" && command !== "consume" && command !== "account" && command !== "login") {
|
|
429
|
+
if (command !== "discover" && command !== "consume" && command !== "feedback" && command !== "account" && command !== "login") {
|
|
374
430
|
printUsage();
|
|
375
|
-
throw new CliError("Invalid command. Use one of: login, discover, consume, account.", 1);
|
|
431
|
+
throw new CliError("Invalid command. Use one of: login, discover, consume, feedback, account.", 1);
|
|
376
432
|
}
|
|
377
433
|
const options = {};
|
|
378
434
|
let index = 1;
|
|
@@ -410,6 +466,7 @@ var printUsage = () => {
|
|
|
410
466
|
print(" [--min-price <cents>] [--max-price <cents>] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
|
|
411
467
|
print(" lidian consume --endpoint-id <uuid> --params '<json>' [--payment-rail prepaid_credits|x402] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
|
|
412
468
|
print(" [--network base|ethereum]");
|
|
469
|
+
print(' lidian feedback --execution-id <uuid> --rank <0..10> [--feedback "<text>"] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]');
|
|
413
470
|
print(" lidian account [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]");
|
|
414
471
|
print("");
|
|
415
472
|
print("Env resolution:");
|
|
@@ -431,6 +488,13 @@ var toInt = (value, fallback) => {
|
|
|
431
488
|
}
|
|
432
489
|
return parsed;
|
|
433
490
|
};
|
|
491
|
+
var toIntInRange = (value, flagName, min, max) => {
|
|
492
|
+
const parsed = Number.parseInt(value, 10);
|
|
493
|
+
if (Number.isNaN(parsed) || String(parsed) !== value || parsed < min || parsed > max) {
|
|
494
|
+
throw new CliError(`Invalid --${flagName} value: ${value}. Expected integer ${min}..${max}.`);
|
|
495
|
+
}
|
|
496
|
+
return parsed;
|
|
497
|
+
};
|
|
434
498
|
var toNumber = (value, flagName) => {
|
|
435
499
|
if (!value)
|
|
436
500
|
return;
|
|
@@ -457,6 +521,12 @@ var asPaymentRail = (value) => {
|
|
|
457
521
|
return value;
|
|
458
522
|
throw new CliError("Invalid --payment-rail. Use prepaid_credits or x402.");
|
|
459
523
|
};
|
|
524
|
+
var resolvePaymentRail = (value, apiKey) => {
|
|
525
|
+
if (value) {
|
|
526
|
+
return asPaymentRail(value);
|
|
527
|
+
}
|
|
528
|
+
return apiKey && apiKey.trim().length > 0 ? "prepaid_credits" : "x402";
|
|
529
|
+
};
|
|
460
530
|
var asAuthType = (value) => {
|
|
461
531
|
if (!value)
|
|
462
532
|
return;
|
package/package.json
CHANGED
package/src/commands/account.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface AccountApiResponse {
|
|
|
17
17
|
|
|
18
18
|
export const runAccountCommand = async (
|
|
19
19
|
http: HttpClient,
|
|
20
|
-
apiKey: string,
|
|
20
|
+
apiKey: string | undefined,
|
|
21
21
|
): Promise<AccountApiResponse> => {
|
|
22
22
|
return http.get<AccountApiResponse>("/v1/account", apiKey);
|
|
23
23
|
};
|
package/src/commands/consume.ts
CHANGED
|
@@ -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;
|
|
@@ -33,7 +34,7 @@ export interface ConsumeCommandResult {
|
|
|
33
34
|
|
|
34
35
|
export const runConsumeCommand = async (
|
|
35
36
|
http: HttpClient,
|
|
36
|
-
apiKey: string,
|
|
37
|
+
apiKey: string | undefined,
|
|
37
38
|
input: ConsumeCommandInput,
|
|
38
39
|
): Promise<ConsumeCommandResult> => {
|
|
39
40
|
if (!isUuid(input.endpointId)) {
|
package/src/commands/discover.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface DiscoverApiResponse {
|
|
|
34
34
|
|
|
35
35
|
export const runDiscoverCommand = async (
|
|
36
36
|
http: HttpClient,
|
|
37
|
-
apiKey: string,
|
|
37
|
+
apiKey: string | undefined,
|
|
38
38
|
input: DiscoverCommandInput,
|
|
39
39
|
): Promise<DiscoverApiResponse> => {
|
|
40
40
|
if (input.pageSize < 1 || input.pageSize > 3) {
|
|
@@ -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 | undefined,
|
|
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
|
};
|
|
@@ -105,8 +108,9 @@ const main = async (): Promise<void> => {
|
|
|
105
108
|
}
|
|
106
109
|
const paramsRaw = asString(parsed.options.params) ?? "{}";
|
|
107
110
|
const params = parseJsonObject(paramsRaw, "--params");
|
|
108
|
-
const paymentRail =
|
|
109
|
-
asString(parsed.options["payment-rail"])
|
|
111
|
+
const paymentRail = resolvePaymentRail(
|
|
112
|
+
asString(parsed.options["payment-rail"]),
|
|
113
|
+
apiKey,
|
|
110
114
|
);
|
|
111
115
|
const network = asNetwork(asString(parsed.options.network));
|
|
112
116
|
const result = await runConsumeCommand(http, apiKey, {
|
|
@@ -124,6 +128,26 @@ const main = async (): Promise<void> => {
|
|
|
124
128
|
printAccountResult(result, asJson);
|
|
125
129
|
return;
|
|
126
130
|
}
|
|
131
|
+
case "feedback": {
|
|
132
|
+
const apiKey = await resolveApiKey(asString(parsed.options["api-key"]));
|
|
133
|
+
const executionId = asString(parsed.options["execution-id"]);
|
|
134
|
+
if (!executionId) {
|
|
135
|
+
throw new CliError("Missing --execution-id for feedback command.");
|
|
136
|
+
}
|
|
137
|
+
const rankRaw = asString(parsed.options.rank);
|
|
138
|
+
if (!rankRaw) {
|
|
139
|
+
throw new CliError("Missing --rank for feedback command.");
|
|
140
|
+
}
|
|
141
|
+
const rank = toIntInRange(rankRaw, "rank", 0, 10);
|
|
142
|
+
const feedback = asString(parsed.options.feedback);
|
|
143
|
+
const result = await runFeedbackCommand(http, apiKey, {
|
|
144
|
+
executionId,
|
|
145
|
+
rank,
|
|
146
|
+
...(feedback ? { feedback } : {}),
|
|
147
|
+
});
|
|
148
|
+
printFeedbackResult(result, asJson);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
127
151
|
default:
|
|
128
152
|
throw new CliError("Unknown command.", 1);
|
|
129
153
|
}
|
|
@@ -134,12 +158,13 @@ const parseArgs = (argv: string[]): ParsedArgs => {
|
|
|
134
158
|
if (
|
|
135
159
|
command !== "discover" &&
|
|
136
160
|
command !== "consume" &&
|
|
161
|
+
command !== "feedback" &&
|
|
137
162
|
command !== "account" &&
|
|
138
163
|
command !== "login"
|
|
139
164
|
) {
|
|
140
165
|
printUsage();
|
|
141
166
|
throw new CliError(
|
|
142
|
-
"Invalid command. Use one of: login, discover, consume, account.",
|
|
167
|
+
"Invalid command. Use one of: login, discover, consume, feedback, account.",
|
|
143
168
|
1,
|
|
144
169
|
);
|
|
145
170
|
}
|
|
@@ -190,6 +215,9 @@ const printUsage = (): void => {
|
|
|
190
215
|
" lidian consume --endpoint-id <uuid> --params '<json>' [--payment-rail prepaid_credits|x402] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]",
|
|
191
216
|
);
|
|
192
217
|
print(" [--network base|ethereum]");
|
|
218
|
+
print(
|
|
219
|
+
' lidian feedback --execution-id <uuid> --rank <0..10> [--feedback "<text>"] [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]',
|
|
220
|
+
);
|
|
193
221
|
print(
|
|
194
222
|
" lidian account [--api-key <key>] [--env production|staging] [--api-base <url>] [--json]",
|
|
195
223
|
);
|
|
@@ -214,6 +242,26 @@ const toInt = (value: string | undefined, fallback: number): number => {
|
|
|
214
242
|
return parsed;
|
|
215
243
|
};
|
|
216
244
|
|
|
245
|
+
const toIntInRange = (
|
|
246
|
+
value: string,
|
|
247
|
+
flagName: string,
|
|
248
|
+
min: number,
|
|
249
|
+
max: number,
|
|
250
|
+
): number => {
|
|
251
|
+
const parsed = Number.parseInt(value, 10);
|
|
252
|
+
if (
|
|
253
|
+
Number.isNaN(parsed) ||
|
|
254
|
+
String(parsed) !== value ||
|
|
255
|
+
parsed < min ||
|
|
256
|
+
parsed > max
|
|
257
|
+
) {
|
|
258
|
+
throw new CliError(
|
|
259
|
+
`Invalid --${flagName} value: ${value}. Expected integer ${min}..${max}.`,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
return parsed;
|
|
263
|
+
};
|
|
264
|
+
|
|
217
265
|
const toNumber = (
|
|
218
266
|
value: string | undefined,
|
|
219
267
|
flagName: string,
|
|
@@ -247,6 +295,16 @@ const asPaymentRail = (value: string): PaymentRail => {
|
|
|
247
295
|
throw new CliError("Invalid --payment-rail. Use prepaid_credits or x402.");
|
|
248
296
|
};
|
|
249
297
|
|
|
298
|
+
const resolvePaymentRail = (
|
|
299
|
+
value: string | undefined,
|
|
300
|
+
apiKey: string | undefined,
|
|
301
|
+
): PaymentRail => {
|
|
302
|
+
if (value) {
|
|
303
|
+
return asPaymentRail(value);
|
|
304
|
+
}
|
|
305
|
+
return apiKey && apiKey.trim().length > 0 ? "prepaid_credits" : "x402";
|
|
306
|
+
};
|
|
307
|
+
|
|
250
308
|
const asAuthType = (
|
|
251
309
|
value: string | undefined,
|
|
252
310
|
):
|
package/src/lib/auth.ts
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import { readConfig } from "@/lib/config";
|
|
2
|
-
import { CliError } from "@/lib/errors";
|
|
3
2
|
|
|
4
3
|
export const resolveApiKey = async (
|
|
5
4
|
argsApiKey: string | undefined,
|
|
6
|
-
): Promise<string> => {
|
|
5
|
+
): Promise<string | undefined> => {
|
|
7
6
|
const config = await readConfig();
|
|
8
|
-
|
|
9
|
-
if (!key) {
|
|
10
|
-
throw new CliError(
|
|
11
|
-
"Missing API key. Use `lidian login --key ld_...`, pass --api-key, or set LIDIAN_API_KEY.",
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
return key;
|
|
7
|
+
return argsApiKey ?? process.env.LIDIAN_API_KEY ?? config.apiKey;
|
|
15
8
|
};
|
package/src/lib/http.ts
CHANGED
|
@@ -13,25 +13,30 @@ export interface ApiFailure {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
interface PlainApiError {
|
|
17
|
+
error?: string;
|
|
18
|
+
message?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type ApiResponse<T> = ApiSuccess<T> | ApiFailure | PlainApiError;
|
|
17
22
|
|
|
18
23
|
export interface HttpClient {
|
|
19
|
-
get<T>(path: string, apiKey
|
|
20
|
-
post<T, B>(path: string, body: B, apiKey
|
|
24
|
+
get<T>(path: string, apiKey?: string): Promise<T>;
|
|
25
|
+
post<T, B>(path: string, body: B, apiKey?: string): Promise<T>;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export const createHttpClient = (baseUrl: string): HttpClient => {
|
|
24
29
|
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
25
30
|
|
|
26
31
|
return {
|
|
27
|
-
async get<T>(path: string, apiKey
|
|
32
|
+
async get<T>(path: string, apiKey?: string): Promise<T> {
|
|
28
33
|
const response = await fetch(`${normalizedBaseUrl}${path}`, {
|
|
29
34
|
method: "GET",
|
|
30
35
|
headers: authHeaders(apiKey),
|
|
31
36
|
});
|
|
32
37
|
return handleResponse<T>(response);
|
|
33
38
|
},
|
|
34
|
-
async post<T, B>(path: string, body: B, apiKey
|
|
39
|
+
async post<T, B>(path: string, body: B, apiKey?: string): Promise<T> {
|
|
35
40
|
const response = await fetch(`${normalizedBaseUrl}${path}`, {
|
|
36
41
|
method: "POST",
|
|
37
42
|
headers: {
|
|
@@ -45,9 +50,14 @@ export const createHttpClient = (baseUrl: string): HttpClient => {
|
|
|
45
50
|
};
|
|
46
51
|
};
|
|
47
52
|
|
|
48
|
-
const authHeaders = (apiKey
|
|
49
|
-
|
|
50
|
-
}
|
|
53
|
+
const authHeaders = (apiKey?: string): HeadersInit => {
|
|
54
|
+
if (!apiKey || apiKey.trim().length === 0) {
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
Authorization: `Bearer ${apiKey}`,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
51
61
|
|
|
52
62
|
const handleResponse = async <T>(response: Response): Promise<T> => {
|
|
53
63
|
const json = (await response
|
|
@@ -58,6 +68,22 @@ const handleResponse = async <T>(response: Response): Promise<T> => {
|
|
|
58
68
|
if (json && "success" in json && json.success === false) {
|
|
59
69
|
throw new CliError(`${json.error.code}: ${json.error.message}`, 1);
|
|
60
70
|
}
|
|
71
|
+
if (
|
|
72
|
+
json &&
|
|
73
|
+
typeof json === "object" &&
|
|
74
|
+
"error" in json &&
|
|
75
|
+
typeof json.error === "string"
|
|
76
|
+
) {
|
|
77
|
+
throw new CliError(json.error, 1);
|
|
78
|
+
}
|
|
79
|
+
if (
|
|
80
|
+
json &&
|
|
81
|
+
typeof json === "object" &&
|
|
82
|
+
"message" in json &&
|
|
83
|
+
typeof json.message === "string"
|
|
84
|
+
) {
|
|
85
|
+
throw new CliError(json.message, 1);
|
|
86
|
+
}
|
|
61
87
|
throw new CliError(`Request failed with status ${response.status}`, 1);
|
|
62
88
|
}
|
|
63
89
|
|
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
|
);
|
package/src/lib/x402.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface PaymentVerifyResponse {
|
|
|
27
27
|
|
|
28
28
|
export const requestPaymentRequirements = async (
|
|
29
29
|
http: HttpClient,
|
|
30
|
-
apiKey: string,
|
|
30
|
+
apiKey: string | undefined,
|
|
31
31
|
endpointId: string,
|
|
32
32
|
network?: string,
|
|
33
33
|
): Promise<PaymentRequirementsResponse> => {
|
|
@@ -43,7 +43,7 @@ export const requestPaymentRequirements = async (
|
|
|
43
43
|
|
|
44
44
|
export const verifyPaymentAddress = async (
|
|
45
45
|
http: HttpClient,
|
|
46
|
-
apiKey: string,
|
|
46
|
+
apiKey: string | undefined,
|
|
47
47
|
payTo: string,
|
|
48
48
|
): Promise<PaymentVerifyResponse> => {
|
|
49
49
|
return http.post<PaymentVerifyResponse, { payTo: string }>(
|