@agentrade/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.
Files changed (2) hide show
  1. package/dist/index.js +887 -285
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,164 +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
- // src/operation-bindings.ts
80
- var cliOperationBindings = {
81
- "activities list": "activitiesListV2",
82
- "admin bridge export": "adminBridgeExportV2",
83
- "admin cycles close": "adminCloseCycleV2",
84
- "admin disputes override": "adminOverrideDisputeV2",
85
- "agents list": "agentsListV2",
86
- "agents profile get": "agentsGetProfileV2",
87
- "agents profile update": "agentsUpdateProfileV2",
88
- "agents stats": "agentsGetStatsV2",
89
- "auth challenge": "authChallengeV2",
90
- "auth verify": "authVerifyV2",
91
- "cycles active": "cyclesGetActiveV2",
92
- "cycles get": "cyclesGetV2",
93
- "cycles list": "cyclesListV2",
94
- "cycles rewards": "cyclesGetRewardsV2",
95
- "dashboard summary": "dashboardSummaryV2",
96
- "dashboard trends": "dashboardTrendsV2",
97
- "disputes get": "disputesGetV2",
98
- "disputes list": "disputesListV2",
99
- "disputes open": "disputesOpenV2",
100
- "disputes vote": "disputesVoteV2",
101
- "economy params": "economyGetParamsV2",
102
- "ledger get": "ledgerGetV2",
103
- "submissions get": "submissionsGetV2",
104
- "submissions list": "submissionsListV2",
105
- "submissions confirm": "submissionsConfirmV2",
106
- "submissions reject": "submissionsRejectV2",
107
- "system health": "systemHealthV2",
108
- "tasks create": "tasksCreateV2",
109
- "tasks get": "tasksGetV2",
110
- "tasks intend": "tasksAddIntentionV2",
111
- "tasks intentions": "tasksListIntentionsV2",
112
- "tasks list": "tasksListV2",
113
- "tasks submit": "tasksSubmitV2",
114
- "tasks terminate": "tasksTerminateV2"
115
- };
116
-
117
- // src/text-input.ts
118
- import { readFileSync } from "fs";
119
-
120
- // src/errors.ts
121
- var CliValidationError = class extends Error {
122
- constructor(message) {
123
- super(message);
124
- this.name = "CliValidationError";
125
- }
126
- };
127
- var CliConfigError = class extends Error {
128
- constructor(message) {
129
- super(message);
130
- this.name = "CliConfigError";
131
- }
132
- };
133
-
134
- // src/text-input.ts
135
- var resolveTextInput = (options) => {
136
- const { inlineValue, filePath, fieldName, required = true, allowEmpty = false } = options;
137
- if (inlineValue !== void 0 && filePath !== void 0) {
138
- throw new CliValidationError(`--${fieldName} and --${fieldName}-file are mutually exclusive`);
139
- }
140
- let value;
141
- if (filePath !== void 0) {
142
- try {
143
- value = readFileSync(filePath, "utf8");
144
- } catch (error) {
145
- throw new CliValidationError(
146
- `failed to read --${fieldName}-file: ${error instanceof Error ? error.message : String(error)}`
147
- );
148
- }
149
- } else {
150
- value = inlineValue;
151
- }
152
- if (value === void 0) {
153
- if (required) {
154
- throw new CliValidationError(`--${fieldName} or --${fieldName}-file is required`);
155
- }
156
- return void 0;
157
- }
158
- if (!allowEmpty && value.trim().length === 0) {
159
- throw new CliValidationError(`--${fieldName} must be non-empty`);
160
- }
161
- return value;
162
- };
163
-
164
6
  // ../../packages/types/src/index.ts
165
7
  var TaskStatus = /* @__PURE__ */ ((TaskStatus2) => {
166
8
  TaskStatus2["OPEN"] = "OPEN";
@@ -198,12 +40,85 @@ var ActivityEventType = /* @__PURE__ */ ((ActivityEventType2) => {
198
40
  ActivityEventType2["TASK_COMPLETED"] = "TASK_COMPLETED";
199
41
  ActivityEventType2["DISPUTE_OPENED"] = "DISPUTE_OPENED";
200
42
  ActivityEventType2["TASK_TERMINATED"] = "TASK_TERMINATED";
43
+ ActivityEventType2["ADMIN_AUDIT"] = "ADMIN_AUDIT";
201
44
  return ActivityEventType2;
202
45
  })(ActivityEventType || {});
203
46
 
47
+ // src/errors.ts
48
+ var CliValidationError = class extends Error {
49
+ constructor(message) {
50
+ super(message);
51
+ this.name = "CliValidationError";
52
+ }
53
+ };
54
+ var CliConfigError = class extends Error {
55
+ constructor(message) {
56
+ super(message);
57
+ this.name = "CliConfigError";
58
+ }
59
+ };
60
+
61
+ // src/operation-bindings.ts
62
+ var cliOperationBindings = {
63
+ "activities list": "activitiesListV2",
64
+ "agents list": "agentsListV2",
65
+ "agents profile get": "agentsGetProfileV2",
66
+ "agents profile update": "agentsUpdateProfileV2",
67
+ "agents stats": "agentsGetStatsV2",
68
+ "auth challenge": "authChallengeV2",
69
+ "auth verify": "authVerifyV2",
70
+ "cycles active": "cyclesGetActiveV2",
71
+ "cycles get": "cyclesGetV2",
72
+ "cycles list": "cyclesListV2",
73
+ "cycles rewards": "cyclesGetRewardsV2",
74
+ "dashboard summary": "dashboardSummaryV2",
75
+ "dashboard trends": "dashboardTrendsV2",
76
+ "disputes get": "disputesGetV2",
77
+ "disputes list": "disputesListV2",
78
+ "disputes open": "disputesOpenV2",
79
+ "disputes vote": "disputesVoteV2",
80
+ "economy params": "economyGetParamsV2",
81
+ "ledger get": "ledgerGetV2",
82
+ "submissions get": "submissionsGetV2",
83
+ "submissions list": "submissionsListV2",
84
+ "submissions confirm": "submissionsConfirmV2",
85
+ "submissions reject": "submissionsRejectV2",
86
+ "system health": "systemHealthV2",
87
+ "system metrics": "systemMetricsV2",
88
+ "system settings get": "systemSettingsGetV2",
89
+ "system settings history": "systemSettingsHistoryV2",
90
+ "system settings reset": "systemSettingsResetV2",
91
+ "system settings update": "systemSettingsUpdateV2",
92
+ "tasks create": "tasksCreateV2",
93
+ "tasks get": "tasksGetV2",
94
+ "tasks intend": "tasksAddIntentionV2",
95
+ "tasks intentions": "tasksListIntentionsV2",
96
+ "tasks list": "tasksListV2",
97
+ "tasks submit": "tasksSubmitV2",
98
+ "tasks terminate": "tasksTerminateV2"
99
+ };
100
+
204
101
  // src/validators.ts
205
102
  var ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
206
103
  var ISO_DATETIME_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
104
+ var RUNTIME_EDITABLE_KEYS = /* @__PURE__ */ new Set([
105
+ "cycleDurationHours",
106
+ "mintPerCycle",
107
+ "taxRateBps",
108
+ "taskCompletionPublisherWorkload",
109
+ "taskCompletionWorkerWorkload",
110
+ "disputeQuorum",
111
+ "disputeApprovalBps",
112
+ "terminationPenaltyBps",
113
+ "submissionTimeoutHours",
114
+ "resubmitCooldownMinutes",
115
+ "reputationWeightPublisherBps",
116
+ "reputationWeightWorkerBps",
117
+ "reputationWeightSupervisorBps",
118
+ "scoreWeightReputationBps",
119
+ "scoreWeightCompletionBps",
120
+ "scoreWeightQualityBps"
121
+ ]);
207
122
  var parseInteger = (raw, flag) => {
208
123
  if (!/^[-]?\d+$/.test(raw.trim())) {
209
124
  throw new CliValidationError(`${flag} must be an integer`);
@@ -286,23 +201,37 @@ var ensureVoteChoice = (raw) => {
286
201
  }
287
202
  return normalized;
288
203
  };
289
- var ensureOverrideResult = (raw) => {
290
- const normalized = raw.trim().toUpperCase();
291
- if (normalized !== "COMPLETED" && normalized !== "NOT_COMPLETED") {
292
- throw new CliValidationError("--result must be COMPLETED or NOT_COMPLETED");
204
+ var ensureRuntimeSettingsApplyTo = (raw, flag = "--apply-to") => {
205
+ const normalized = raw.trim().toLowerCase();
206
+ if (normalized !== "current" && normalized !== "next") {
207
+ throw new CliValidationError(`${flag} must be current or next`);
293
208
  }
294
209
  return normalized;
295
210
  };
296
- var parseOptionalAddressList = (raw, flag) => {
297
- if (!raw || raw.trim().length === 0) {
298
- return void 0;
211
+ var ensureRuntimeSettingsPatchJson = (raw, flag = "--patch-json") => {
212
+ let parsed;
213
+ try {
214
+ parsed = JSON.parse(raw);
215
+ } catch {
216
+ throw new CliValidationError(`${flag} must be a valid JSON object`);
299
217
  }
300
- const values = raw.split(/[\s,]+/).map((item) => item.trim()).filter((item) => item.length > 0);
301
- if (values.length === 0) {
302
- return void 0;
218
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
219
+ throw new CliValidationError(`${flag} must be a JSON object`);
303
220
  }
304
- const unique = [...new Set(values)];
305
- return unique.map((value) => ensureAddress(value, flag));
221
+ const patch = {};
222
+ for (const [key, value] of Object.entries(parsed)) {
223
+ if (!RUNTIME_EDITABLE_KEYS.has(key)) {
224
+ throw new CliValidationError(`${flag} contains unsupported key: ${key}`);
225
+ }
226
+ if (typeof value !== "number" || !Number.isFinite(value)) {
227
+ throw new CliValidationError(`${flag}.${key} must be a finite number`);
228
+ }
229
+ patch[key] = value;
230
+ }
231
+ if (Object.keys(patch).length === 0) {
232
+ throw new CliValidationError(`${flag} must include at least one editable rule`);
233
+ }
234
+ return patch;
306
235
  };
307
236
 
308
237
  // ../../packages/contracts/src/schemas.ts
@@ -1275,6 +1204,7 @@ var publicEconomyParamsSchema = defineSchema(
1275
1204
  rewardMin: z.number().int(),
1276
1205
  initialAgentBalance: z.number().int(),
1277
1206
  mintPerCycle: z.number().int(),
1207
+ cycleDurationHours: z.number().int(),
1278
1208
  terminationPenaltyBps: z.number().int(),
1279
1209
  submissionTimeoutHours: z.number().int(),
1280
1210
  resubmitCooldownMinutes: z.number().int(),
@@ -1316,6 +1246,7 @@ var publicEconomyParamsSchema = defineSchema(
1316
1246
  "rewardMin",
1317
1247
  "initialAgentBalance",
1318
1248
  "mintPerCycle",
1249
+ "cycleDurationHours",
1319
1250
  "terminationPenaltyBps",
1320
1251
  "submissionTimeoutHours",
1321
1252
  "resubmitCooldownMinutes",
@@ -1354,6 +1285,7 @@ var publicEconomyParamsSchema = defineSchema(
1354
1285
  rewardMin: { ...integerField },
1355
1286
  initialAgentBalance: { ...integerField },
1356
1287
  mintPerCycle: { ...integerField },
1288
+ cycleDurationHours: { ...integerField },
1357
1289
  terminationPenaltyBps: { ...integerField },
1358
1290
  submissionTimeoutHours: { ...integerField },
1359
1291
  resubmitCooldownMinutes: { ...integerField },
@@ -1373,6 +1305,212 @@ var publicEconomyParamsSchema = defineSchema(
1373
1305
  }
1374
1306
  }
1375
1307
  );
1308
+ var runtimeEditableRulesSchema = defineSchema(
1309
+ "RuntimeEditableRules",
1310
+ z.object({
1311
+ cycleDurationHours: z.number().int(),
1312
+ mintPerCycle: z.number().int(),
1313
+ taxRateBps: z.number().int(),
1314
+ taskCompletionPublisherWorkload: z.number(),
1315
+ taskCompletionWorkerWorkload: z.number(),
1316
+ disputeQuorum: z.number().int(),
1317
+ disputeApprovalBps: z.number().int(),
1318
+ terminationPenaltyBps: z.number().int(),
1319
+ submissionTimeoutHours: z.number().int(),
1320
+ resubmitCooldownMinutes: z.number().int(),
1321
+ reputationWeightPublisherBps: z.number().int(),
1322
+ reputationWeightWorkerBps: z.number().int(),
1323
+ reputationWeightSupervisorBps: z.number().int(),
1324
+ scoreWeightReputationBps: z.number().int(),
1325
+ scoreWeightCompletionBps: z.number().int(),
1326
+ scoreWeightQualityBps: z.number().int()
1327
+ }),
1328
+ {
1329
+ type: "object",
1330
+ additionalProperties: false,
1331
+ required: [
1332
+ "cycleDurationHours",
1333
+ "mintPerCycle",
1334
+ "taxRateBps",
1335
+ "taskCompletionPublisherWorkload",
1336
+ "taskCompletionWorkerWorkload",
1337
+ "disputeQuorum",
1338
+ "disputeApprovalBps",
1339
+ "terminationPenaltyBps",
1340
+ "submissionTimeoutHours",
1341
+ "resubmitCooldownMinutes",
1342
+ "reputationWeightPublisherBps",
1343
+ "reputationWeightWorkerBps",
1344
+ "reputationWeightSupervisorBps",
1345
+ "scoreWeightReputationBps",
1346
+ "scoreWeightCompletionBps",
1347
+ "scoreWeightQualityBps"
1348
+ ],
1349
+ properties: {
1350
+ cycleDurationHours: { ...integerField },
1351
+ mintPerCycle: { ...integerField },
1352
+ taxRateBps: { ...integerField },
1353
+ taskCompletionPublisherWorkload: { ...numberField },
1354
+ taskCompletionWorkerWorkload: { ...numberField },
1355
+ disputeQuorum: { ...integerField },
1356
+ disputeApprovalBps: { ...integerField },
1357
+ terminationPenaltyBps: { ...integerField },
1358
+ submissionTimeoutHours: { ...integerField },
1359
+ resubmitCooldownMinutes: { ...integerField },
1360
+ reputationWeightPublisherBps: { ...integerField },
1361
+ reputationWeightWorkerBps: { ...integerField },
1362
+ reputationWeightSupervisorBps: { ...integerField },
1363
+ scoreWeightReputationBps: { ...integerField },
1364
+ scoreWeightCompletionBps: { ...integerField },
1365
+ scoreWeightQualityBps: { ...integerField }
1366
+ }
1367
+ }
1368
+ );
1369
+ var runtimeEditableRulesPatchSchema = defineSchema(
1370
+ "RuntimeEditableRulesPatch",
1371
+ runtimeEditableRulesSchema.schema.partial(),
1372
+ {
1373
+ type: "object",
1374
+ additionalProperties: false,
1375
+ properties: {
1376
+ cycleDurationHours: { ...integerField },
1377
+ mintPerCycle: { ...integerField },
1378
+ taxRateBps: { ...integerField },
1379
+ taskCompletionPublisherWorkload: { ...numberField },
1380
+ taskCompletionWorkerWorkload: { ...numberField },
1381
+ disputeQuorum: { ...integerField },
1382
+ disputeApprovalBps: { ...integerField },
1383
+ terminationPenaltyBps: { ...integerField },
1384
+ submissionTimeoutHours: { ...integerField },
1385
+ resubmitCooldownMinutes: { ...integerField },
1386
+ reputationWeightPublisherBps: { ...integerField },
1387
+ reputationWeightWorkerBps: { ...integerField },
1388
+ reputationWeightSupervisorBps: { ...integerField },
1389
+ scoreWeightReputationBps: { ...integerField },
1390
+ scoreWeightCompletionBps: { ...integerField },
1391
+ scoreWeightQualityBps: { ...integerField }
1392
+ }
1393
+ }
1394
+ );
1395
+ var runtimeSettingsStateSchema = defineSchema(
1396
+ "RuntimeSettingsState",
1397
+ z.object({
1398
+ currentRules: runtimeEditableRulesSchema.schema,
1399
+ pendingNextPatch: runtimeEditableRulesPatchSchema.schema.nullable(),
1400
+ nextRules: runtimeEditableRulesSchema.schema,
1401
+ updatedAt: isoDateSchema
1402
+ }),
1403
+ {
1404
+ type: "object",
1405
+ additionalProperties: false,
1406
+ required: ["currentRules", "pendingNextPatch", "nextRules", "updatedAt"],
1407
+ properties: {
1408
+ currentRules: schemaRef(runtimeEditableRulesSchema),
1409
+ pendingNextPatch: { ...schemaRef(runtimeEditableRulesPatchSchema), nullable: true },
1410
+ nextRules: schemaRef(runtimeEditableRulesSchema),
1411
+ updatedAt: { ...isoDateField }
1412
+ }
1413
+ }
1414
+ );
1415
+ var runtimeSettingsUpdateRequestSchema = defineSchema(
1416
+ "RuntimeSettingsUpdateRequest",
1417
+ z.object({
1418
+ applyTo: z.enum(["current", "next"]),
1419
+ patch: runtimeEditableRulesPatchSchema.schema.refine(
1420
+ (value) => Object.keys(value).length > 0,
1421
+ "patch must contain at least one editable rule"
1422
+ ),
1423
+ reason: z.string().trim().min(1).max(1e3).optional()
1424
+ }),
1425
+ {
1426
+ type: "object",
1427
+ additionalProperties: false,
1428
+ required: ["applyTo", "patch"],
1429
+ properties: {
1430
+ applyTo: { type: "string", enum: ["current", "next"] },
1431
+ patch: schemaRef(runtimeEditableRulesPatchSchema),
1432
+ reason: { ...stringField, minLength: 1, maxLength: 1e3 }
1433
+ }
1434
+ }
1435
+ );
1436
+ var runtimeSettingsResetRequestSchema = defineSchema(
1437
+ "RuntimeSettingsResetRequest",
1438
+ z.object({
1439
+ applyTo: z.enum(["current", "next"]),
1440
+ reason: z.string().trim().min(1).max(1e3).optional()
1441
+ }),
1442
+ {
1443
+ type: "object",
1444
+ additionalProperties: false,
1445
+ required: ["applyTo"],
1446
+ properties: {
1447
+ applyTo: { type: "string", enum: ["current", "next"] },
1448
+ reason: { ...stringField, minLength: 1, maxLength: 1e3 }
1449
+ }
1450
+ }
1451
+ );
1452
+ var runtimeRuleAuditRecordSchema = defineSchema(
1453
+ "RuntimeRuleAuditRecord",
1454
+ z.object({
1455
+ id: z.string(),
1456
+ eventType: z.enum(["UPDATE", "RESET", "AUTO_APPLY_NEXT"]),
1457
+ applyTo: z.enum(["current", "next"]).nullable(),
1458
+ reason: z.string().nullable(),
1459
+ actor: z.string().nullable(),
1460
+ cycleId: z.string().nullable(),
1461
+ beforeRules: runtimeEditableRulesSchema.schema.nullable(),
1462
+ afterRules: runtimeEditableRulesSchema.schema.nullable(),
1463
+ patch: runtimeEditableRulesPatchSchema.schema.nullable(),
1464
+ pendingNextPatch: runtimeEditableRulesPatchSchema.schema.nullable(),
1465
+ createdAt: isoDateSchema
1466
+ }),
1467
+ {
1468
+ type: "object",
1469
+ additionalProperties: false,
1470
+ required: [
1471
+ "id",
1472
+ "eventType",
1473
+ "applyTo",
1474
+ "reason",
1475
+ "actor",
1476
+ "cycleId",
1477
+ "beforeRules",
1478
+ "afterRules",
1479
+ "patch",
1480
+ "pendingNextPatch",
1481
+ "createdAt"
1482
+ ],
1483
+ properties: {
1484
+ id: { ...stringField },
1485
+ eventType: { type: "string", enum: ["UPDATE", "RESET", "AUTO_APPLY_NEXT"] },
1486
+ applyTo: { type: "string", enum: ["current", "next"], nullable: true },
1487
+ reason: { ...stringField, nullable: true },
1488
+ actor: { ...stringField, nullable: true },
1489
+ cycleId: { ...stringField, nullable: true },
1490
+ beforeRules: { ...schemaRef(runtimeEditableRulesSchema), nullable: true },
1491
+ afterRules: { ...schemaRef(runtimeEditableRulesSchema), nullable: true },
1492
+ patch: { ...schemaRef(runtimeEditableRulesPatchSchema), nullable: true },
1493
+ pendingNextPatch: { ...schemaRef(runtimeEditableRulesPatchSchema), nullable: true },
1494
+ createdAt: { ...isoDateField }
1495
+ }
1496
+ }
1497
+ );
1498
+ var paginatedRuntimeRuleAuditResponseSchema = defineSchema(
1499
+ "PaginatedRuntimeRuleAuditResponse",
1500
+ z.object({
1501
+ items: z.array(runtimeRuleAuditRecordSchema.schema),
1502
+ nextCursor: z.string().nullable()
1503
+ }),
1504
+ {
1505
+ type: "object",
1506
+ additionalProperties: false,
1507
+ required: ["items", "nextCursor"],
1508
+ properties: {
1509
+ items: { type: "array", items: schemaRef(runtimeRuleAuditRecordSchema) },
1510
+ nextCursor: { type: "string", nullable: true }
1511
+ }
1512
+ }
1513
+ );
1376
1514
  var createTaskRequestSchema = defineSchema(
1377
1515
  "CreateTaskRequest",
1378
1516
  z.object({
@@ -1602,6 +1740,10 @@ var cycleListQuerySchemaV2 = z.object({
1602
1740
  cursor: z.string().optional(),
1603
1741
  limit: z.coerce.number().int().min(1).max(100).default(20)
1604
1742
  });
1743
+ var runtimeRuleAuditHistoryQuerySchemaV2 = z.object({
1744
+ cursor: z.string().optional(),
1745
+ limit: z.coerce.number().int().min(1).max(100).default(20)
1746
+ });
1605
1747
  var idPathSchema = z.object({
1606
1748
  id: nonEmptyStringSchema
1607
1749
  });
@@ -1649,6 +1791,13 @@ var namedSchemas = [
1649
1791
  bridgeExportItemSchema,
1650
1792
  bridgeExportResponseSchema,
1651
1793
  publicEconomyParamsSchema,
1794
+ runtimeEditableRulesSchema,
1795
+ runtimeEditableRulesPatchSchema,
1796
+ runtimeSettingsStateSchema,
1797
+ runtimeSettingsUpdateRequestSchema,
1798
+ runtimeSettingsResetRequestSchema,
1799
+ runtimeRuleAuditRecordSchema,
1800
+ paginatedRuntimeRuleAuditResponseSchema,
1652
1801
  createTaskRequestSchema,
1653
1802
  submitTaskRequestSchema,
1654
1803
  openDisputeRequestSchema,
@@ -1817,6 +1966,7 @@ var dashboardTrendParameters = [
1817
1966
  queryStringParam("window", { type: "string", enum: ["7d", "30d"], default: "7d" }, { en: "Trend window", zh: "\u8D8B\u52BF\u7A97\u53E3" })
1818
1967
  ];
1819
1968
  var cycleListParametersV2 = [queryCursorParam, queryLimitParam];
1969
+ var runtimeRuleHistoryParametersV2 = [queryCursorParam, queryLimitParam];
1820
1970
  var apiOperations = [
1821
1971
  defineOperationSpec({
1822
1972
  baseOperationId: "systemHealth",
@@ -1833,13 +1983,63 @@ var apiOperations = [
1833
1983
  baseOperationId: "systemMetrics",
1834
1984
  method: "GET",
1835
1985
  tag: "System",
1836
- auth: "admin",
1986
+ auth: "bearer",
1837
1987
  summary: { en: "Get service metrics", zh: "\u8BFB\u53D6\u670D\u52A1\u6307\u6807" },
1838
1988
  pathTemplate: "/v2/system/metrics",
1839
1989
  responseSchema: serviceMetricsResponseSchema.schema,
1840
1990
  responseComponent: serviceMetricsResponseSchema,
1841
1991
  errorStatuses: [401, 500]
1842
1992
  }),
1993
+ defineOperationSpec({
1994
+ baseOperationId: "systemSettingsGet",
1995
+ method: "GET",
1996
+ tag: "System",
1997
+ auth: "bearer",
1998
+ summary: { en: "Get runtime settings", zh: "\u8BFB\u53D6\u8FD0\u884C\u89C4\u5219\u8BBE\u7F6E" },
1999
+ pathTemplate: "/v2/system/settings",
2000
+ responseSchema: runtimeSettingsStateSchema.schema,
2001
+ responseComponent: runtimeSettingsStateSchema,
2002
+ errorStatuses: [401, 500]
2003
+ }),
2004
+ defineOperationSpec({
2005
+ baseOperationId: "systemSettingsUpdate",
2006
+ method: "PATCH",
2007
+ tag: "System",
2008
+ auth: "bearer_admin",
2009
+ summary: { en: "Update runtime settings", zh: "\u66F4\u65B0\u8FD0\u884C\u89C4\u5219\u8BBE\u7F6E" },
2010
+ pathTemplate: "/v2/system/settings",
2011
+ bodySchema: runtimeSettingsUpdateRequestSchema.schema,
2012
+ requestBodyComponent: runtimeSettingsUpdateRequestSchema,
2013
+ responseSchema: runtimeSettingsStateSchema.schema,
2014
+ responseComponent: runtimeSettingsStateSchema,
2015
+ errorStatuses: [400, 401, 500]
2016
+ }),
2017
+ defineOperationSpec({
2018
+ baseOperationId: "systemSettingsReset",
2019
+ method: "POST",
2020
+ tag: "System",
2021
+ auth: "bearer_admin",
2022
+ summary: { en: "Reset runtime settings", zh: "\u91CD\u7F6E\u8FD0\u884C\u89C4\u5219\u8BBE\u7F6E" },
2023
+ pathTemplate: "/v2/system/settings/reset",
2024
+ bodySchema: runtimeSettingsResetRequestSchema.schema,
2025
+ requestBodyComponent: runtimeSettingsResetRequestSchema,
2026
+ responseSchema: runtimeSettingsStateSchema.schema,
2027
+ responseComponent: runtimeSettingsStateSchema,
2028
+ errorStatuses: [400, 401, 500]
2029
+ }),
2030
+ defineOperationSpec({
2031
+ baseOperationId: "systemSettingsHistory",
2032
+ method: "GET",
2033
+ tag: "System",
2034
+ auth: "bearer",
2035
+ summary: { en: "List runtime settings history", zh: "\u8BFB\u53D6\u8FD0\u884C\u89C4\u5219\u53D8\u66F4\u5386\u53F2" },
2036
+ pathTemplate: "/v2/system/settings/history",
2037
+ querySchema: runtimeRuleAuditHistoryQuerySchemaV2,
2038
+ responseSchema: paginatedRuntimeRuleAuditResponseSchema.schema,
2039
+ responseComponent: paginatedRuntimeRuleAuditResponseSchema,
2040
+ parameters: runtimeRuleHistoryParametersV2,
2041
+ errorStatuses: [401, 500]
2042
+ }),
1843
2043
  defineOperationSpec({
1844
2044
  baseOperationId: "authChallenge",
1845
2045
  method: "POST",
@@ -2232,49 +2432,6 @@ var apiOperations = [
2232
2432
  responseSchema: publicEconomyParamsSchema.schema,
2233
2433
  responseComponent: publicEconomyParamsSchema,
2234
2434
  errorStatuses: [500]
2235
- }),
2236
- defineOperationSpec({
2237
- baseOperationId: "adminCloseCycle",
2238
- method: "POST",
2239
- tag: "Admin",
2240
- auth: "admin",
2241
- summary: { en: "Close current cycle", zh: "\u5173\u95ED\u5F53\u524D\u5468\u671F" },
2242
- pathTemplate: "/v2/admin/cycles/close",
2243
- responseSchema: closeCycleResultSchema.schema,
2244
- responseComponent: closeCycleResultSchema,
2245
- errorStatuses: [401, 409, 500]
2246
- }),
2247
- defineOperationSpec({
2248
- baseOperationId: "adminOverrideDispute",
2249
- method: "POST",
2250
- tag: "Admin",
2251
- auth: "admin",
2252
- summary: { en: "Override dispute", zh: "\u7BA1\u7406\u5458\u8986\u76D6\u4E89\u8BAE\u7ED3\u679C" },
2253
- description: {
2254
- en: "NOT_COMPLETED reopens dispute to OPEN. If another OPEN dispute already exists for the same submission, returns 409 OPEN_DISPUTE_ALREADY_EXISTS.",
2255
- zh: "NOT_COMPLETED \u4F1A\u5C06\u4E89\u8BAE\u91CD\u5F00\u4E3A OPEN\u3002\u82E5\u540C\u4E00 submission \u5DF2\u5B58\u5728\u5176\u4ED6 OPEN \u4E89\u8BAE\uFF0C\u5219\u8FD4\u56DE 409 OPEN_DISPUTE_ALREADY_EXISTS\u3002"
2256
- },
2257
- pathTemplate: "/v2/admin/disputes/{id}/override",
2258
- pathParamsSchema: idPathSchema,
2259
- bodySchema: overrideDisputeRequestSchema.schema,
2260
- requestBodyComponent: overrideDisputeRequestSchema,
2261
- responseSchema: disputeSchema.schema,
2262
- responseComponent: disputeSchema,
2263
- parameters: [pathStringParam("id", { en: "Dispute id", zh: "\u4E89\u8BAE id" })],
2264
- errorStatuses: [401, 404, 409, 500]
2265
- }),
2266
- defineOperationSpec({
2267
- baseOperationId: "adminBridgeExport",
2268
- method: "POST",
2269
- tag: "Admin",
2270
- auth: "admin",
2271
- summary: { en: "Export bridge batch", zh: "\u5BFC\u51FA\u6865\u63A5\u6279\u6B21" },
2272
- pathTemplate: "/v2/admin/bridge/export",
2273
- bodySchema: bridgeExportRequestSchema.schema,
2274
- requestBodyComponent: bridgeExportRequestSchema,
2275
- responseSchema: bridgeExportResponseSchema.schema,
2276
- responseComponent: bridgeExportResponseSchema,
2277
- errorStatuses: [400, 401, 500]
2278
2435
  })
2279
2436
  ];
2280
2437
  var supportedApiVersions = [...new Set(apiOperations.map((operation) => operation.version))];
@@ -2331,7 +2488,7 @@ var ApiClientError = class extends Error {
2331
2488
  var DEFAULT_TIMEOUT_MS = 1e4;
2332
2489
  var DEFAULT_RETRIES = 1;
2333
2490
  var sleep = async (ms) => {
2334
- await new Promise((resolve) => setTimeout(resolve, ms));
2491
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
2335
2492
  };
2336
2493
  var shouldRetryStatus = (status) => status === 429 || status >= 500;
2337
2494
  var retryDelayMs = (attempt) => Math.min(1e3, 100 * 2 ** (attempt - 1));
@@ -2420,13 +2577,21 @@ var AgentradeApiClient = class {
2420
2577
  }
2421
2578
  return { authorization: `Bearer ${this.token}` };
2422
2579
  }
2423
- if (auth === "admin") {
2580
+ if (auth === "bearer_admin") {
2581
+ if (!this.token) {
2582
+ throw new ApiClientError("missing bearer token for authenticated request", {
2583
+ apiError: "MISSING_BEARER_TOKEN"
2584
+ });
2585
+ }
2424
2586
  if (!this.adminKey) {
2425
- throw new ApiClientError("missing admin service key for admin request", {
2587
+ throw new ApiClientError("missing admin service key for admin-authenticated request", {
2426
2588
  apiError: "MISSING_ADMIN_KEY"
2427
2589
  });
2428
2590
  }
2429
- return { "x-admin-service-key": this.adminKey };
2591
+ return {
2592
+ authorization: `Bearer ${this.token}`,
2593
+ "x-admin-service-key": this.adminKey
2594
+ };
2430
2595
  }
2431
2596
  return {};
2432
2597
  }
@@ -2670,20 +2835,254 @@ var AgentradeApiClient = class {
2670
2835
  getEconomyParams() {
2671
2836
  return this.requestOperation("economyGetParamsV2");
2672
2837
  }
2673
- closeCurrentCycleAdmin() {
2674
- return this.requestOperation("adminCloseCycleV2");
2838
+ getRuntimeSettings() {
2839
+ return this.requestOperation("systemSettingsGetV2");
2675
2840
  }
2676
- overrideDisputeAdmin(disputeId, payload) {
2677
- return this.requestOperation("adminOverrideDisputeV2", {
2678
- pathParams: { id: disputeId },
2841
+ updateRuntimeSettings(payload) {
2842
+ return this.requestOperation("systemSettingsUpdateV2", {
2679
2843
  body: payload
2680
2844
  });
2681
2845
  }
2682
- exportBridgeBatchAdmin(payload = {}) {
2683
- return this.requestOperation("adminBridgeExportV2", {
2846
+ resetRuntimeSettings(payload) {
2847
+ return this.requestOperation("systemSettingsResetV2", {
2684
2848
  body: payload
2685
2849
  });
2686
2850
  }
2851
+ getRuntimeSettingsHistory(params) {
2852
+ return this.requestOperation(
2853
+ "systemSettingsHistoryV2",
2854
+ {
2855
+ query: params
2856
+ }
2857
+ );
2858
+ }
2859
+ };
2860
+
2861
+ // src/cli-config.ts
2862
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
2863
+ import { homedir } from "os";
2864
+ import { dirname, isAbsolute, join, resolve } from "path";
2865
+ var CLI_DEFAULT_BASE_URL = "https://agentrade.info/api";
2866
+ var CLI_DEFAULT_TIMEOUT_MS = 1e4;
2867
+ var CLI_DEFAULT_RETRIES = 1;
2868
+ var configError = (path, message) => new CliConfigError(`invalid CLI config at ${path}: ${message}`);
2869
+ var parseOptionalString = (raw, path, field) => {
2870
+ if (raw === void 0 || raw === null) {
2871
+ return void 0;
2872
+ }
2873
+ if (typeof raw !== "string") {
2874
+ throw configError(path, `${field} must be a string`);
2875
+ }
2876
+ const value = raw.trim();
2877
+ return value.length > 0 ? value : void 0;
2878
+ };
2879
+ var parseOptionalInteger = (raw, path, field) => {
2880
+ if (raw === void 0 || raw === null) {
2881
+ return void 0;
2882
+ }
2883
+ if (typeof raw === "number") {
2884
+ if (!Number.isSafeInteger(raw)) {
2885
+ throw configError(path, `${field} must be a safe integer`);
2886
+ }
2887
+ return raw;
2888
+ }
2889
+ if (typeof raw !== "string") {
2890
+ throw configError(path, `${field} must be an integer`);
2891
+ }
2892
+ const value = raw.trim();
2893
+ if (value.length === 0) {
2894
+ return void 0;
2895
+ }
2896
+ if (!/^-?\d+$/.test(value)) {
2897
+ throw configError(path, `${field} must be an integer`);
2898
+ }
2899
+ const parsed = Number(value);
2900
+ if (!Number.isSafeInteger(parsed)) {
2901
+ throw configError(path, `${field} must be a safe integer`);
2902
+ }
2903
+ return parsed;
2904
+ };
2905
+ var parseCliPersistedConfig = (raw, path) => {
2906
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
2907
+ throw configError(path, "root value must be a JSON object");
2908
+ }
2909
+ const input = raw;
2910
+ const parsed = {};
2911
+ const baseUrl = parseOptionalString(input.baseUrl, path, "baseUrl");
2912
+ const token = parseOptionalString(input.token, path, "token");
2913
+ const adminKey = parseOptionalString(input.adminKey, path, "adminKey");
2914
+ const timeoutMs = parseOptionalInteger(input.timeoutMs, path, "timeoutMs");
2915
+ const retries = parseOptionalInteger(input.retries, path, "retries");
2916
+ if (baseUrl !== void 0) {
2917
+ let parsedUrl;
2918
+ try {
2919
+ parsedUrl = new URL(baseUrl);
2920
+ } catch {
2921
+ throw configError(path, "baseUrl must be a valid URL");
2922
+ }
2923
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
2924
+ throw configError(path, "baseUrl must start with http:// or https://");
2925
+ }
2926
+ parsed.baseUrl = baseUrl;
2927
+ }
2928
+ if (token !== void 0) {
2929
+ parsed.token = token;
2930
+ }
2931
+ if (adminKey !== void 0) {
2932
+ parsed.adminKey = adminKey;
2933
+ }
2934
+ if (timeoutMs !== void 0) {
2935
+ if (timeoutMs <= 0) {
2936
+ throw configError(path, "timeoutMs must be > 0");
2937
+ }
2938
+ parsed.timeoutMs = timeoutMs;
2939
+ }
2940
+ if (retries !== void 0) {
2941
+ if (retries < 0) {
2942
+ throw configError(path, "retries must be >= 0");
2943
+ }
2944
+ parsed.retries = retries;
2945
+ }
2946
+ return parsed;
2947
+ };
2948
+ var normalizeConfigForWrite = (values, path) => {
2949
+ const normalized = parseCliPersistedConfig(values, path);
2950
+ const ordered = {};
2951
+ if (normalized.baseUrl !== void 0) {
2952
+ ordered.baseUrl = normalized.baseUrl;
2953
+ }
2954
+ if (normalized.token !== void 0) {
2955
+ ordered.token = normalized.token;
2956
+ }
2957
+ if (normalized.adminKey !== void 0) {
2958
+ ordered.adminKey = normalized.adminKey;
2959
+ }
2960
+ if (normalized.timeoutMs !== void 0) {
2961
+ ordered.timeoutMs = normalized.timeoutMs;
2962
+ }
2963
+ if (normalized.retries !== void 0) {
2964
+ ordered.retries = normalized.retries;
2965
+ }
2966
+ return ordered;
2967
+ };
2968
+ var writeCliPersistedConfig = (path, values) => {
2969
+ const normalized = normalizeConfigForWrite(values, path);
2970
+ if (Object.keys(normalized).length === 0) {
2971
+ if (existsSync(path)) {
2972
+ unlinkSync(path);
2973
+ }
2974
+ return {
2975
+ path,
2976
+ exists: false,
2977
+ values: {}
2978
+ };
2979
+ }
2980
+ mkdirSync(dirname(path), { recursive: true, mode: 448 });
2981
+ writeFileSync(path, `${JSON.stringify(normalized, null, 2)}
2982
+ `, {
2983
+ encoding: "utf8",
2984
+ mode: 384
2985
+ });
2986
+ return {
2987
+ path,
2988
+ exists: true,
2989
+ values: normalized
2990
+ };
2991
+ };
2992
+ var resolveCliConfigPath = () => {
2993
+ const explicit = process.env.AGENTRADE_CLI_CONFIG_PATH;
2994
+ if (explicit !== void 0) {
2995
+ const value = explicit.trim();
2996
+ if (value.length === 0) {
2997
+ throw new CliConfigError("AGENTRADE_CLI_CONFIG_PATH must be non-empty when set");
2998
+ }
2999
+ return isAbsolute(value) ? value : resolve(value);
3000
+ }
3001
+ const xdgBase = process.env.XDG_CONFIG_HOME?.trim();
3002
+ if (xdgBase) {
3003
+ return join(xdgBase, "agentrade", "config.json");
3004
+ }
3005
+ const home = homedir().trim();
3006
+ if (home.length === 0) {
3007
+ throw new CliConfigError("unable to resolve home directory for CLI config");
3008
+ }
3009
+ return join(home, ".agentrade", "config.json");
3010
+ };
3011
+ var loadCliPersistedConfig = () => {
3012
+ const path = resolveCliConfigPath();
3013
+ if (!existsSync(path)) {
3014
+ return {
3015
+ path,
3016
+ exists: false,
3017
+ values: {}
3018
+ };
3019
+ }
3020
+ let rawText;
3021
+ try {
3022
+ rawText = readFileSync(path, "utf8");
3023
+ } catch (error) {
3024
+ throw new CliConfigError(
3025
+ `unable to read CLI config at ${path}: ${error instanceof Error ? error.message : String(error)}`
3026
+ );
3027
+ }
3028
+ if (rawText.trim().length === 0) {
3029
+ return {
3030
+ path,
3031
+ exists: true,
3032
+ values: {}
3033
+ };
3034
+ }
3035
+ let parsed;
3036
+ try {
3037
+ parsed = JSON.parse(rawText);
3038
+ } catch (error) {
3039
+ throw new CliConfigError(
3040
+ `invalid CLI config JSON at ${path}: ${error instanceof Error ? error.message : String(error)}`
3041
+ );
3042
+ }
3043
+ return {
3044
+ path,
3045
+ exists: true,
3046
+ values: parseCliPersistedConfig(parsed, path)
3047
+ };
3048
+ };
3049
+ var setCliPersistedConfigValue = (key, value) => {
3050
+ const current = loadCliPersistedConfig();
3051
+ const next = { ...current.values };
3052
+ switch (key) {
3053
+ case "baseUrl":
3054
+ next.baseUrl = String(value);
3055
+ break;
3056
+ case "token":
3057
+ next.token = String(value);
3058
+ break;
3059
+ case "adminKey":
3060
+ next.adminKey = String(value);
3061
+ break;
3062
+ case "timeoutMs":
3063
+ next.timeoutMs = Number(value);
3064
+ break;
3065
+ case "retries":
3066
+ next.retries = Number(value);
3067
+ break;
3068
+ default: {
3069
+ const exhaustive = key;
3070
+ throw new CliConfigError(`unsupported CLI config key: ${String(exhaustive)}`);
3071
+ }
3072
+ }
3073
+ return writeCliPersistedConfig(current.path, next);
3074
+ };
3075
+ var unsetCliPersistedConfigKeys = (keys) => {
3076
+ const current = loadCliPersistedConfig();
3077
+ const next = { ...current.values };
3078
+ for (const key of keys) {
3079
+ delete next[key];
3080
+ }
3081
+ return writeCliPersistedConfig(current.path, next);
3082
+ };
3083
+ var clearCliPersistedConfig = () => {
3084
+ const current = loadCliPersistedConfig();
3085
+ return writeCliPersistedConfig(current.path, {});
2687
3086
  };
2688
3087
 
2689
3088
  // src/context.ts
@@ -2702,19 +3101,26 @@ var normalizeOptional = (value) => {
2702
3101
  }
2703
3102
  return value.trim().length > 0 ? value : void 0;
2704
3103
  };
2705
- var resolveGlobalOptions = (command) => {
3104
+ var parsePositiveInteger = (value, flag) => {
3105
+ return ensurePositiveInteger(String(value), flag);
3106
+ };
3107
+ var parseNonNegativeInteger = (value, flag) => {
3108
+ return ensureNonNegativeInteger(String(value), flag);
3109
+ };
3110
+ var resolveGlobalOptions = (command, persistedConfig = loadCliPersistedConfig().values) => {
2706
3111
  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");
3112
+ const rawBaseUrl = raw.baseUrl === void 0 ? persistedConfig.baseUrl : String(raw.baseUrl);
3113
+ const baseUrl = ensureHttpUrl(rawBaseUrl ?? CLI_DEFAULT_BASE_URL, "--base-url");
3114
+ const rawToken = raw.token === void 0 ? persistedConfig.token : String(raw.token);
3115
+ const rawAdminKey = raw.adminKey === void 0 ? persistedConfig.adminKey : String(raw.adminKey);
3116
+ const rawTimeoutMs = raw.timeoutMs === void 0 ? persistedConfig.timeoutMs ?? CLI_DEFAULT_TIMEOUT_MS : raw.timeoutMs;
3117
+ const timeoutMs = parsePositiveInteger(rawTimeoutMs, "--timeout-ms");
3118
+ const rawRetries = raw.retries === void 0 ? persistedConfig.retries ?? CLI_DEFAULT_RETRIES : raw.retries;
3119
+ const retries = parseNonNegativeInteger(rawRetries, "--retries");
2714
3120
  return {
2715
3121
  baseUrl,
2716
- token: normalizeOptional(raw.token),
2717
- adminKey: normalizeOptional(raw.adminKey),
3122
+ token: normalizeOptional(rawToken),
3123
+ adminKey: normalizeOptional(rawAdminKey),
2718
3124
  timeoutMs,
2719
3125
  retries,
2720
3126
  pretty: Boolean(raw.pretty)
@@ -2735,13 +3141,13 @@ var createCommandContext = (command) => {
2735
3141
  client,
2736
3142
  requireToken: () => {
2737
3143
  if (!options.token) {
2738
- throw new CliConfigError("missing token: use --token or AGENTRADE_TOKEN");
3144
+ throw new CliConfigError("missing token: use --token");
2739
3145
  }
2740
3146
  return options.token;
2741
3147
  },
2742
3148
  requireAdminKey: () => {
2743
3149
  if (!options.adminKey) {
2744
- throw new CliConfigError("missing admin key: use --admin-key or AGENTRADE_ADMIN_SERVICE_KEY");
3150
+ throw new CliConfigError("missing admin key: use --admin-key");
2745
3151
  }
2746
3152
  return options.adminKey;
2747
3153
  }
@@ -2905,46 +3311,13 @@ var executeBearerOperationCommand = async (command, operationId, buildInput) =>
2905
3311
  };
2906
3312
  var executeAdminOperationCommand = async (command, operationId, buildInput) => {
2907
3313
  await executeJsonCommand(command, async (ctx) => {
3314
+ ctx.requireToken();
2908
3315
  ctx.requireAdminKey();
2909
3316
  const input = buildInput ? await buildInput(ctx) : {};
2910
3317
  return ctx.client.requestOperation(operationId, input);
2911
3318
  });
2912
3319
  };
2913
3320
 
2914
- // src/commands/admin.ts
2915
- var registerAdminCommands = (program) => {
2916
- const admin = program.command("admin").description("Admin-only commands");
2917
- const adminCycles = admin.command("cycles").description("Cycle admin commands");
2918
- adminCycles.command("close").description("Close current cycle").action(async (_options, command) => {
2919
- await executeAdminOperationCommand(command, cliOperationBindings["admin cycles close"]);
2920
- });
2921
- const adminDisputes = admin.command("disputes").description("Dispute admin commands");
2922
- adminDisputes.command("override").description("Override dispute result").requiredOption("--dispute <id>", "dispute id").requiredOption("--result <result>", "COMPLETED or NOT_COMPLETED").action(async (options, command) => {
2923
- await executeAdminOperationCommand(command, cliOperationBindings["admin disputes override"], async () => ({
2924
- pathParams: { id: ensureNonEmpty(String(options.dispute), "--dispute") },
2925
- body: {
2926
- result: ensureOverrideResult(String(options.result))
2927
- }
2928
- }));
2929
- });
2930
- const adminBridge = admin.command("bridge").description("Bridge export commands");
2931
- adminBridge.command("export").description("Export bridge balances").option("--addresses <list>", "comma or whitespace separated addresses").option("--addresses-file <path>", "file containing comma or whitespace separated addresses").action(async (options, command) => {
2932
- await executeAdminOperationCommand(command, cliOperationBindings["admin bridge export"], async () => {
2933
- const rawAddresses = resolveTextInput({
2934
- inlineValue: options.addresses,
2935
- filePath: options.addressesFile,
2936
- fieldName: "addresses",
2937
- required: false,
2938
- allowEmpty: true
2939
- });
2940
- const addresses = parseOptionalAddressList(rawAddresses, "--addresses");
2941
- return {
2942
- body: addresses ? { addresses } : {}
2943
- };
2944
- });
2945
- });
2946
- };
2947
-
2948
3321
  // src/commands/activities.ts
2949
3322
  var ensureActivityType = (raw) => {
2950
3323
  const normalized = raw.trim().toUpperCase();
@@ -2978,6 +3351,37 @@ var registerActivityCommands = (program) => {
2978
3351
  });
2979
3352
  };
2980
3353
 
3354
+ // src/text-input.ts
3355
+ import { readFileSync as readFileSync2 } from "fs";
3356
+ var resolveTextInput = (options) => {
3357
+ const { inlineValue, filePath, fieldName, required = true, allowEmpty = false } = options;
3358
+ if (inlineValue !== void 0 && filePath !== void 0) {
3359
+ throw new CliValidationError(`--${fieldName} and --${fieldName}-file are mutually exclusive`);
3360
+ }
3361
+ let value;
3362
+ if (filePath !== void 0) {
3363
+ try {
3364
+ value = readFileSync2(filePath, "utf8");
3365
+ } catch (error) {
3366
+ throw new CliValidationError(
3367
+ `failed to read --${fieldName}-file: ${error instanceof Error ? error.message : String(error)}`
3368
+ );
3369
+ }
3370
+ } else {
3371
+ value = inlineValue;
3372
+ }
3373
+ if (value === void 0) {
3374
+ if (required) {
3375
+ throw new CliValidationError(`--${fieldName} or --${fieldName}-file is required`);
3376
+ }
3377
+ return void 0;
3378
+ }
3379
+ if (!allowEmpty && value.trim().length === 0) {
3380
+ throw new CliValidationError(`--${fieldName} must be non-empty`);
3381
+ }
3382
+ return value;
3383
+ };
3384
+
2981
3385
  // src/commands/agents.ts
2982
3386
  var registerAgentCommands = (program) => {
2983
3387
  const agents = program.command("agents").description("Agent profile and stats commands");
@@ -3100,6 +3504,157 @@ var registerAuthCommands = (program) => {
3100
3504
  });
3101
3505
  };
3102
3506
 
3507
+ // src/commands/config.ts
3508
+ var KEY_ALIASES = {
3509
+ "base-url": "baseUrl",
3510
+ base_url: "baseUrl",
3511
+ token: "token",
3512
+ "admin-key": "adminKey",
3513
+ admin_key: "adminKey",
3514
+ "timeout-ms": "timeoutMs",
3515
+ timeout_ms: "timeoutMs",
3516
+ retries: "retries"
3517
+ };
3518
+ var VALID_SET_KEYS = "base-url|token|admin-key|timeout-ms|retries";
3519
+ var attachCommandPath = (error, commandPath) => {
3520
+ if (!error || typeof error !== "object") {
3521
+ return;
3522
+ }
3523
+ const tagged = error;
3524
+ if (!tagged.commandPath) {
3525
+ tagged.commandPath = commandPath;
3526
+ }
3527
+ };
3528
+ var resolvePretty = (command) => {
3529
+ const raw = command.optsWithGlobals();
3530
+ return Boolean(raw.pretty);
3531
+ };
3532
+ var maskSecret = (value) => {
3533
+ if (!value) {
3534
+ return null;
3535
+ }
3536
+ const trimmed = value.trim();
3537
+ if (trimmed.length === 0) {
3538
+ return null;
3539
+ }
3540
+ if (trimmed.length <= 8) {
3541
+ return "***";
3542
+ }
3543
+ return `${trimmed.slice(0, 4)}...${trimmed.slice(-4)}`;
3544
+ };
3545
+ var toConfigOutput = (path, exists, values) => {
3546
+ return {
3547
+ path,
3548
+ exists,
3549
+ configured: {
3550
+ baseUrl: values.baseUrl ?? null,
3551
+ token: maskSecret(values.token),
3552
+ tokenConfigured: Boolean(values.token),
3553
+ adminKey: maskSecret(values.adminKey),
3554
+ adminKeyConfigured: Boolean(values.adminKey),
3555
+ timeoutMs: values.timeoutMs ?? null,
3556
+ retries: values.retries ?? null
3557
+ },
3558
+ effective: {
3559
+ baseUrl: values.baseUrl ?? CLI_DEFAULT_BASE_URL,
3560
+ tokenConfigured: Boolean(values.token),
3561
+ adminKeyConfigured: Boolean(values.adminKey),
3562
+ timeoutMs: values.timeoutMs ?? CLI_DEFAULT_TIMEOUT_MS,
3563
+ retries: values.retries ?? CLI_DEFAULT_RETRIES
3564
+ }
3565
+ };
3566
+ };
3567
+ var parseSetKey = (raw) => {
3568
+ const normalized = raw.trim().toLowerCase();
3569
+ const key = KEY_ALIASES[normalized];
3570
+ if (!key) {
3571
+ throw new CliValidationError(
3572
+ `invalid config key '${raw}': expected one of ${VALID_SET_KEYS}`
3573
+ );
3574
+ }
3575
+ return key;
3576
+ };
3577
+ var parseUnsetKey = (raw) => {
3578
+ const normalized = raw.trim().toLowerCase();
3579
+ if (normalized === "all") {
3580
+ return "all";
3581
+ }
3582
+ return parseSetKey(raw);
3583
+ };
3584
+ var parseSetValue = (key, rawValue) => {
3585
+ switch (key) {
3586
+ case "baseUrl":
3587
+ return ensureHttpUrl(rawValue, "<value>");
3588
+ case "token":
3589
+ return ensureNonEmpty(rawValue, "<value>");
3590
+ case "adminKey":
3591
+ return ensureNonEmpty(rawValue, "<value>");
3592
+ case "timeoutMs":
3593
+ return ensurePositiveInteger(rawValue, "<value>");
3594
+ case "retries":
3595
+ return ensureNonNegativeInteger(rawValue, "<value>");
3596
+ default: {
3597
+ const exhaustive = key;
3598
+ return exhaustive;
3599
+ }
3600
+ }
3601
+ };
3602
+ var registerConfigCommands = (program) => {
3603
+ const config = program.command("config").description("Manage global CLI runtime configuration");
3604
+ config.command("show").description("Show persisted global CLI config and effective runtime values").action(function() {
3605
+ try {
3606
+ const snapshot = loadCliPersistedConfig();
3607
+ printJson(
3608
+ {
3609
+ ok: true,
3610
+ ...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
3611
+ },
3612
+ resolvePretty(this)
3613
+ );
3614
+ } catch (error) {
3615
+ attachCommandPath(error, "config show");
3616
+ throw error;
3617
+ }
3618
+ });
3619
+ 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) {
3620
+ try {
3621
+ const key = parseSetKey(rawKey);
3622
+ const value = parseSetValue(key, rawValue);
3623
+ const snapshot = setCliPersistedConfigValue(key, value);
3624
+ printJson(
3625
+ {
3626
+ ok: true,
3627
+ action: "set",
3628
+ key,
3629
+ ...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
3630
+ },
3631
+ resolvePretty(this)
3632
+ );
3633
+ } catch (error) {
3634
+ attachCommandPath(error, "config set");
3635
+ throw error;
3636
+ }
3637
+ });
3638
+ 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) {
3639
+ try {
3640
+ const key = parseUnsetKey(rawKey);
3641
+ const snapshot = key === "all" ? clearCliPersistedConfig() : unsetCliPersistedConfigKeys([key]);
3642
+ printJson(
3643
+ {
3644
+ ok: true,
3645
+ action: "unset",
3646
+ key,
3647
+ ...toConfigOutput(snapshot.path, snapshot.exists, snapshot.values)
3648
+ },
3649
+ resolvePretty(this)
3650
+ );
3651
+ } catch (error) {
3652
+ attachCommandPath(error, "config unset");
3653
+ throw error;
3654
+ }
3655
+ });
3656
+ };
3657
+
3103
3658
  // src/commands/cycles.ts
3104
3659
  var registerCycleCommands = (program) => {
3105
3660
  const cycles = program.command("cycles").description("Cycle and settlement visibility commands");
@@ -3266,6 +3821,50 @@ var registerSystemCommands = (program) => {
3266
3821
  system.command("health").description("Get API health status").action(async (_options, command) => {
3267
3822
  await executeOperationCommand(command, cliOperationBindings["system health"]);
3268
3823
  });
3824
+ system.command("metrics").description("Get API metrics (token required)").action(async (_options, command) => {
3825
+ await executeBearerOperationCommand(command, cliOperationBindings["system metrics"]);
3826
+ });
3827
+ const settings = system.command("settings").description("Runtime settings commands");
3828
+ settings.command("get").description("Get runtime settings").action(async (_options, command) => {
3829
+ await executeBearerOperationCommand(command, cliOperationBindings["system settings get"]);
3830
+ });
3831
+ settings.command("update").description("Update runtime settings patch").requiredOption("--apply-to <target>", "current or next").requiredOption("--patch-json <json>", "JSON patch object with editable runtime rule fields").option("--reason <reason>", "optional update reason").action(async (options, command) => {
3832
+ await executeAdminOperationCommand(
3833
+ command,
3834
+ cliOperationBindings["system settings update"],
3835
+ async () => ({
3836
+ body: {
3837
+ applyTo: ensureRuntimeSettingsApplyTo(String(options.applyTo), "--apply-to"),
3838
+ patch: ensureRuntimeSettingsPatchJson(String(options.patchJson), "--patch-json"),
3839
+ ...options.reason ? { reason: ensureNonEmpty(String(options.reason), "--reason") } : {}
3840
+ }
3841
+ })
3842
+ );
3843
+ });
3844
+ settings.command("reset").description("Reset runtime settings to environment defaults").requiredOption("--apply-to <target>", "current or next").option("--reason <reason>", "optional reset reason").action(async (options, command) => {
3845
+ await executeAdminOperationCommand(
3846
+ command,
3847
+ cliOperationBindings["system settings reset"],
3848
+ async () => ({
3849
+ body: {
3850
+ applyTo: ensureRuntimeSettingsApplyTo(String(options.applyTo), "--apply-to"),
3851
+ ...options.reason ? { reason: ensureNonEmpty(String(options.reason), "--reason") } : {}
3852
+ }
3853
+ })
3854
+ );
3855
+ });
3856
+ settings.command("history").description("List runtime settings audit history").option("--cursor <cursor>", "pagination cursor").option("--limit <n>", "page size (1-100)").action(async (options, command) => {
3857
+ await executeBearerOperationCommand(
3858
+ command,
3859
+ cliOperationBindings["system settings history"],
3860
+ async () => ({
3861
+ query: {
3862
+ ...options.cursor ? { cursor: ensureNonEmpty(String(options.cursor), "--cursor") } : {},
3863
+ ...options.limit ? { limit: ensurePositiveInteger(String(options.limit), "--limit") } : {}
3864
+ }
3865
+ })
3866
+ );
3867
+ });
3269
3868
  };
3270
3869
 
3271
3870
  // src/commands/tasks.ts
@@ -3352,12 +3951,6 @@ var registerTaskCommands = (program) => {
3352
3951
  };
3353
3952
 
3354
3953
  // 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
3954
  var GLOBAL_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set([
3362
3955
  "--base-url",
3363
3956
  "--token",
@@ -3367,12 +3960,21 @@ var GLOBAL_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set([
3367
3960
  ]);
3368
3961
  var GLOBAL_BOOLEAN_OPTIONS = /* @__PURE__ */ new Set(["--pretty"]);
3369
3962
  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
3963
+ CLI runtime setting precedence:
3964
+ 1) command flags
3965
+ 2) global config file (agentrade config set/show/unset)
3966
+ 3) built-in defaults
3967
+
3968
+ Global config file path:
3969
+ $AGENTRADE_CLI_CONFIG_PATH
3970
+ or $XDG_CONFIG_HOME/agentrade/config.json
3971
+ or ~/.agentrade/config.json
3972
+
3973
+ Built-in defaults:
3974
+ --base-url (default: ${CLI_DEFAULT_BASE_URL})
3975
+ --timeout-ms (default: ${CLI_DEFAULT_TIMEOUT_MS})
3976
+ --retries (default: ${CLI_DEFAULT_RETRIES})
3977
+ --token / --admin-key remain optional unless required by command auth mode
3376
3978
 
3377
3979
  Output contract:
3378
3980
  success: stdout JSON
@@ -3411,10 +4013,11 @@ var detectCommandFromArgv = (argv) => {
3411
4013
  };
3412
4014
  var buildProgram = () => {
3413
4015
  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({
4016
+ program.name("agentrade").description("Agentrade CLI for complete authenticated 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 privileged 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
4017
  writeErr: () => void 0
3416
4018
  }).addHelpText("after", HELP_APPENDIX).exitOverride();
3417
4019
  registerAuthCommands(program);
4020
+ registerConfigCommands(program);
3418
4021
  registerSystemCommands(program);
3419
4022
  registerTaskCommands(program);
3420
4023
  registerSubmissionCommands(program);
@@ -3425,7 +4028,6 @@ var buildProgram = () => {
3425
4028
  registerLedgerCommands(program);
3426
4029
  registerCycleCommands(program);
3427
4030
  registerEconomyCommands(program);
3428
- registerAdminCommands(program);
3429
4031
  return program;
3430
4032
  };
3431
4033
  var runCli = async (argv = process.argv) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrade/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "agentrade": "dist/index.js"