@agentrade/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/LICENSE +22 -0
- package/dist/index.js +415 -99
- package/package.json +15 -16
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentrade Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/dist/index.js
CHANGED
|
@@ -3,79 +3,6 @@
|
|
|
3
3
|
// src/program.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
|
-
// ../../packages/config/src/index.ts
|
|
7
|
-
var envString = (key, fallback) => {
|
|
8
|
-
const raw = process.env[key];
|
|
9
|
-
return raw && raw.length > 0 ? raw : fallback;
|
|
10
|
-
};
|
|
11
|
-
var PLACEHOLDER_VALUES = {
|
|
12
|
-
JWT_SECRET: "replace-this-secret",
|
|
13
|
-
ADMIN_SERVICE_KEY: "replace-this-admin-key"
|
|
14
|
-
};
|
|
15
|
-
var defaultConfig = {
|
|
16
|
-
appName: "Agentrade",
|
|
17
|
-
host: "0.0.0.0",
|
|
18
|
-
port: 3e3,
|
|
19
|
-
apiDefaultVersion: "v2",
|
|
20
|
-
databaseUrl: "postgresql://postgres:postgres@localhost:5432/agentrade",
|
|
21
|
-
redisUrl: "redis://localhost:6379",
|
|
22
|
-
enablePersistence: true,
|
|
23
|
-
enableRedisRateLimit: true,
|
|
24
|
-
trustProxy: false,
|
|
25
|
-
corsAllowedOrigins: [
|
|
26
|
-
"http://localhost:3000",
|
|
27
|
-
"http://127.0.0.1:3000",
|
|
28
|
-
"http://localhost:3001",
|
|
29
|
-
"http://127.0.0.1:3001"
|
|
30
|
-
],
|
|
31
|
-
jwtSecret: PLACEHOLDER_VALUES.JWT_SECRET,
|
|
32
|
-
adminServiceKey: PLACEHOLDER_VALUES.ADMIN_SERVICE_KEY,
|
|
33
|
-
authChallengeTtlMinutes: 10,
|
|
34
|
-
authChallengeMaxEntries: 1e4,
|
|
35
|
-
authChallengeSweepIntervalMs: 3e4,
|
|
36
|
-
rateLimitPerMinute: 300,
|
|
37
|
-
rateLimitBurst: 60,
|
|
38
|
-
taskTitleMaxLength: 200,
|
|
39
|
-
taskDescriptionMaxLength: 2e4,
|
|
40
|
-
taskAcceptanceCriteriaMaxLength: 8e3,
|
|
41
|
-
taskSubmissionPayloadMaxLength: 2e4,
|
|
42
|
-
taskSubmissionAttachmentMaxCount: 10,
|
|
43
|
-
taskSubmissionAttachmentNameMaxLength: 200,
|
|
44
|
-
taskSubmissionAttachmentUrlMaxLength: 2e3,
|
|
45
|
-
taskSubmissionAttachmentMaxSizeBytes: 100 * 1024 * 1024,
|
|
46
|
-
disputeReasonMaxLength: 4e3,
|
|
47
|
-
taskSlotsMax: 100,
|
|
48
|
-
taskRewardPerSlotMax: 1e6,
|
|
49
|
-
taskDeadlineMaxHours: 4320,
|
|
50
|
-
taxRateBps: 500,
|
|
51
|
-
taxMin: 1,
|
|
52
|
-
rewardMin: 1,
|
|
53
|
-
initialAgentBalance: 1e3,
|
|
54
|
-
mintPerCycle: 1e4,
|
|
55
|
-
taskCompletionPublisherWorkload: 0.25,
|
|
56
|
-
taskCompletionWorkerWorkload: 0.25,
|
|
57
|
-
terminationPenaltyBps: 1e3,
|
|
58
|
-
submissionTimeoutHours: 72,
|
|
59
|
-
resubmitCooldownMinutes: 30,
|
|
60
|
-
disputeQuorum: 5,
|
|
61
|
-
disputeApprovalBps: 6e3,
|
|
62
|
-
reputationWeightPublisherBps: 2e3,
|
|
63
|
-
reputationWeightWorkerBps: 3e3,
|
|
64
|
-
reputationWeightSupervisorBps: 5e3,
|
|
65
|
-
scoreWeightReputationBps: 4500,
|
|
66
|
-
scoreWeightCompletionBps: 3500,
|
|
67
|
-
scoreWeightQualityBps: 2e3,
|
|
68
|
-
bridgeChain: "Base Sepolia",
|
|
69
|
-
bridgeMode: "OFFCHAIN_EXPORT_ONLY"
|
|
70
|
-
};
|
|
71
|
-
var loadCliRuntimeConfig = () => ({
|
|
72
|
-
apiBaseUrl: envString("AGENTRADE_API_BASE_URL", "https://agentrade.info/api"),
|
|
73
|
-
token: process.env.AGENTRADE_TOKEN,
|
|
74
|
-
adminServiceKey: process.env.AGENTRADE_ADMIN_SERVICE_KEY,
|
|
75
|
-
timeoutMs: envString("AGENTRADE_TIMEOUT_MS", "10000"),
|
|
76
|
-
retries: envString("AGENTRADE_RETRIES", "1")
|
|
77
|
-
});
|
|
78
|
-
|
|
79
6
|
// src/operation-bindings.ts
|
|
80
7
|
var cliOperationBindings = {
|
|
81
8
|
"activities list": "activitiesListV2",
|
|
@@ -2331,7 +2258,7 @@ var ApiClientError = class extends Error {
|
|
|
2331
2258
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
2332
2259
|
var DEFAULT_RETRIES = 1;
|
|
2333
2260
|
var sleep = async (ms) => {
|
|
2334
|
-
await new Promise((
|
|
2261
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
2335
2262
|
};
|
|
2336
2263
|
var shouldRetryStatus = (status) => status === 429 || status >= 500;
|
|
2337
2264
|
var retryDelayMs = (attempt) => Math.min(1e3, 100 * 2 ** (attempt - 1));
|
|
@@ -2686,6 +2613,233 @@ var AgentradeApiClient = class {
|
|
|
2686
2613
|
}
|
|
2687
2614
|
};
|
|
2688
2615
|
|
|
2616
|
+
// src/cli-config.ts
|
|
2617
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
|
|
2618
|
+
import { homedir } from "os";
|
|
2619
|
+
import { dirname, isAbsolute, join, resolve } from "path";
|
|
2620
|
+
var CLI_DEFAULT_BASE_URL = "https://agentrade.info/api";
|
|
2621
|
+
var CLI_DEFAULT_TIMEOUT_MS = 1e4;
|
|
2622
|
+
var CLI_DEFAULT_RETRIES = 1;
|
|
2623
|
+
var configError = (path, message) => new CliConfigError(`invalid CLI config at ${path}: ${message}`);
|
|
2624
|
+
var parseOptionalString = (raw, path, field) => {
|
|
2625
|
+
if (raw === void 0 || raw === null) {
|
|
2626
|
+
return void 0;
|
|
2627
|
+
}
|
|
2628
|
+
if (typeof raw !== "string") {
|
|
2629
|
+
throw configError(path, `${field} must be a string`);
|
|
2630
|
+
}
|
|
2631
|
+
const value = raw.trim();
|
|
2632
|
+
return value.length > 0 ? value : void 0;
|
|
2633
|
+
};
|
|
2634
|
+
var parseOptionalInteger = (raw, path, field) => {
|
|
2635
|
+
if (raw === void 0 || raw === null) {
|
|
2636
|
+
return void 0;
|
|
2637
|
+
}
|
|
2638
|
+
if (typeof raw === "number") {
|
|
2639
|
+
if (!Number.isSafeInteger(raw)) {
|
|
2640
|
+
throw configError(path, `${field} must be a safe integer`);
|
|
2641
|
+
}
|
|
2642
|
+
return raw;
|
|
2643
|
+
}
|
|
2644
|
+
if (typeof raw !== "string") {
|
|
2645
|
+
throw configError(path, `${field} must be an integer`);
|
|
2646
|
+
}
|
|
2647
|
+
const value = raw.trim();
|
|
2648
|
+
if (value.length === 0) {
|
|
2649
|
+
return void 0;
|
|
2650
|
+
}
|
|
2651
|
+
if (!/^-?\d+$/.test(value)) {
|
|
2652
|
+
throw configError(path, `${field} must be an integer`);
|
|
2653
|
+
}
|
|
2654
|
+
const parsed = Number(value);
|
|
2655
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
2656
|
+
throw configError(path, `${field} must be a safe integer`);
|
|
2657
|
+
}
|
|
2658
|
+
return parsed;
|
|
2659
|
+
};
|
|
2660
|
+
var parseCliPersistedConfig = (raw, path) => {
|
|
2661
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
2662
|
+
throw configError(path, "root value must be a JSON object");
|
|
2663
|
+
}
|
|
2664
|
+
const input = raw;
|
|
2665
|
+
const parsed = {};
|
|
2666
|
+
const baseUrl = parseOptionalString(input.baseUrl, path, "baseUrl");
|
|
2667
|
+
const token = parseOptionalString(input.token, path, "token");
|
|
2668
|
+
const adminKey = parseOptionalString(input.adminKey, path, "adminKey");
|
|
2669
|
+
const timeoutMs = parseOptionalInteger(input.timeoutMs, path, "timeoutMs");
|
|
2670
|
+
const retries = parseOptionalInteger(input.retries, path, "retries");
|
|
2671
|
+
if (baseUrl !== void 0) {
|
|
2672
|
+
let parsedUrl;
|
|
2673
|
+
try {
|
|
2674
|
+
parsedUrl = new URL(baseUrl);
|
|
2675
|
+
} catch {
|
|
2676
|
+
throw configError(path, "baseUrl must be a valid URL");
|
|
2677
|
+
}
|
|
2678
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
2679
|
+
throw configError(path, "baseUrl must start with http:// or https://");
|
|
2680
|
+
}
|
|
2681
|
+
parsed.baseUrl = baseUrl;
|
|
2682
|
+
}
|
|
2683
|
+
if (token !== void 0) {
|
|
2684
|
+
parsed.token = token;
|
|
2685
|
+
}
|
|
2686
|
+
if (adminKey !== void 0) {
|
|
2687
|
+
parsed.adminKey = adminKey;
|
|
2688
|
+
}
|
|
2689
|
+
if (timeoutMs !== void 0) {
|
|
2690
|
+
if (timeoutMs <= 0) {
|
|
2691
|
+
throw configError(path, "timeoutMs must be > 0");
|
|
2692
|
+
}
|
|
2693
|
+
parsed.timeoutMs = timeoutMs;
|
|
2694
|
+
}
|
|
2695
|
+
if (retries !== void 0) {
|
|
2696
|
+
if (retries < 0) {
|
|
2697
|
+
throw configError(path, "retries must be >= 0");
|
|
2698
|
+
}
|
|
2699
|
+
parsed.retries = retries;
|
|
2700
|
+
}
|
|
2701
|
+
return parsed;
|
|
2702
|
+
};
|
|
2703
|
+
var normalizeConfigForWrite = (values, path) => {
|
|
2704
|
+
const normalized = parseCliPersistedConfig(values, path);
|
|
2705
|
+
const ordered = {};
|
|
2706
|
+
if (normalized.baseUrl !== void 0) {
|
|
2707
|
+
ordered.baseUrl = normalized.baseUrl;
|
|
2708
|
+
}
|
|
2709
|
+
if (normalized.token !== void 0) {
|
|
2710
|
+
ordered.token = normalized.token;
|
|
2711
|
+
}
|
|
2712
|
+
if (normalized.adminKey !== void 0) {
|
|
2713
|
+
ordered.adminKey = normalized.adminKey;
|
|
2714
|
+
}
|
|
2715
|
+
if (normalized.timeoutMs !== void 0) {
|
|
2716
|
+
ordered.timeoutMs = normalized.timeoutMs;
|
|
2717
|
+
}
|
|
2718
|
+
if (normalized.retries !== void 0) {
|
|
2719
|
+
ordered.retries = normalized.retries;
|
|
2720
|
+
}
|
|
2721
|
+
return ordered;
|
|
2722
|
+
};
|
|
2723
|
+
var writeCliPersistedConfig = (path, values) => {
|
|
2724
|
+
const normalized = normalizeConfigForWrite(values, path);
|
|
2725
|
+
if (Object.keys(normalized).length === 0) {
|
|
2726
|
+
if (existsSync(path)) {
|
|
2727
|
+
unlinkSync(path);
|
|
2728
|
+
}
|
|
2729
|
+
return {
|
|
2730
|
+
path,
|
|
2731
|
+
exists: false,
|
|
2732
|
+
values: {}
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
mkdirSync(dirname(path), { recursive: true, mode: 448 });
|
|
2736
|
+
writeFileSync(path, `${JSON.stringify(normalized, null, 2)}
|
|
2737
|
+
`, {
|
|
2738
|
+
encoding: "utf8",
|
|
2739
|
+
mode: 384
|
|
2740
|
+
});
|
|
2741
|
+
return {
|
|
2742
|
+
path,
|
|
2743
|
+
exists: true,
|
|
2744
|
+
values: normalized
|
|
2745
|
+
};
|
|
2746
|
+
};
|
|
2747
|
+
var resolveCliConfigPath = () => {
|
|
2748
|
+
const explicit = process.env.AGENTRADE_CLI_CONFIG_PATH;
|
|
2749
|
+
if (explicit !== void 0) {
|
|
2750
|
+
const value = explicit.trim();
|
|
2751
|
+
if (value.length === 0) {
|
|
2752
|
+
throw new CliConfigError("AGENTRADE_CLI_CONFIG_PATH must be non-empty when set");
|
|
2753
|
+
}
|
|
2754
|
+
return isAbsolute(value) ? value : resolve(value);
|
|
2755
|
+
}
|
|
2756
|
+
const xdgBase = process.env.XDG_CONFIG_HOME?.trim();
|
|
2757
|
+
if (xdgBase) {
|
|
2758
|
+
return join(xdgBase, "agentrade", "config.json");
|
|
2759
|
+
}
|
|
2760
|
+
const home = homedir().trim();
|
|
2761
|
+
if (home.length === 0) {
|
|
2762
|
+
throw new CliConfigError("unable to resolve home directory for CLI config");
|
|
2763
|
+
}
|
|
2764
|
+
return join(home, ".agentrade", "config.json");
|
|
2765
|
+
};
|
|
2766
|
+
var loadCliPersistedConfig = () => {
|
|
2767
|
+
const path = resolveCliConfigPath();
|
|
2768
|
+
if (!existsSync(path)) {
|
|
2769
|
+
return {
|
|
2770
|
+
path,
|
|
2771
|
+
exists: false,
|
|
2772
|
+
values: {}
|
|
2773
|
+
};
|
|
2774
|
+
}
|
|
2775
|
+
let rawText;
|
|
2776
|
+
try {
|
|
2777
|
+
rawText = readFileSync2(path, "utf8");
|
|
2778
|
+
} catch (error) {
|
|
2779
|
+
throw new CliConfigError(
|
|
2780
|
+
`unable to read CLI config at ${path}: ${error instanceof Error ? error.message : String(error)}`
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
if (rawText.trim().length === 0) {
|
|
2784
|
+
return {
|
|
2785
|
+
path,
|
|
2786
|
+
exists: true,
|
|
2787
|
+
values: {}
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2790
|
+
let parsed;
|
|
2791
|
+
try {
|
|
2792
|
+
parsed = JSON.parse(rawText);
|
|
2793
|
+
} catch (error) {
|
|
2794
|
+
throw new CliConfigError(
|
|
2795
|
+
`invalid CLI config JSON at ${path}: ${error instanceof Error ? error.message : String(error)}`
|
|
2796
|
+
);
|
|
2797
|
+
}
|
|
2798
|
+
return {
|
|
2799
|
+
path,
|
|
2800
|
+
exists: true,
|
|
2801
|
+
values: parseCliPersistedConfig(parsed, path)
|
|
2802
|
+
};
|
|
2803
|
+
};
|
|
2804
|
+
var setCliPersistedConfigValue = (key, value) => {
|
|
2805
|
+
const current = loadCliPersistedConfig();
|
|
2806
|
+
const next = { ...current.values };
|
|
2807
|
+
switch (key) {
|
|
2808
|
+
case "baseUrl":
|
|
2809
|
+
next.baseUrl = String(value);
|
|
2810
|
+
break;
|
|
2811
|
+
case "token":
|
|
2812
|
+
next.token = String(value);
|
|
2813
|
+
break;
|
|
2814
|
+
case "adminKey":
|
|
2815
|
+
next.adminKey = String(value);
|
|
2816
|
+
break;
|
|
2817
|
+
case "timeoutMs":
|
|
2818
|
+
next.timeoutMs = Number(value);
|
|
2819
|
+
break;
|
|
2820
|
+
case "retries":
|
|
2821
|
+
next.retries = Number(value);
|
|
2822
|
+
break;
|
|
2823
|
+
default: {
|
|
2824
|
+
const exhaustive = key;
|
|
2825
|
+
throw new CliConfigError(`unsupported CLI config key: ${String(exhaustive)}`);
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
return writeCliPersistedConfig(current.path, next);
|
|
2829
|
+
};
|
|
2830
|
+
var unsetCliPersistedConfigKeys = (keys) => {
|
|
2831
|
+
const current = loadCliPersistedConfig();
|
|
2832
|
+
const next = { ...current.values };
|
|
2833
|
+
for (const key of keys) {
|
|
2834
|
+
delete next[key];
|
|
2835
|
+
}
|
|
2836
|
+
return writeCliPersistedConfig(current.path, next);
|
|
2837
|
+
};
|
|
2838
|
+
var clearCliPersistedConfig = () => {
|
|
2839
|
+
const current = loadCliPersistedConfig();
|
|
2840
|
+
return writeCliPersistedConfig(current.path, {});
|
|
2841
|
+
};
|
|
2842
|
+
|
|
2689
2843
|
// src/context.ts
|
|
2690
2844
|
var resolveCommandPath = (command) => {
|
|
2691
2845
|
const segments = [];
|
|
@@ -2702,19 +2856,26 @@ var normalizeOptional = (value) => {
|
|
|
2702
2856
|
}
|
|
2703
2857
|
return value.trim().length > 0 ? value : void 0;
|
|
2704
2858
|
};
|
|
2705
|
-
var
|
|
2859
|
+
var parsePositiveInteger = (value, flag) => {
|
|
2860
|
+
return ensurePositiveInteger(String(value), flag);
|
|
2861
|
+
};
|
|
2862
|
+
var parseNonNegativeInteger = (value, flag) => {
|
|
2863
|
+
return ensureNonNegativeInteger(String(value), flag);
|
|
2864
|
+
};
|
|
2865
|
+
var resolveGlobalOptions = (command, persistedConfig = loadCliPersistedConfig().values) => {
|
|
2706
2866
|
const raw = command.optsWithGlobals();
|
|
2707
|
-
const rawBaseUrl =
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
const
|
|
2712
|
-
const timeoutMs =
|
|
2713
|
-
const
|
|
2867
|
+
const rawBaseUrl = raw.baseUrl === void 0 ? persistedConfig.baseUrl : String(raw.baseUrl);
|
|
2868
|
+
const baseUrl = ensureHttpUrl(rawBaseUrl ?? CLI_DEFAULT_BASE_URL, "--base-url");
|
|
2869
|
+
const rawToken = raw.token === void 0 ? persistedConfig.token : String(raw.token);
|
|
2870
|
+
const rawAdminKey = raw.adminKey === void 0 ? persistedConfig.adminKey : String(raw.adminKey);
|
|
2871
|
+
const rawTimeoutMs = raw.timeoutMs === void 0 ? persistedConfig.timeoutMs ?? CLI_DEFAULT_TIMEOUT_MS : raw.timeoutMs;
|
|
2872
|
+
const timeoutMs = parsePositiveInteger(rawTimeoutMs, "--timeout-ms");
|
|
2873
|
+
const rawRetries = raw.retries === void 0 ? persistedConfig.retries ?? CLI_DEFAULT_RETRIES : raw.retries;
|
|
2874
|
+
const retries = parseNonNegativeInteger(rawRetries, "--retries");
|
|
2714
2875
|
return {
|
|
2715
2876
|
baseUrl,
|
|
2716
|
-
token: normalizeOptional(
|
|
2717
|
-
adminKey: normalizeOptional(
|
|
2877
|
+
token: normalizeOptional(rawToken),
|
|
2878
|
+
adminKey: normalizeOptional(rawAdminKey),
|
|
2718
2879
|
timeoutMs,
|
|
2719
2880
|
retries,
|
|
2720
2881
|
pretty: Boolean(raw.pretty)
|
|
@@ -2735,13 +2896,13 @@ var createCommandContext = (command) => {
|
|
|
2735
2896
|
client,
|
|
2736
2897
|
requireToken: () => {
|
|
2737
2898
|
if (!options.token) {
|
|
2738
|
-
throw new CliConfigError("missing token: use --token
|
|
2899
|
+
throw new CliConfigError("missing token: use --token");
|
|
2739
2900
|
}
|
|
2740
2901
|
return options.token;
|
|
2741
2902
|
},
|
|
2742
2903
|
requireAdminKey: () => {
|
|
2743
2904
|
if (!options.adminKey) {
|
|
2744
|
-
throw new CliConfigError("missing admin key: use --admin-key
|
|
2905
|
+
throw new CliConfigError("missing admin key: use --admin-key");
|
|
2745
2906
|
}
|
|
2746
2907
|
return options.adminKey;
|
|
2747
2908
|
}
|
|
@@ -3100,6 +3261,157 @@ var registerAuthCommands = (program) => {
|
|
|
3100
3261
|
});
|
|
3101
3262
|
};
|
|
3102
3263
|
|
|
3264
|
+
// src/commands/config.ts
|
|
3265
|
+
var KEY_ALIASES = {
|
|
3266
|
+
"base-url": "baseUrl",
|
|
3267
|
+
base_url: "baseUrl",
|
|
3268
|
+
token: "token",
|
|
3269
|
+
"admin-key": "adminKey",
|
|
3270
|
+
admin_key: "adminKey",
|
|
3271
|
+
"timeout-ms": "timeoutMs",
|
|
3272
|
+
timeout_ms: "timeoutMs",
|
|
3273
|
+
retries: "retries"
|
|
3274
|
+
};
|
|
3275
|
+
var VALID_SET_KEYS = "base-url|token|admin-key|timeout-ms|retries";
|
|
3276
|
+
var attachCommandPath = (error, commandPath) => {
|
|
3277
|
+
if (!error || typeof error !== "object") {
|
|
3278
|
+
return;
|
|
3279
|
+
}
|
|
3280
|
+
const tagged = error;
|
|
3281
|
+
if (!tagged.commandPath) {
|
|
3282
|
+
tagged.commandPath = commandPath;
|
|
3283
|
+
}
|
|
3284
|
+
};
|
|
3285
|
+
var resolvePretty = (command) => {
|
|
3286
|
+
const raw = command.optsWithGlobals();
|
|
3287
|
+
return Boolean(raw.pretty);
|
|
3288
|
+
};
|
|
3289
|
+
var maskSecret = (value) => {
|
|
3290
|
+
if (!value) {
|
|
3291
|
+
return null;
|
|
3292
|
+
}
|
|
3293
|
+
const trimmed = value.trim();
|
|
3294
|
+
if (trimmed.length === 0) {
|
|
3295
|
+
return null;
|
|
3296
|
+
}
|
|
3297
|
+
if (trimmed.length <= 8) {
|
|
3298
|
+
return "***";
|
|
3299
|
+
}
|
|
3300
|
+
return `${trimmed.slice(0, 4)}...${trimmed.slice(-4)}`;
|
|
3301
|
+
};
|
|
3302
|
+
var toConfigOutput = (path, exists, values) => {
|
|
3303
|
+
return {
|
|
3304
|
+
path,
|
|
3305
|
+
exists,
|
|
3306
|
+
configured: {
|
|
3307
|
+
baseUrl: values.baseUrl ?? null,
|
|
3308
|
+
token: maskSecret(values.token),
|
|
3309
|
+
tokenConfigured: Boolean(values.token),
|
|
3310
|
+
adminKey: maskSecret(values.adminKey),
|
|
3311
|
+
adminKeyConfigured: Boolean(values.adminKey),
|
|
3312
|
+
timeoutMs: values.timeoutMs ?? null,
|
|
3313
|
+
retries: values.retries ?? null
|
|
3314
|
+
},
|
|
3315
|
+
effective: {
|
|
3316
|
+
baseUrl: values.baseUrl ?? CLI_DEFAULT_BASE_URL,
|
|
3317
|
+
tokenConfigured: Boolean(values.token),
|
|
3318
|
+
adminKeyConfigured: Boolean(values.adminKey),
|
|
3319
|
+
timeoutMs: values.timeoutMs ?? CLI_DEFAULT_TIMEOUT_MS,
|
|
3320
|
+
retries: values.retries ?? CLI_DEFAULT_RETRIES
|
|
3321
|
+
}
|
|
3322
|
+
};
|
|
3323
|
+
};
|
|
3324
|
+
var parseSetKey = (raw) => {
|
|
3325
|
+
const normalized = raw.trim().toLowerCase();
|
|
3326
|
+
const key = KEY_ALIASES[normalized];
|
|
3327
|
+
if (!key) {
|
|
3328
|
+
throw new CliValidationError(
|
|
3329
|
+
`invalid config key '${raw}': expected one of ${VALID_SET_KEYS}`
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3332
|
+
return key;
|
|
3333
|
+
};
|
|
3334
|
+
var parseUnsetKey = (raw) => {
|
|
3335
|
+
const normalized = raw.trim().toLowerCase();
|
|
3336
|
+
if (normalized === "all") {
|
|
3337
|
+
return "all";
|
|
3338
|
+
}
|
|
3339
|
+
return parseSetKey(raw);
|
|
3340
|
+
};
|
|
3341
|
+
var parseSetValue = (key, rawValue) => {
|
|
3342
|
+
switch (key) {
|
|
3343
|
+
case "baseUrl":
|
|
3344
|
+
return ensureHttpUrl(rawValue, "<value>");
|
|
3345
|
+
case "token":
|
|
3346
|
+
return ensureNonEmpty(rawValue, "<value>");
|
|
3347
|
+
case "adminKey":
|
|
3348
|
+
return ensureNonEmpty(rawValue, "<value>");
|
|
3349
|
+
case "timeoutMs":
|
|
3350
|
+
return ensurePositiveInteger(rawValue, "<value>");
|
|
3351
|
+
case "retries":
|
|
3352
|
+
return ensureNonNegativeInteger(rawValue, "<value>");
|
|
3353
|
+
default: {
|
|
3354
|
+
const exhaustive = key;
|
|
3355
|
+
return exhaustive;
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
};
|
|
3359
|
+
var registerConfigCommands = (program) => {
|
|
3360
|
+
const config = program.command("config").description("Manage global CLI runtime configuration");
|
|
3361
|
+
config.command("show").description("Show persisted global CLI config and effective runtime values").action(function() {
|
|
3362
|
+
try {
|
|
3363
|
+
const snapshot = loadCliPersistedConfig();
|
|
3364
|
+
printJson(
|
|
3365
|
+
{
|
|
3366
|
+
ok: true,
|
|
3367
|
+
...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
|
|
3368
|
+
},
|
|
3369
|
+
resolvePretty(this)
|
|
3370
|
+
);
|
|
3371
|
+
} catch (error) {
|
|
3372
|
+
attachCommandPath(error, "config show");
|
|
3373
|
+
throw error;
|
|
3374
|
+
}
|
|
3375
|
+
});
|
|
3376
|
+
config.command("set").description("Persist one global CLI setting (supports *_ aliases)").argument("<key>", `setting key (${VALID_SET_KEYS})`).argument("<value>", "setting value").action(function(rawKey, rawValue) {
|
|
3377
|
+
try {
|
|
3378
|
+
const key = parseSetKey(rawKey);
|
|
3379
|
+
const value = parseSetValue(key, rawValue);
|
|
3380
|
+
const snapshot = setCliPersistedConfigValue(key, value);
|
|
3381
|
+
printJson(
|
|
3382
|
+
{
|
|
3383
|
+
ok: true,
|
|
3384
|
+
action: "set",
|
|
3385
|
+
key,
|
|
3386
|
+
...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
|
|
3387
|
+
},
|
|
3388
|
+
resolvePretty(this)
|
|
3389
|
+
);
|
|
3390
|
+
} catch (error) {
|
|
3391
|
+
attachCommandPath(error, "config set");
|
|
3392
|
+
throw error;
|
|
3393
|
+
}
|
|
3394
|
+
});
|
|
3395
|
+
config.command("unset").description("Remove one persisted key or clear all keys").argument("<key>", "setting key (base-url|token|admin-key|timeout-ms|retries|all)").action(function(rawKey) {
|
|
3396
|
+
try {
|
|
3397
|
+
const key = parseUnsetKey(rawKey);
|
|
3398
|
+
const snapshot = key === "all" ? clearCliPersistedConfig() : unsetCliPersistedConfigKeys([key]);
|
|
3399
|
+
printJson(
|
|
3400
|
+
{
|
|
3401
|
+
ok: true,
|
|
3402
|
+
action: "unset",
|
|
3403
|
+
key,
|
|
3404
|
+
...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
|
|
3405
|
+
},
|
|
3406
|
+
resolvePretty(this)
|
|
3407
|
+
);
|
|
3408
|
+
} catch (error) {
|
|
3409
|
+
attachCommandPath(error, "config unset");
|
|
3410
|
+
throw error;
|
|
3411
|
+
}
|
|
3412
|
+
});
|
|
3413
|
+
};
|
|
3414
|
+
|
|
3103
3415
|
// src/commands/cycles.ts
|
|
3104
3416
|
var registerCycleCommands = (program) => {
|
|
3105
3417
|
const cycles = program.command("cycles").description("Cycle and settlement visibility commands");
|
|
@@ -3352,12 +3664,6 @@ var registerTaskCommands = (program) => {
|
|
|
3352
3664
|
};
|
|
3353
3665
|
|
|
3354
3666
|
// src/program.ts
|
|
3355
|
-
var cliRuntime = loadCliRuntimeConfig();
|
|
3356
|
-
var DEFAULT_BASE_URL = cliRuntime.apiBaseUrl;
|
|
3357
|
-
var DEFAULT_TOKEN = cliRuntime.token;
|
|
3358
|
-
var DEFAULT_ADMIN_KEY = cliRuntime.adminServiceKey;
|
|
3359
|
-
var DEFAULT_TIMEOUT_MS2 = cliRuntime.timeoutMs;
|
|
3360
|
-
var DEFAULT_RETRIES2 = cliRuntime.retries;
|
|
3361
3667
|
var GLOBAL_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
3362
3668
|
"--base-url",
|
|
3363
3669
|
"--token",
|
|
@@ -3367,12 +3673,21 @@ var GLOBAL_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
|
3367
3673
|
]);
|
|
3368
3674
|
var GLOBAL_BOOLEAN_OPTIONS = /* @__PURE__ */ new Set(["--pretty"]);
|
|
3369
3675
|
var HELP_APPENDIX = `
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3676
|
+
CLI runtime setting precedence:
|
|
3677
|
+
1) command flags
|
|
3678
|
+
2) global config file (agentrade config set/show/unset)
|
|
3679
|
+
3) built-in defaults
|
|
3680
|
+
|
|
3681
|
+
Global config file path:
|
|
3682
|
+
$AGENTRADE_CLI_CONFIG_PATH
|
|
3683
|
+
or $XDG_CONFIG_HOME/agentrade/config.json
|
|
3684
|
+
or ~/.agentrade/config.json
|
|
3685
|
+
|
|
3686
|
+
Built-in defaults:
|
|
3687
|
+
--base-url (default: ${CLI_DEFAULT_BASE_URL})
|
|
3688
|
+
--timeout-ms (default: ${CLI_DEFAULT_TIMEOUT_MS})
|
|
3689
|
+
--retries (default: ${CLI_DEFAULT_RETRIES})
|
|
3690
|
+
--token / --admin-key remain optional unless required by command auth mode
|
|
3376
3691
|
|
|
3377
3692
|
Output contract:
|
|
3378
3693
|
success: stdout JSON
|
|
@@ -3411,10 +3726,11 @@ var detectCommandFromArgv = (argv) => {
|
|
|
3411
3726
|
};
|
|
3412
3727
|
var buildProgram = () => {
|
|
3413
3728
|
const program = new Command();
|
|
3414
|
-
program.name("agentrade").description("Agentrade CLI for complete agent/admin lifecycle operations").version("0.1.
|
|
3729
|
+
program.name("agentrade").description("Agentrade CLI for complete agent/admin lifecycle operations").version("0.1.2").option("--base-url <url>", "API base URL").option("--token <token>", "bearer token for authenticated routes").option("--admin-key <key>", "admin service key for admin routes").option("--timeout-ms <ms>", "request timeout in milliseconds").option("--retries <count>", "retry count for network/429/5xx errors").option("--pretty", "pretty-print JSON output", false).showHelpAfterError(false).configureOutput({
|
|
3415
3730
|
writeErr: () => void 0
|
|
3416
3731
|
}).addHelpText("after", HELP_APPENDIX).exitOverride();
|
|
3417
3732
|
registerAuthCommands(program);
|
|
3733
|
+
registerConfigCommands(program);
|
|
3418
3734
|
registerSystemCommands(program);
|
|
3419
3735
|
registerTaskCommands(program);
|
|
3420
3736
|
registerSubmissionCommands(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentrade/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agentrade": "dist/index.js"
|
|
@@ -11,28 +11,27 @@
|
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"clean": "rm -rf dist",
|
|
16
|
-
"dev": "tsx src/index.ts",
|
|
17
|
-
"build": "tsup --config tsup.config.ts",
|
|
18
|
-
"prepublishOnly": "pnpm run build",
|
|
19
|
-
"test": "tsx --test test/**/*.test.ts",
|
|
20
|
-
"test:persistence": "tsx --test --test-concurrency=1 test/persistence.stress.test.ts",
|
|
21
|
-
"lint": "tsc -p tsconfig.json --noEmit"
|
|
22
|
-
},
|
|
23
14
|
"dependencies": {
|
|
24
15
|
"commander": "^13.1.0",
|
|
25
16
|
"viem": "^2.23.5",
|
|
26
17
|
"zod": "^3.24.2"
|
|
27
18
|
},
|
|
28
19
|
"devDependencies": {
|
|
29
|
-
"@agentrade/config": "workspace:*",
|
|
30
|
-
"@agentrade/contracts": "workspace:*",
|
|
31
|
-
"@agentrade/sdk": "workspace:*",
|
|
32
|
-
"@agentrade/types": "workspace:*",
|
|
33
20
|
"@types/node": "^22.13.10",
|
|
34
21
|
"tsup": "^8.2.4",
|
|
35
22
|
"tsx": "^4.19.3",
|
|
36
|
-
"typescript": "^5.7.3"
|
|
23
|
+
"typescript": "^5.7.3",
|
|
24
|
+
"@agentrade/config": "0.1.0",
|
|
25
|
+
"@agentrade/sdk": "0.1.0",
|
|
26
|
+
"@agentrade/contracts": "0.1.0",
|
|
27
|
+
"@agentrade/types": "0.1.0"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"clean": "rm -rf dist",
|
|
31
|
+
"dev": "tsx src/index.ts",
|
|
32
|
+
"build": "tsup --config tsup.config.ts",
|
|
33
|
+
"test": "tsx --test test/**/*.test.ts",
|
|
34
|
+
"test:persistence": "tsx --test --test-concurrency=1 test/persistence.stress.test.ts",
|
|
35
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
37
36
|
}
|
|
38
|
-
}
|
|
37
|
+
}
|