@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.
Files changed (3) hide show
  1. package/LICENSE +22 -0
  2. package/dist/index.js +415 -99
  3. 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((resolve) => setTimeout(resolve, ms));
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 resolveGlobalOptions = (command) => {
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 = normalizeOptional(raw.baseUrl);
2708
- if (!rawBaseUrl) {
2709
- throw new CliConfigError("--base-url is required");
2710
- }
2711
- const baseUrl = ensureHttpUrl(rawBaseUrl, "--base-url");
2712
- const timeoutMs = typeof raw.timeoutMs === "number" ? raw.timeoutMs : ensurePositiveInteger(String(raw.timeoutMs ?? "10000"), "--timeout-ms");
2713
- const retries = typeof raw.retries === "number" ? raw.retries : ensureNonNegativeInteger(String(raw.retries ?? "1"), "--retries");
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(raw.token),
2717
- adminKey: normalizeOptional(raw.adminKey),
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 or AGENTRADE_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 or AGENTRADE_ADMIN_SERVICE_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
- Environment variable fallbacks:
3371
- AGENTRADE_API_BASE_URL
3372
- AGENTRADE_TOKEN
3373
- AGENTRADE_ADMIN_SERVICE_KEY
3374
- AGENTRADE_TIMEOUT_MS
3375
- AGENTRADE_RETRIES
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.1").option("--base-url <url>", "API base URL", DEFAULT_BASE_URL).option("--token <token>", "bearer token for authenticated routes", DEFAULT_TOKEN).option("--admin-key <key>", "admin service key for admin routes", DEFAULT_ADMIN_KEY).option("--timeout-ms <ms>", "request timeout in milliseconds", DEFAULT_TIMEOUT_MS2).option("--retries <count>", "retry count for network/429/5xx errors", DEFAULT_RETRIES2).option("--pretty", "pretty-print JSON output", false).showHelpAfterError(false).configureOutput({
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.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
+ }