@lexq/cli 0.1.36 → 0.1.38
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/dist/index.js +296 -148
- package/dist/mcp/register.js +126 -77
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2183,13 +2183,141 @@ function resolveBody(opts) {
|
|
|
2183
2183
|
return {};
|
|
2184
2184
|
}
|
|
2185
2185
|
|
|
2186
|
-
// src/commands/
|
|
2186
|
+
// src/commands/profile.ts
|
|
2187
2187
|
import "commander";
|
|
2188
2188
|
import dedent9 from "dedent";
|
|
2189
|
+
|
|
2190
|
+
// src/types/enums.ts
|
|
2191
|
+
var ProfileCacheState = ["HIT", "MISS"];
|
|
2192
|
+
var FailureStatus = ["PENDING", "RESOLVED", "IGNORED"];
|
|
2193
|
+
var FailureAction = ["RETRY", "IGNORE", "RESOLVE"];
|
|
2194
|
+
var TaskCategory = ["INTEGRATION", "INTERNAL"];
|
|
2195
|
+
var TaskType = [
|
|
2196
|
+
// Integration
|
|
2197
|
+
"COUPON_ISSUE",
|
|
2198
|
+
"COUPON_CANCEL",
|
|
2199
|
+
"POINT_EARN",
|
|
2200
|
+
"POINT_USE",
|
|
2201
|
+
"POINT_REFUND",
|
|
2202
|
+
"NOTIFICATION_SEND",
|
|
2203
|
+
"CRM_SYNC_USER",
|
|
2204
|
+
"CRM_ADD_TAG",
|
|
2205
|
+
"WEBHOOK_EXECUTE",
|
|
2206
|
+
// Internal
|
|
2207
|
+
"IMAGE_PROCESSING",
|
|
2208
|
+
"DAILY_SETTLEMENT",
|
|
2209
|
+
"PLATFORM_WEBHOOK"
|
|
2210
|
+
];
|
|
2211
|
+
var PlatformEventType = [
|
|
2212
|
+
"VERSION_PUBLISHED",
|
|
2213
|
+
"DEPLOYED",
|
|
2214
|
+
"ROLLED_BACK",
|
|
2215
|
+
"UNDEPLOYED"
|
|
2216
|
+
];
|
|
2217
|
+
var WebhookPayloadFormat = ["GENERIC", "SLACK"];
|
|
2218
|
+
|
|
2219
|
+
// src/commands/profile.ts
|
|
2220
|
+
var ms = (nanos) => nanos == null ? "\u2013" : (nanos / 1e6).toFixed(2);
|
|
2221
|
+
var msWithUnit = (nanos) => nanos == null ? "\u2013" : `${(nanos / 1e6).toFixed(2)}ms`;
|
|
2222
|
+
function registerProfileCommands(program) {
|
|
2223
|
+
program.command("profile <groupId>").description("Per-rule latency profile with relative slow-rule flags").option("--rule <ruleId>", "Single-rule detail (distributions + 60s window series)").option("--version <versionId>", "Version to inspect (default: live version)").option("--from <instant>", "Window start, ISO-8601 instant (default: 24h ago)").option("--to <instant>", "Window end, ISO-8601 instant (default: now)").option("--cache <state>", "Cache dimension for the rule table: HIT | MISS (default: HIT)").addHelpText(
|
|
2224
|
+
"after",
|
|
2225
|
+
dedent9`
|
|
2226
|
+
|
|
2227
|
+
Slow-rule judgment is relative only: flagged = p50 ≥ 10× the median of
|
|
2228
|
+
per-rule p50s within the group. Absolute ms thresholds are intentionally
|
|
2229
|
+
not supported. Each percentile is withheld (–) unless n×(1−q) ≥ 3 —
|
|
2230
|
+
p50 from n ≥ 6, p95 from n ≥ 60, p99 from n ≥ 300. TOTAL is recorded
|
|
2231
|
+
on every call, rule detail from a deterministic 1% sample.
|
|
2232
|
+
|
|
2233
|
+
Examples:
|
|
2234
|
+
$ lexq profile <groupId>
|
|
2235
|
+
$ lexq profile <groupId> --cache MISS --from 2026-07-01T00:00:00Z
|
|
2236
|
+
$ lexq profile <groupId> --rule <ruleId> --version <versionId>
|
|
2237
|
+
`
|
|
2238
|
+
).action(async (groupId, opts) => {
|
|
2239
|
+
try {
|
|
2240
|
+
const globalOpts = program.opts();
|
|
2241
|
+
const format = globalOpts.format ?? "json";
|
|
2242
|
+
if (opts.cache && !ProfileCacheState.includes(opts.cache)) {
|
|
2243
|
+
throw new Error(`--cache must be one of: ${ProfileCacheState.join(" | ")}`);
|
|
2244
|
+
}
|
|
2245
|
+
const params = {};
|
|
2246
|
+
if (opts.version) params.versionId = opts.version;
|
|
2247
|
+
if (opts.from) params.from = opts.from;
|
|
2248
|
+
if (opts.to) params.to = opts.to;
|
|
2249
|
+
if (opts.cache) params.cacheState = opts.cache;
|
|
2250
|
+
const clientOpts = {
|
|
2251
|
+
apiKey: globalOpts.apiKey,
|
|
2252
|
+
baseUrl: globalOpts.baseUrl,
|
|
2253
|
+
dryRun: globalOpts.dryRun,
|
|
2254
|
+
verbose: globalOpts.verbose
|
|
2255
|
+
};
|
|
2256
|
+
if (opts.rule) {
|
|
2257
|
+
const data2 = await apiRequest(
|
|
2258
|
+
"GET",
|
|
2259
|
+
`policy-groups/${groupId}/profile/rules/${opts.rule}`,
|
|
2260
|
+
{ ...clientOpts, params }
|
|
2261
|
+
);
|
|
2262
|
+
if (format === "table") {
|
|
2263
|
+
console.error("note: --rule detail is nested; printing JSON (table not supported)");
|
|
2264
|
+
}
|
|
2265
|
+
printJson(data2);
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
const data = await apiRequest("GET", `policy-groups/${groupId}/profile`, {
|
|
2269
|
+
...clientOpts,
|
|
2270
|
+
params
|
|
2271
|
+
});
|
|
2272
|
+
if (format !== "table") {
|
|
2273
|
+
printJson(data);
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
console.log(`window : ${data.from} ~ ${data.to} (cache: ${data.ruleCacheState})`);
|
|
2277
|
+
console.log(`version : ${data.policyVersionId ?? "\u2013 (no live version)"}`);
|
|
2278
|
+
for (const s of data.summary) {
|
|
2279
|
+
const t = s.total;
|
|
2280
|
+
console.log(
|
|
2281
|
+
`TOTAL ${s.cacheState.padEnd(4)}: n=${t.n} p50=${msWithUnit(t.p50Nanos)} p95=${msWithUnit(t.p95Nanos)} p99=${msWithUnit(t.p99Nanos)}`
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
for (const b of data.baselines) {
|
|
2285
|
+
const base = b.status === "OK" ? `${msWithUnit(b.baselineP50Nanos)} (cohort ${b.cohortSize})` : `\u2013 (${b.status}, cohort ${b.cohortSize})`;
|
|
2286
|
+
console.log(`baseline ${b.phase.padEnd(9)}: ${base}`);
|
|
2287
|
+
}
|
|
2288
|
+
if (data.droppedRows > 0) {
|
|
2289
|
+
console.log(`\u26A0 droppedRows=${data.droppedRows} (corrupt histogram rows skipped)`);
|
|
2290
|
+
}
|
|
2291
|
+
printTable(
|
|
2292
|
+
["Rule", "Phase", "n", "p50(ms)", "p95(ms)", "p99(ms)", "\xD7base", "Flagged"],
|
|
2293
|
+
data.rules.flatMap(
|
|
2294
|
+
(rule) => rule.phases.map((p) => [
|
|
2295
|
+
rule.ruleId.substring(0, 12),
|
|
2296
|
+
p.phase,
|
|
2297
|
+
String(p.stats.n),
|
|
2298
|
+
ms(p.stats.p50Nanos),
|
|
2299
|
+
ms(p.stats.p95Nanos),
|
|
2300
|
+
ms(p.stats.p99Nanos),
|
|
2301
|
+
p.baselineMultiple == null ? "\u2013" : `${p.baselineMultiple.toFixed(1)}\xD7`,
|
|
2302
|
+
p.flagged ? "YES" : ""
|
|
2303
|
+
])
|
|
2304
|
+
),
|
|
2305
|
+
{ truncate: 24 }
|
|
2306
|
+
);
|
|
2307
|
+
} catch (error) {
|
|
2308
|
+
printError(error);
|
|
2309
|
+
process.exit(1);
|
|
2310
|
+
}
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
// src/commands/history.ts
|
|
2315
|
+
import "commander";
|
|
2316
|
+
import dedent10 from "dedent";
|
|
2189
2317
|
function registerHistoryCommands(program) {
|
|
2190
2318
|
const history = program.command("history").description("Execution history").addHelpText(
|
|
2191
2319
|
"after",
|
|
2192
|
-
|
|
2320
|
+
dedent10`
|
|
2193
2321
|
|
|
2194
2322
|
View and analyze policy execution logs from production traffic.
|
|
2195
2323
|
|
|
@@ -2203,7 +2331,7 @@ function registerHistoryCommands(program) {
|
|
|
2203
2331
|
);
|
|
2204
2332
|
history.command("list").description("List execution history").option("--trace-id <traceId>", "Filter by trace ID").option("--group-id <groupId>", "Filter by policy group").option("--version-id <versionId>", "Filter by version").option("--status <status>", "Filter by status (SUCCESS, NO_MATCH, ERROR, TIMEOUT)").option("--start-date <date>", "Start date (yyyy-MM-dd)").option("--end-date <date>", "End date (yyyy-MM-dd)").option("--page <number>", "Page number", "0").option("--size <number>", "Page size", "20").addHelpText(
|
|
2205
2333
|
"after",
|
|
2206
|
-
|
|
2334
|
+
dedent10`
|
|
2207
2335
|
|
|
2208
2336
|
Examples:
|
|
2209
2337
|
$ lexq history list --status ERROR --format table
|
|
@@ -2257,7 +2385,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2257
2385
|
});
|
|
2258
2386
|
history.command("get").description("Get execution detail").requiredOption("--id <traceId>", "Trace ID").addHelpText(
|
|
2259
2387
|
"after",
|
|
2260
|
-
|
|
2388
|
+
dedent10`
|
|
2261
2389
|
|
|
2262
2390
|
Returns the full execution detail including request facts, result traces,
|
|
2263
2391
|
and decision traces (SELECTED, NO_MATCH, BLOCKED, etc.).
|
|
@@ -2283,7 +2411,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2283
2411
|
});
|
|
2284
2412
|
history.command("stats").description("Get execution statistics").option("--group-id <groupId>", "Filter by policy group").option("--start-date <date>", "Start date (yyyy-MM-dd)").option("--end-date <date>", "End date (yyyy-MM-dd)").addHelpText(
|
|
2285
2413
|
"after",
|
|
2286
|
-
|
|
2414
|
+
dedent10`
|
|
2287
2415
|
|
|
2288
2416
|
Shows total executions, success/no-match/failure counts, success rate, and avg latency.
|
|
2289
2417
|
|
|
@@ -2332,11 +2460,11 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2332
2460
|
|
|
2333
2461
|
// src/commands/replay.ts
|
|
2334
2462
|
import "commander";
|
|
2335
|
-
import
|
|
2463
|
+
import dedent11 from "dedent";
|
|
2336
2464
|
function registerReplayCommands(program) {
|
|
2337
2465
|
const replay = program.command("replay").description("Decision Replay").addHelpText(
|
|
2338
2466
|
"after",
|
|
2339
|
-
|
|
2467
|
+
dedent11`
|
|
2340
2468
|
|
|
2341
2469
|
Re-evaluate past production executions against a candidate version.
|
|
2342
2470
|
|
|
@@ -2352,7 +2480,7 @@ function registerReplayCommands(program) {
|
|
|
2352
2480
|
);
|
|
2353
2481
|
replay.command("decision").description("Replay a single execution against a candidate version").requiredOption("--trace-id <traceId>", "Trace ID of the past execution").requiredOption("--version-id <versionId>", "Candidate version to re-evaluate against").addHelpText(
|
|
2354
2482
|
"after",
|
|
2355
|
-
|
|
2483
|
+
dedent11`
|
|
2356
2484
|
|
|
2357
2485
|
Free of charge (TPS throttle only). Returns decisionChanged, effect
|
|
2358
2486
|
changes, fired rules on both sides, and a determinism verdict.
|
|
@@ -2378,7 +2506,7 @@ function registerReplayCommands(program) {
|
|
|
2378
2506
|
});
|
|
2379
2507
|
replay.command("start").description("Submit a window replay job (blast radius)").requiredOption("--version-id <versionId>", "Candidate version to re-evaluate against").requiredOption("--from <date>", "Window start date (yyyy-MM-dd)").requiredOption("--to <date>", "Window end date (yyyy-MM-dd)").option("--max-records <number>", "Sample cap (hard cap 50k)").addHelpText(
|
|
2380
2508
|
"after",
|
|
2381
|
-
|
|
2509
|
+
dedent11`
|
|
2382
2510
|
|
|
2383
2511
|
Billed per replayed record (REPLAY metric). Poll with "lexq replay get".
|
|
2384
2512
|
|
|
@@ -2476,11 +2604,11 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2476
2604
|
|
|
2477
2605
|
// src/commands/provenance.ts
|
|
2478
2606
|
import "commander";
|
|
2479
|
-
import
|
|
2607
|
+
import dedent12 from "dedent";
|
|
2480
2608
|
function registerProvenanceCommands(program) {
|
|
2481
2609
|
const provenance = program.command("provenance").description("Decision Provenance").addHelpText(
|
|
2482
2610
|
"after",
|
|
2483
|
-
|
|
2611
|
+
dedent12`
|
|
2484
2612
|
|
|
2485
2613
|
Trace who authored, published, and deployed the rules behind a decision.
|
|
2486
2614
|
|
|
@@ -2506,7 +2634,7 @@ function registerProvenanceCommands(program) {
|
|
|
2506
2634
|
});
|
|
2507
2635
|
provenance.command("reveal-audits").description("List PII reveal audits (who revealed what, when)").option("--trace-id <traceId>", "Filter by trace ID (exact)").option("--fact-key <factKey>", "Filter by fact key (partial, case-insensitive)").option("--revealed-by <operatorId>", "Filter by operator ID (exact)").option("--start-date <date>", "Start date (yyyy-MM-dd)").option("--end-date <date>", "End date (yyyy-MM-dd)").option("--page <number>", "Page number", "0").option("--size <number>", "Page size", "20").addHelpText(
|
|
2508
2636
|
"after",
|
|
2509
|
-
|
|
2637
|
+
dedent12`
|
|
2510
2638
|
|
|
2511
2639
|
Metadata only — revealed values are never stored or returned.
|
|
2512
2640
|
|
|
@@ -2559,11 +2687,11 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2559
2687
|
|
|
2560
2688
|
// src/commands/integrations.ts
|
|
2561
2689
|
import "commander";
|
|
2562
|
-
import
|
|
2690
|
+
import dedent13 from "dedent";
|
|
2563
2691
|
function registerIntegrationCommands(program) {
|
|
2564
2692
|
const integrations = program.command("integrations").description("Manage external integrations").addHelpText(
|
|
2565
2693
|
"after",
|
|
2566
|
-
|
|
2694
|
+
dedent13`
|
|
2567
2695
|
|
|
2568
2696
|
Integrations connect rule actions to external services (webhooks, coupons,
|
|
2569
2697
|
points, notifications, CRM, messengers).
|
|
@@ -2633,7 +2761,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2633
2761
|
});
|
|
2634
2762
|
integrations.command("save").description("Create or update an integration").requiredOption("--json <body>", "Request body as JSON string").addHelpText(
|
|
2635
2763
|
"after",
|
|
2636
|
-
|
|
2764
|
+
dedent13`
|
|
2637
2765
|
|
|
2638
2766
|
Examples:
|
|
2639
2767
|
# Create
|
|
@@ -2683,7 +2811,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2683
2811
|
});
|
|
2684
2812
|
integrations.command("delete").description("Delete an integration").requiredOption("--id <integrationId>", "Integration ID").option("--force", "Skip confirmation prompt").addHelpText(
|
|
2685
2813
|
"after",
|
|
2686
|
-
|
|
2814
|
+
dedent13`
|
|
2687
2815
|
|
|
2688
2816
|
Rules referencing this integration will fail at execution time.
|
|
2689
2817
|
Use --force to skip confirmation.
|
|
@@ -2715,7 +2843,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2715
2843
|
});
|
|
2716
2844
|
integrations.command("config-spec").description("Get integration configuration field specs").addHelpText(
|
|
2717
2845
|
"after",
|
|
2718
|
-
|
|
2846
|
+
dedent13`
|
|
2719
2847
|
|
|
2720
2848
|
Shows required and optional configuration fields for each integration type.
|
|
2721
2849
|
|
|
@@ -2741,41 +2869,11 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2741
2869
|
|
|
2742
2870
|
// src/commands/logs.ts
|
|
2743
2871
|
import "commander";
|
|
2744
|
-
import
|
|
2745
|
-
|
|
2746
|
-
// src/types/enums.ts
|
|
2747
|
-
var FailureStatus = ["PENDING", "RESOLVED", "IGNORED"];
|
|
2748
|
-
var FailureAction = ["RETRY", "IGNORE", "RESOLVE"];
|
|
2749
|
-
var TaskCategory = ["INTEGRATION", "INTERNAL"];
|
|
2750
|
-
var TaskType = [
|
|
2751
|
-
// Integration
|
|
2752
|
-
"COUPON_ISSUE",
|
|
2753
|
-
"COUPON_CANCEL",
|
|
2754
|
-
"POINT_EARN",
|
|
2755
|
-
"POINT_USE",
|
|
2756
|
-
"POINT_REFUND",
|
|
2757
|
-
"NOTIFICATION_SEND",
|
|
2758
|
-
"CRM_SYNC_USER",
|
|
2759
|
-
"CRM_ADD_TAG",
|
|
2760
|
-
"WEBHOOK_EXECUTE",
|
|
2761
|
-
// Internal
|
|
2762
|
-
"IMAGE_PROCESSING",
|
|
2763
|
-
"DAILY_SETTLEMENT",
|
|
2764
|
-
"PLATFORM_WEBHOOK"
|
|
2765
|
-
];
|
|
2766
|
-
var PlatformEventType = [
|
|
2767
|
-
"VERSION_PUBLISHED",
|
|
2768
|
-
"DEPLOYED",
|
|
2769
|
-
"ROLLED_BACK",
|
|
2770
|
-
"UNDEPLOYED"
|
|
2771
|
-
];
|
|
2772
|
-
var WebhookPayloadFormat = ["GENERIC", "SLACK"];
|
|
2773
|
-
|
|
2774
|
-
// src/commands/logs.ts
|
|
2872
|
+
import dedent14 from "dedent";
|
|
2775
2873
|
function registerLogCommands(program) {
|
|
2776
2874
|
const logs = program.command("logs").description("Failure logs").addHelpText(
|
|
2777
2875
|
"after",
|
|
2778
|
-
|
|
2876
|
+
dedent14`
|
|
2779
2877
|
|
|
2780
2878
|
System failure logs (DLQ) for background tasks — webhook calls, coupon issuance,
|
|
2781
2879
|
point operations, notifications, and platform event webhooks.
|
|
@@ -2792,7 +2890,7 @@ function registerLogCommands(program) {
|
|
|
2792
2890
|
);
|
|
2793
2891
|
logs.command("list").description("List failure logs").option("--category <category>", "Filter by category (INTEGRATION, INTERNAL)").option("--task-type <taskType>", `Filter by task type (${TaskType.join(", ")})`).option("--status <status>", "Filter by status (PENDING, RESOLVED, IGNORED)").option("--keyword <keyword>", "Search keyword").option("--start-date <date>", "Start date (yyyy-MM-dd)").option("--end-date <date>", "End date (yyyy-MM-dd)").option("--page <number>", "Page number", "0").option("--size <number>", "Page size", "20").addHelpText(
|
|
2794
2892
|
"after",
|
|
2795
|
-
|
|
2893
|
+
dedent14`
|
|
2796
2894
|
|
|
2797
2895
|
Examples:
|
|
2798
2896
|
$ lexq logs list --status PENDING --format table
|
|
@@ -2843,7 +2941,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2843
2941
|
});
|
|
2844
2942
|
logs.command("get").description("Get failure log detail").requiredOption("--id <logId>", "Log ID").addHelpText(
|
|
2845
2943
|
"after",
|
|
2846
|
-
|
|
2944
|
+
dedent14`
|
|
2847
2945
|
|
|
2848
2946
|
Includes the full payload that was used for the failed operation.
|
|
2849
2947
|
Use this to inspect what went wrong before deciding to RETRY or RESOLVE.
|
|
@@ -2865,7 +2963,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2865
2963
|
});
|
|
2866
2964
|
logs.command("action").description("Process a failure log action (RETRY, IGNORE, RESOLVE)").requiredOption("--id <logId>", "Log ID").requiredOption("--action <action>", "Action: RETRY, IGNORE, or RESOLVE").addHelpText(
|
|
2867
2965
|
"after",
|
|
2868
|
-
|
|
2966
|
+
dedent14`
|
|
2869
2967
|
|
|
2870
2968
|
Actions:
|
|
2871
2969
|
RETRY Re-execute the failed operation with the original payload
|
|
@@ -2897,7 +2995,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2897
2995
|
});
|
|
2898
2996
|
logs.command("bulk-action").description("Bulk process failure logs").requiredOption("--ids <logIds>", "Comma-separated log IDs").requiredOption("--action <action>", "Action: RETRY, IGNORE, or RESOLVE").addHelpText(
|
|
2899
2997
|
"after",
|
|
2900
|
-
|
|
2998
|
+
dedent14`
|
|
2901
2999
|
|
|
2902
3000
|
Processes each log individually. Failures are skipped with a warning.
|
|
2903
3001
|
|
|
@@ -2925,11 +3023,11 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
2925
3023
|
|
|
2926
3024
|
// src/commands/webhook-subscriptions.ts
|
|
2927
3025
|
import "commander";
|
|
2928
|
-
import
|
|
3026
|
+
import dedent15 from "dedent";
|
|
2929
3027
|
function registerWebhookSubscriptionCommands(program) {
|
|
2930
3028
|
const webhooks = program.command("webhook-subscriptions").description("Manage platform event webhook subscriptions").addHelpText(
|
|
2931
3029
|
"after",
|
|
2932
|
-
|
|
3030
|
+
dedent15`
|
|
2933
3031
|
|
|
2934
3032
|
Receive notifications when deployment lifecycle events occur
|
|
2935
3033
|
(publish, deploy, rollback, undeploy).
|
|
@@ -3003,7 +3101,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
3003
3101
|
});
|
|
3004
3102
|
webhooks.command("save").description("Create or update a webhook subscription").requiredOption("--json <body>", "Request body as JSON string").addHelpText(
|
|
3005
3103
|
"after",
|
|
3006
|
-
|
|
3104
|
+
dedent15`
|
|
3007
3105
|
|
|
3008
3106
|
Examples:
|
|
3009
3107
|
# Create (Slack format)
|
|
@@ -3058,7 +3156,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
3058
3156
|
});
|
|
3059
3157
|
webhooks.command("delete").description("Delete a webhook subscription").requiredOption("--id <subscriptionId>", "Subscription ID").option("--force", "Skip confirmation prompt").addHelpText(
|
|
3060
3158
|
"after",
|
|
3061
|
-
|
|
3159
|
+
dedent15`
|
|
3062
3160
|
|
|
3063
3161
|
Use --force to skip the confirmation prompt.
|
|
3064
3162
|
|
|
@@ -3092,7 +3190,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
3092
3190
|
});
|
|
3093
3191
|
webhooks.command("test").description("Send a test event to verify webhook connectivity").requiredOption("--id <subscriptionId>", "Subscription ID").addHelpText(
|
|
3094
3192
|
"after",
|
|
3095
|
-
|
|
3193
|
+
dedent15`
|
|
3096
3194
|
|
|
3097
3195
|
Sends a test event to the webhook URL and reports the HTTP status code.
|
|
3098
3196
|
Does not record failures in the failure log.
|
|
@@ -3128,7 +3226,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
3128
3226
|
|
|
3129
3227
|
// src/commands/serve.ts
|
|
3130
3228
|
import "commander";
|
|
3131
|
-
import
|
|
3229
|
+
import dedent18 from "dedent";
|
|
3132
3230
|
|
|
3133
3231
|
// src/mcp/server.ts
|
|
3134
3232
|
import { readFileSync as readFileSync3 } from "fs";
|
|
@@ -3455,7 +3553,7 @@ function registerVersionTools(server, callApi) {
|
|
|
3455
3553
|
|
|
3456
3554
|
// src/mcp/tools/rules.ts
|
|
3457
3555
|
import { z as z3 } from "zod";
|
|
3458
|
-
import
|
|
3556
|
+
import dedent16 from "dedent";
|
|
3459
3557
|
function registerRuleTools(server, callApi) {
|
|
3460
3558
|
server.registerTool(
|
|
3461
3559
|
"lexq_rules_list",
|
|
@@ -3486,7 +3584,7 @@ function registerRuleTools(server, callApi) {
|
|
|
3486
3584
|
"lexq_rules_create",
|
|
3487
3585
|
{
|
|
3488
3586
|
title: "Create Rule",
|
|
3489
|
-
description:
|
|
3587
|
+
description: dedent16`
|
|
3490
3588
|
Create a rule in a DRAFT version. Requires name, condition tree, and actions array. priority is auto-assigned (appended last); use lexq_rules_reorder to change order.
|
|
3491
3589
|
|
|
3492
3590
|
Before creating rules with new fact keys, call lexq_facts_list to check existing facts.
|
|
@@ -3832,13 +3930,13 @@ function registerDeployTools(server, callApi) {
|
|
|
3832
3930
|
|
|
3833
3931
|
// src/mcp/tools/analytics.ts
|
|
3834
3932
|
import { z as z6 } from "zod";
|
|
3835
|
-
import
|
|
3933
|
+
import dedent17 from "dedent";
|
|
3836
3934
|
function registerAnalyticsTools(server, callApi) {
|
|
3837
3935
|
server.registerTool(
|
|
3838
3936
|
"lexq_dry_run",
|
|
3839
3937
|
{
|
|
3840
3938
|
title: "Dry Run",
|
|
3841
|
-
description:
|
|
3939
|
+
description: dedent17`
|
|
3842
3940
|
Execute a single dry run against a version. Tests how rules evaluate given input facts without side effects.
|
|
3843
3941
|
|
|
3844
3942
|
Returns:
|
|
@@ -3868,7 +3966,7 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
3868
3966
|
"lexq_dry_run_compare",
|
|
3869
3967
|
{
|
|
3870
3968
|
title: "Dry Run Compare",
|
|
3871
|
-
description:
|
|
3969
|
+
description: dedent17`
|
|
3872
3970
|
Compare dry run results between two versions using the same input facts. Useful for validating changes.
|
|
3873
3971
|
|
|
3874
3972
|
Returns:
|
|
@@ -3904,7 +4002,7 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
3904
4002
|
"lexq_simulation_start",
|
|
3905
4003
|
{
|
|
3906
4004
|
title: "Start Simulation",
|
|
3907
|
-
description:
|
|
4005
|
+
description: dedent17`
|
|
3908
4006
|
Start an Impact Simulation against historical, uploaded, or inline data.
|
|
3909
4007
|
|
|
3910
4008
|
dataset.type and dataset.source are BOTH required, and must be paired:
|
|
@@ -4002,7 +4100,7 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
4002
4100
|
"lexq_dataset_upload",
|
|
4003
4101
|
{
|
|
4004
4102
|
title: "Upload Dataset",
|
|
4005
|
-
description:
|
|
4103
|
+
description: dedent17`
|
|
4006
4104
|
Upload inline CSV or JSON content as a simulation dataset.
|
|
4007
4105
|
The content is uploaded to S3 and a path is returned in the "path" field.
|
|
4008
4106
|
|
|
@@ -4058,8 +4156,56 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
4058
4156
|
);
|
|
4059
4157
|
}
|
|
4060
4158
|
|
|
4061
|
-
// src/mcp/tools/
|
|
4159
|
+
// src/mcp/tools/profile.ts
|
|
4062
4160
|
import { z as z7 } from "zod";
|
|
4161
|
+
var RELATIVE_THRESHOLD = "flagged = p50 \u2265 10\xD7 median of per-rule p50s within the group; absolute thresholds are intentionally not supported.";
|
|
4162
|
+
function profileParams(opts) {
|
|
4163
|
+
const params = {};
|
|
4164
|
+
if (opts.versionId) params.versionId = opts.versionId;
|
|
4165
|
+
if (opts.from) params.from = opts.from;
|
|
4166
|
+
if (opts.to) params.to = opts.to;
|
|
4167
|
+
if (opts.cacheState) params.cacheState = opts.cacheState;
|
|
4168
|
+
return params;
|
|
4169
|
+
}
|
|
4170
|
+
function registerProfileTools(server, callApi) {
|
|
4171
|
+
server.registerTool(
|
|
4172
|
+
"lexq_profile_overview",
|
|
4173
|
+
{
|
|
4174
|
+
title: "Group Latency Profile",
|
|
4175
|
+
description: "Per-rule latency profile of a policy group over a time window: group TOTAL distribution split by cache state (HIT = compiled ruleset cache hit, MISS = deep-load + compile), a per-rule CONDITION/ACTION percentile table, and slow-rule flags. " + RELATIVE_THRESHOLD + " Every percentile is accompanied by its sample count n; a percentile is withheld (null) unless n\xD7(1\u2212q) \u2265 3 (p50 needs n \u2265 6, p95 n \u2265 60, p99 n \u2265 300 \u2014 display gate, separate from the n \u2265 100 judgment gate). Baselines report INSUFFICIENT_COHORT when fewer than 3 rules qualify. Rule detail comes from a deterministic 1% sample of calls; TOTAL is recorded for every call. Defaults: last 24h, live version, cacheState HIT.",
|
|
4176
|
+
inputSchema: {
|
|
4177
|
+
groupId: z7.string().uuid().describe("Policy group ID"),
|
|
4178
|
+
versionId: z7.string().uuid().optional().describe("Version to inspect (default: live version)"),
|
|
4179
|
+
from: z7.string().optional().describe("Window start, ISO-8601 instant (e.g. 2026-07-01T00:00:00Z). Default: 24h ago"),
|
|
4180
|
+
to: z7.string().optional().describe("Window end, ISO-8601 instant. Default: now"),
|
|
4181
|
+
cacheState: z7.enum(["HIT", "MISS"]).optional().describe("Cache dimension for the rule table and judgment (default: HIT)")
|
|
4182
|
+
}
|
|
4183
|
+
},
|
|
4184
|
+
async ({ groupId, versionId, from, to, cacheState }) => callApi("GET", `policy-groups/${groupId}/profile`, {
|
|
4185
|
+
params: profileParams({ versionId, from, to, cacheState })
|
|
4186
|
+
})
|
|
4187
|
+
);
|
|
4188
|
+
server.registerTool(
|
|
4189
|
+
"lexq_profile_rule",
|
|
4190
|
+
{
|
|
4191
|
+
title: "Rule Latency Detail",
|
|
4192
|
+
description: "Single-rule latency detail: merged phase \xD7 cacheState distributions plus a per-window time series (60s windows). Missing windows are genuine gaps \u2014 never interpolated. Series points carry each window's own values; percentiles in merged distributions are withheld (null) unless n\xD7(1\u2212q) \u2265 3 (p50 n \u2265 6, p95 n \u2265 60, p99 n \u2265 300). " + RELATIVE_THRESHOLD,
|
|
4193
|
+
inputSchema: {
|
|
4194
|
+
groupId: z7.string().uuid().describe("Policy group ID"),
|
|
4195
|
+
ruleId: z7.string().uuid().describe("Rule ID (from lexq_profile_overview)"),
|
|
4196
|
+
versionId: z7.string().uuid().optional().describe("Version to inspect (default: live version)"),
|
|
4197
|
+
from: z7.string().optional().describe("Window start, ISO-8601 instant. Default: 24h ago"),
|
|
4198
|
+
to: z7.string().optional().describe("Window end, ISO-8601 instant. Default: now")
|
|
4199
|
+
}
|
|
4200
|
+
},
|
|
4201
|
+
async ({ groupId, ruleId, versionId, from, to }) => callApi("GET", `policy-groups/${groupId}/profile/rules/${ruleId}`, {
|
|
4202
|
+
params: profileParams({ versionId, from, to })
|
|
4203
|
+
})
|
|
4204
|
+
);
|
|
4205
|
+
}
|
|
4206
|
+
|
|
4207
|
+
// src/mcp/tools/replay.ts
|
|
4208
|
+
import { z as z8 } from "zod";
|
|
4063
4209
|
function registerReplayTools(server, callApi) {
|
|
4064
4210
|
server.registerTool(
|
|
4065
4211
|
"lexq_replay_decision",
|
|
@@ -4067,8 +4213,8 @@ function registerReplayTools(server, callApi) {
|
|
|
4067
4213
|
title: "Replay a Decision",
|
|
4068
4214
|
description: "Re-evaluate a past execution (traceId) against a candidate version and return the decision diff (decisionChanged, effect changes, fired rules) plus a determinism verdict. Synchronous and free of charge (TPS throttle only). External effects (webhooks, notifications) are always mocked \u2014 nothing fires.",
|
|
4069
4215
|
inputSchema: {
|
|
4070
|
-
traceId:
|
|
4071
|
-
candidateVersionId:
|
|
4216
|
+
traceId: z8.string().describe("Trace ID of the past execution to replay"),
|
|
4217
|
+
candidateVersionId: z8.string().uuid().describe("Version to re-evaluate against")
|
|
4072
4218
|
}
|
|
4073
4219
|
},
|
|
4074
4220
|
async ({ traceId, candidateVersionId }) => callApi("POST", "replay/decisions", { body: { traceId, candidateVersionId } })
|
|
@@ -4079,10 +4225,10 @@ function registerReplayTools(server, callApi) {
|
|
|
4079
4225
|
title: "Start Window Replay (Blast Radius)",
|
|
4080
4226
|
description: "Submit an async job that replays a date window of past executions against a candidate version and measures the blast radius (how many decisions change). Billed per replayed record (REPLAY metric); VIEWER role cannot submit. Poll with lexq_replay_status.",
|
|
4081
4227
|
inputSchema: {
|
|
4082
|
-
candidateVersionId:
|
|
4083
|
-
from:
|
|
4084
|
-
to:
|
|
4085
|
-
maxRecords:
|
|
4228
|
+
candidateVersionId: z8.string().uuid().describe("Version to re-evaluate against"),
|
|
4229
|
+
from: z8.string().describe("Window start date (yyyy-MM-dd)"),
|
|
4230
|
+
to: z8.string().describe("Window end date (yyyy-MM-dd)"),
|
|
4231
|
+
maxRecords: z8.number().int().min(1).optional().describe("Sample cap (server default applies; hard cap 50k)")
|
|
4086
4232
|
}
|
|
4087
4233
|
},
|
|
4088
4234
|
async ({ candidateVersionId, from, to, maxRecords }) => callApi("POST", "replay/jobs", { body: { candidateVersionId, from, to, maxRecords } })
|
|
@@ -4093,7 +4239,7 @@ function registerReplayTools(server, callApi) {
|
|
|
4093
4239
|
title: "Get Replay Job Status",
|
|
4094
4240
|
description: "Poll a window replay job. RUNNING shows progress 0\u2013100; COMPLETED fills summary and changedSamples; FAILED carries errorMessage. capped=true means the window exceeded the sample cap and only part was replayed.",
|
|
4095
4241
|
inputSchema: {
|
|
4096
|
-
jobId:
|
|
4242
|
+
jobId: z8.string().describe("Replay job ID from lexq_replay_start")
|
|
4097
4243
|
}
|
|
4098
4244
|
},
|
|
4099
4245
|
async ({ jobId }) => callApi("GET", `replay/jobs/${jobId}`)
|
|
@@ -4104,8 +4250,8 @@ function registerReplayTools(server, callApi) {
|
|
|
4104
4250
|
title: "List Replay Jobs",
|
|
4105
4251
|
description: "List window replay job history (reverse-chronological). Lightweight items \u2014 use lexq_replay_status for summary and changed samples.",
|
|
4106
4252
|
inputSchema: {
|
|
4107
|
-
page:
|
|
4108
|
-
size:
|
|
4253
|
+
page: z8.number().int().min(0).default(0).describe("Page number"),
|
|
4254
|
+
size: z8.number().int().min(1).max(100).default(20).describe("Page size")
|
|
4109
4255
|
}
|
|
4110
4256
|
},
|
|
4111
4257
|
async ({ page, size }) => callApi("GET", "replay/jobs", { params: paginationParams(page, size) })
|
|
@@ -4116,7 +4262,7 @@ function registerReplayTools(server, callApi) {
|
|
|
4116
4262
|
title: "Cancel Replay Job",
|
|
4117
4263
|
description: "Cooperatively cancel a PENDING or RUNNING window replay job. Other states are rejected. VIEWER role cannot cancel.",
|
|
4118
4264
|
inputSchema: {
|
|
4119
|
-
jobId:
|
|
4265
|
+
jobId: z8.string().describe("Replay job ID")
|
|
4120
4266
|
}
|
|
4121
4267
|
},
|
|
4122
4268
|
async ({ jobId }) => callApi("POST", `replay/jobs/${jobId}/cancel`)
|
|
@@ -4124,7 +4270,7 @@ function registerReplayTools(server, callApi) {
|
|
|
4124
4270
|
}
|
|
4125
4271
|
|
|
4126
4272
|
// src/mcp/tools/history.ts
|
|
4127
|
-
import { z as
|
|
4273
|
+
import { z as z9 } from "zod";
|
|
4128
4274
|
function registerHistoryTools(server, callApi) {
|
|
4129
4275
|
server.registerTool(
|
|
4130
4276
|
"lexq_history_list",
|
|
@@ -4132,14 +4278,14 @@ function registerHistoryTools(server, callApi) {
|
|
|
4132
4278
|
title: "List Execution History",
|
|
4133
4279
|
description: "List policy execution history. Shows trace ID, group, version, status, match result, and latency.",
|
|
4134
4280
|
inputSchema: {
|
|
4135
|
-
page:
|
|
4136
|
-
size:
|
|
4137
|
-
traceId:
|
|
4138
|
-
groupId:
|
|
4139
|
-
versionId:
|
|
4140
|
-
status:
|
|
4141
|
-
startDate:
|
|
4142
|
-
endDate:
|
|
4281
|
+
page: z9.number().int().min(0).default(0).describe("Page number"),
|
|
4282
|
+
size: z9.number().int().min(1).max(100).default(20).describe("Page size"),
|
|
4283
|
+
traceId: z9.string().optional().describe("Filter by trace ID"),
|
|
4284
|
+
groupId: z9.string().uuid().optional().describe("Filter by policy group"),
|
|
4285
|
+
versionId: z9.string().uuid().optional().describe("Filter by version"),
|
|
4286
|
+
status: z9.enum(["SUCCESS", "NO_MATCH", "ERROR", "TIMEOUT"]).optional().describe("Filter by execution status"),
|
|
4287
|
+
startDate: z9.string().optional().describe("Start date (yyyy-MM-dd)"),
|
|
4288
|
+
endDate: z9.string().optional().describe("End date (yyyy-MM-dd)")
|
|
4143
4289
|
}
|
|
4144
4290
|
},
|
|
4145
4291
|
async ({ page, size, traceId, groupId, versionId, status, startDate, endDate }) => {
|
|
@@ -4159,7 +4305,7 @@ function registerHistoryTools(server, callApi) {
|
|
|
4159
4305
|
title: "Get Execution Detail",
|
|
4160
4306
|
description: "Get full execution detail including inputFacts, mutatedFacts, generatedVariables, executionTraces, and decisionTraces.",
|
|
4161
4307
|
inputSchema: {
|
|
4162
|
-
traceId:
|
|
4308
|
+
traceId: z9.string().describe("Trace ID from execution history")
|
|
4163
4309
|
}
|
|
4164
4310
|
},
|
|
4165
4311
|
async ({ traceId }) => callApi("GET", `execution/history/${traceId}`)
|
|
@@ -4170,9 +4316,9 @@ function registerHistoryTools(server, callApi) {
|
|
|
4170
4316
|
title: "Execution Statistics",
|
|
4171
4317
|
description: "Get execution KPIs: total executions, success/failure counts, success rate, and average latency.",
|
|
4172
4318
|
inputSchema: {
|
|
4173
|
-
groupId:
|
|
4174
|
-
startDate:
|
|
4175
|
-
endDate:
|
|
4319
|
+
groupId: z9.string().uuid().optional().describe("Filter by policy group"),
|
|
4320
|
+
startDate: z9.string().optional().describe("Start date (yyyy-MM-dd)"),
|
|
4321
|
+
endDate: z9.string().optional().describe("End date (yyyy-MM-dd)")
|
|
4176
4322
|
}
|
|
4177
4323
|
},
|
|
4178
4324
|
async ({ groupId, startDate, endDate }) => {
|
|
@@ -4186,7 +4332,7 @@ function registerHistoryTools(server, callApi) {
|
|
|
4186
4332
|
}
|
|
4187
4333
|
|
|
4188
4334
|
// src/mcp/tools/provenance.ts
|
|
4189
|
-
import { z as
|
|
4335
|
+
import { z as z10 } from "zod";
|
|
4190
4336
|
function registerProvenanceTools(server, callApi) {
|
|
4191
4337
|
server.registerTool(
|
|
4192
4338
|
"lexq_provenance_get",
|
|
@@ -4194,7 +4340,7 @@ function registerProvenanceTools(server, callApi) {
|
|
|
4194
4340
|
title: "Get Decision Provenance",
|
|
4195
4341
|
description: "Get the lineage of a single decision: what was decided, deterministic why per rule, input facts (PII facts are masked as \u2022\u2022\u2022\u2022\u2022\u2022 with maskedKeys listing them \u2014 values are revealable only in the console, audited), the authored/published/deployed responsibility chain, and the rule snapshot fingerprint.",
|
|
4196
4342
|
inputSchema: {
|
|
4197
|
-
traceId:
|
|
4343
|
+
traceId: z10.string().describe("Trace ID of the execution")
|
|
4198
4344
|
}
|
|
4199
4345
|
},
|
|
4200
4346
|
async ({ traceId }) => callApi("GET", `provenance/${traceId}`)
|
|
@@ -4205,13 +4351,13 @@ function registerProvenanceTools(server, callApi) {
|
|
|
4205
4351
|
title: "List PII Reveal Audits",
|
|
4206
4352
|
description: "List the PII reveal audit ledger \u2014 who revealed which fact of which trace, and when. Metadata only; revealed values are never stored or returned. Use for monthly access-log inspection and SIEM collection.",
|
|
4207
4353
|
inputSchema: {
|
|
4208
|
-
page:
|
|
4209
|
-
size:
|
|
4210
|
-
traceId:
|
|
4211
|
-
revealedBy:
|
|
4212
|
-
factKey:
|
|
4213
|
-
startDate:
|
|
4214
|
-
endDate:
|
|
4354
|
+
page: z10.number().int().min(0).default(0).describe("Page number"),
|
|
4355
|
+
size: z10.number().int().min(1).max(100).default(20).describe("Page size"),
|
|
4356
|
+
traceId: z10.string().optional().describe("Filter by trace ID (exact match)"),
|
|
4357
|
+
revealedBy: z10.string().optional().describe("Filter by operator ID (exact match)"),
|
|
4358
|
+
factKey: z10.string().optional().describe("Filter by fact key (partial match, case-insensitive)"),
|
|
4359
|
+
startDate: z10.string().optional().describe("Start date (yyyy-MM-dd)"),
|
|
4360
|
+
endDate: z10.string().optional().describe("End date (yyyy-MM-dd)")
|
|
4215
4361
|
}
|
|
4216
4362
|
},
|
|
4217
4363
|
async ({ page, size, traceId, revealedBy, factKey, startDate, endDate }) => {
|
|
@@ -4227,7 +4373,7 @@ function registerProvenanceTools(server, callApi) {
|
|
|
4227
4373
|
}
|
|
4228
4374
|
|
|
4229
4375
|
// src/mcp/tools/integrations.ts
|
|
4230
|
-
import { z as
|
|
4376
|
+
import { z as z11 } from "zod";
|
|
4231
4377
|
function registerIntegrationTools(server, callApi) {
|
|
4232
4378
|
server.registerTool(
|
|
4233
4379
|
"lexq_integrations_list",
|
|
@@ -4235,9 +4381,9 @@ function registerIntegrationTools(server, callApi) {
|
|
|
4235
4381
|
title: "List Integrations",
|
|
4236
4382
|
description: "List all external integrations (webhooks, CRM, notification, etc.).",
|
|
4237
4383
|
inputSchema: {
|
|
4238
|
-
page:
|
|
4239
|
-
size:
|
|
4240
|
-
type:
|
|
4384
|
+
page: z11.number().int().min(0).default(0).describe("Page number"),
|
|
4385
|
+
size: z11.number().int().min(1).max(100).default(20).describe("Page size"),
|
|
4386
|
+
type: z11.enum(["COUPON", "POINT", "NOTIFICATION", "CRM", "MESSENGER", "WEBHOOK"]).optional().describe("Filter by integration type")
|
|
4241
4387
|
}
|
|
4242
4388
|
},
|
|
4243
4389
|
async ({ page, size, type }) => {
|
|
@@ -4252,7 +4398,7 @@ function registerIntegrationTools(server, callApi) {
|
|
|
4252
4398
|
title: "Get Integration",
|
|
4253
4399
|
description: "Get integration detail by ID.",
|
|
4254
4400
|
inputSchema: {
|
|
4255
|
-
integrationId:
|
|
4401
|
+
integrationId: z11.string().uuid().describe("Integration ID")
|
|
4256
4402
|
}
|
|
4257
4403
|
},
|
|
4258
4404
|
async ({ integrationId }) => callApi("GET", `integrations/${integrationId}`)
|
|
@@ -4263,13 +4409,13 @@ function registerIntegrationTools(server, callApi) {
|
|
|
4263
4409
|
title: "Save Integration",
|
|
4264
4410
|
description: "Create or update an integration. Provide id to update an existing one; omit id to create new. Types: COUPON, POINT, NOTIFICATION, CRM, MESSENGER, WEBHOOK.",
|
|
4265
4411
|
inputSchema: {
|
|
4266
|
-
id:
|
|
4267
|
-
type:
|
|
4268
|
-
name:
|
|
4269
|
-
baseUrl:
|
|
4270
|
-
credential:
|
|
4271
|
-
additionalConfig:
|
|
4272
|
-
isActive:
|
|
4412
|
+
id: z11.string().uuid().optional().describe("Integration ID (omit to create, provide to update)"),
|
|
4413
|
+
type: z11.enum(["COUPON", "POINT", "NOTIFICATION", "CRM", "MESSENGER", "WEBHOOK"]).describe("Integration type"),
|
|
4414
|
+
name: z11.string().describe("Integration name"),
|
|
4415
|
+
baseUrl: z11.string().describe("Base URL of the external service"),
|
|
4416
|
+
credential: z11.string().optional().describe("API key or token for the service"),
|
|
4417
|
+
additionalConfig: z11.string().optional().describe("JSON string of additional config key-value pairs"),
|
|
4418
|
+
isActive: z11.boolean().default(true).describe("Whether the integration is active")
|
|
4273
4419
|
}
|
|
4274
4420
|
},
|
|
4275
4421
|
async ({ additionalConfig, ...rest }) => {
|
|
@@ -4284,7 +4430,7 @@ function registerIntegrationTools(server, callApi) {
|
|
|
4284
4430
|
title: "Delete Integration",
|
|
4285
4431
|
description: "Delete an integration by ID.",
|
|
4286
4432
|
inputSchema: {
|
|
4287
|
-
integrationId:
|
|
4433
|
+
integrationId: z11.string().uuid().describe("Integration ID")
|
|
4288
4434
|
}
|
|
4289
4435
|
},
|
|
4290
4436
|
async ({ integrationId }) => callApi("DELETE", `integrations/${integrationId}`)
|
|
@@ -4301,7 +4447,7 @@ function registerIntegrationTools(server, callApi) {
|
|
|
4301
4447
|
}
|
|
4302
4448
|
|
|
4303
4449
|
// src/mcp/tools/logs.ts
|
|
4304
|
-
import { z as
|
|
4450
|
+
import { z as z12 } from "zod";
|
|
4305
4451
|
function registerLogTools(server, callApi) {
|
|
4306
4452
|
server.registerTool(
|
|
4307
4453
|
"lexq_logs_list",
|
|
@@ -4309,14 +4455,14 @@ function registerLogTools(server, callApi) {
|
|
|
4309
4455
|
title: "List Failure Logs",
|
|
4310
4456
|
description: "List system failure logs from background tasks (webhook calls, coupon issuance, etc.).",
|
|
4311
4457
|
inputSchema: {
|
|
4312
|
-
page:
|
|
4313
|
-
size:
|
|
4314
|
-
category:
|
|
4315
|
-
taskType:
|
|
4316
|
-
status:
|
|
4317
|
-
keyword:
|
|
4318
|
-
startDate:
|
|
4319
|
-
endDate:
|
|
4458
|
+
page: z12.number().int().min(0).default(0).describe("Page number"),
|
|
4459
|
+
size: z12.number().int().min(1).max(100).default(20).describe("Page size"),
|
|
4460
|
+
category: z12.enum(TaskCategory).optional().describe("Task category"),
|
|
4461
|
+
taskType: z12.enum(TaskType).optional().describe("Task type"),
|
|
4462
|
+
status: z12.enum(FailureStatus).optional().describe("Log status"),
|
|
4463
|
+
keyword: z12.string().optional().describe("Search in refId, refSubId, errorMessage"),
|
|
4464
|
+
startDate: z12.string().optional().describe("Start date (yyyy-MM-dd)"),
|
|
4465
|
+
endDate: z12.string().optional().describe("End date (yyyy-MM-dd)")
|
|
4320
4466
|
}
|
|
4321
4467
|
},
|
|
4322
4468
|
async ({ page, size, category, taskType, status, keyword, startDate, endDate }) => {
|
|
@@ -4336,7 +4482,7 @@ function registerLogTools(server, callApi) {
|
|
|
4336
4482
|
title: "Get Failure Log",
|
|
4337
4483
|
description: "Get failure log detail by ID.",
|
|
4338
4484
|
inputSchema: {
|
|
4339
|
-
logId:
|
|
4485
|
+
logId: z12.string().uuid().describe("Failure log ID")
|
|
4340
4486
|
}
|
|
4341
4487
|
},
|
|
4342
4488
|
async ({ logId }) => callApi("GET", `failure-logs/${logId}`)
|
|
@@ -4347,8 +4493,8 @@ function registerLogTools(server, callApi) {
|
|
|
4347
4493
|
title: "Process Failure Log",
|
|
4348
4494
|
description: "Process a single failure log: RETRY (re-execute with original payload), RESOLVE (mark as manually fixed), or IGNORE (skip intentionally).",
|
|
4349
4495
|
inputSchema: {
|
|
4350
|
-
logId:
|
|
4351
|
-
action:
|
|
4496
|
+
logId: z12.string().uuid().describe("Failure log ID"),
|
|
4497
|
+
action: z12.enum(FailureAction).describe("Action to take")
|
|
4352
4498
|
}
|
|
4353
4499
|
},
|
|
4354
4500
|
async ({ logId, action }) => callApi("POST", `failure-logs/${logId}/actions`, {
|
|
@@ -4361,8 +4507,8 @@ function registerLogTools(server, callApi) {
|
|
|
4361
4507
|
title: "Bulk Process Failure Logs",
|
|
4362
4508
|
description: "Process multiple failure logs at once. Provide an array of log IDs and the action.",
|
|
4363
4509
|
inputSchema: {
|
|
4364
|
-
logIds:
|
|
4365
|
-
action:
|
|
4510
|
+
logIds: z12.array(z12.string().uuid()).describe("Array of failure log IDs"),
|
|
4511
|
+
action: z12.enum(FailureAction).describe("Action to apply to all logs")
|
|
4366
4512
|
}
|
|
4367
4513
|
},
|
|
4368
4514
|
async ({ logIds, action }) => callApi("POST", "failure-logs/bulk-actions", {
|
|
@@ -4372,7 +4518,7 @@ function registerLogTools(server, callApi) {
|
|
|
4372
4518
|
}
|
|
4373
4519
|
|
|
4374
4520
|
// src/mcp/tools/webhook-subscriptions.ts
|
|
4375
|
-
import { z as
|
|
4521
|
+
import { z as z13 } from "zod";
|
|
4376
4522
|
function registerWebhookSubscriptionTools(server, callApi) {
|
|
4377
4523
|
server.registerTool(
|
|
4378
4524
|
"lexq_webhook_subscriptions_list",
|
|
@@ -4380,8 +4526,8 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4380
4526
|
title: "List Webhook Subscriptions",
|
|
4381
4527
|
description: "List platform event webhook subscriptions. These receive deployment lifecycle notifications (publish, deploy, rollback, undeploy).",
|
|
4382
4528
|
inputSchema: {
|
|
4383
|
-
page:
|
|
4384
|
-
size:
|
|
4529
|
+
page: z13.number().int().min(0).default(0).describe("Page number"),
|
|
4530
|
+
size: z13.number().int().min(1).max(100).default(20).describe("Page size")
|
|
4385
4531
|
}
|
|
4386
4532
|
},
|
|
4387
4533
|
async ({ page, size }) => {
|
|
@@ -4395,7 +4541,7 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4395
4541
|
title: "Get Webhook Subscription",
|
|
4396
4542
|
description: "Get webhook subscription detail by ID.",
|
|
4397
4543
|
inputSchema: {
|
|
4398
|
-
id:
|
|
4544
|
+
id: z13.string().uuid().describe("Webhook subscription ID")
|
|
4399
4545
|
}
|
|
4400
4546
|
},
|
|
4401
4547
|
async ({ id }) => callApi("GET", `webhook-subscriptions/${id}`)
|
|
@@ -4406,13 +4552,13 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4406
4552
|
title: "Save Webhook Subscription",
|
|
4407
4553
|
description: 'Create or update a webhook subscription. Omit id to create, provide id to update. Events: VERSION_PUBLISHED, DEPLOYED, ROLLED_BACK, UNDEPLOYED. Formats: GENERIC (full JSON), SLACK ({"text": "..."}).',
|
|
4408
4554
|
inputSchema: {
|
|
4409
|
-
id:
|
|
4410
|
-
name:
|
|
4411
|
-
webhookUrl:
|
|
4412
|
-
subscribedEvents:
|
|
4413
|
-
payloadFormat:
|
|
4414
|
-
secret:
|
|
4415
|
-
isActive:
|
|
4555
|
+
id: z13.string().uuid().optional().describe("Subscription ID (omit to create, provide to update)"),
|
|
4556
|
+
name: z13.string().min(1).describe("Subscription name (unique per tenant)"),
|
|
4557
|
+
webhookUrl: z13.string().url().describe("Webhook endpoint URL"),
|
|
4558
|
+
subscribedEvents: z13.array(z13.enum(PlatformEventType)).min(1).describe("Events to subscribe to"),
|
|
4559
|
+
payloadFormat: z13.enum(WebhookPayloadFormat).optional().default("GENERIC").describe("Payload format"),
|
|
4560
|
+
secret: z13.string().optional().describe("HMAC-SHA256 signing secret"),
|
|
4561
|
+
isActive: z13.boolean().optional().default(true).describe("Whether the subscription is active")
|
|
4416
4562
|
}
|
|
4417
4563
|
},
|
|
4418
4564
|
async ({ ...body }) => callApi("POST", "webhook-subscriptions", { body })
|
|
@@ -4423,7 +4569,7 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4423
4569
|
title: "Delete Webhook Subscription",
|
|
4424
4570
|
description: "Delete a webhook subscription by ID.",
|
|
4425
4571
|
inputSchema: {
|
|
4426
|
-
id:
|
|
4572
|
+
id: z13.string().uuid().describe("Webhook subscription ID")
|
|
4427
4573
|
}
|
|
4428
4574
|
},
|
|
4429
4575
|
async ({ id }) => callApi("DELETE", `webhook-subscriptions/${id}`)
|
|
@@ -4434,7 +4580,7 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4434
4580
|
title: "Test Webhook Subscription",
|
|
4435
4581
|
description: "Send a test event to verify webhook connectivity. Returns the HTTP status code and success/failure message.",
|
|
4436
4582
|
inputSchema: {
|
|
4437
|
-
id:
|
|
4583
|
+
id: z13.string().uuid().describe("Webhook subscription ID")
|
|
4438
4584
|
}
|
|
4439
4585
|
},
|
|
4440
4586
|
async ({ id }) => callApi("POST", `webhook-subscriptions/${id}/test`)
|
|
@@ -4442,7 +4588,7 @@ function registerWebhookSubscriptionTools(server, callApi) {
|
|
|
4442
4588
|
}
|
|
4443
4589
|
|
|
4444
4590
|
// src/mcp/tools/domain-templates.ts
|
|
4445
|
-
import { z as
|
|
4591
|
+
import { z as z14 } from "zod";
|
|
4446
4592
|
function registerDomainTemplateTools(server, callApi) {
|
|
4447
4593
|
server.registerTool(
|
|
4448
4594
|
"lexq_domain_templates_list",
|
|
@@ -4459,7 +4605,7 @@ function registerDomainTemplateTools(server, callApi) {
|
|
|
4459
4605
|
title: "Preview Domain Template",
|
|
4460
4606
|
description: "Preview exactly what a domain template will provision before applying it: the fact definitions it registers, the sample rules it creates, and an apply plan. This is a read-only dry run \u2014 nothing is created. Only ACTIVE templates can be previewed.",
|
|
4461
4607
|
inputSchema: {
|
|
4462
|
-
template:
|
|
4608
|
+
template: z14.string().describe(
|
|
4463
4609
|
"Domain template key (e.g. ECOMMERCE). Use lexq_domain_templates_list to see available keys \u2014 currently only ECOMMERCE is ACTIVE."
|
|
4464
4610
|
)
|
|
4465
4611
|
}
|
|
@@ -4472,8 +4618,8 @@ function registerDomainTemplateTools(server, callApi) {
|
|
|
4472
4618
|
title: "Apply Domain Template",
|
|
4473
4619
|
description: "Apply a domain template to the current tenant. Creates the template's fact definitions and a new policy group pre-populated with its sample rules as a DRAFT version. Existing facts are skipped \u2014 apply is additive and never overwrites existing schema. Run lexq_domain_templates_preview first to review what will be created. Only ACTIVE templates can be applied.",
|
|
4474
4620
|
inputSchema: {
|
|
4475
|
-
template:
|
|
4476
|
-
customName:
|
|
4621
|
+
template: z14.string().describe("Domain template key to apply (e.g. ECOMMERCE)."),
|
|
4622
|
+
customName: z14.string().optional().describe(
|
|
4477
4623
|
"Optional custom name for the policy group that gets created. If omitted, the template's default name is used."
|
|
4478
4624
|
)
|
|
4479
4625
|
}
|
|
@@ -4495,6 +4641,7 @@ function registerAllTools(server, callApi) {
|
|
|
4495
4641
|
registerFactTools(server, callApi);
|
|
4496
4642
|
registerDeployTools(server, callApi);
|
|
4497
4643
|
registerAnalyticsTools(server, callApi);
|
|
4644
|
+
registerProfileTools(server, callApi);
|
|
4498
4645
|
registerReplayTools(server, callApi);
|
|
4499
4646
|
registerHistoryTools(server, callApi);
|
|
4500
4647
|
registerProvenanceTools(server, callApi);
|
|
@@ -4529,7 +4676,7 @@ async function startMcpServer() {
|
|
|
4529
4676
|
function registerServeCommand(program) {
|
|
4530
4677
|
program.command("serve").description("Start LexQ as a server for AI agent integrations").option("--mcp", "Start as MCP (Model Context Protocol) server over stdio").addHelpText(
|
|
4531
4678
|
"after",
|
|
4532
|
-
|
|
4679
|
+
dedent18`
|
|
4533
4680
|
|
|
4534
4681
|
Example:
|
|
4535
4682
|
$ lexq serve --mcp
|
|
@@ -4560,11 +4707,11 @@ function registerServeCommand(program) {
|
|
|
4560
4707
|
|
|
4561
4708
|
// src/commands/domain-templates.ts
|
|
4562
4709
|
import "commander";
|
|
4563
|
-
import
|
|
4710
|
+
import dedent19 from "dedent";
|
|
4564
4711
|
function registerDomainTemplateCommands(program) {
|
|
4565
4712
|
const templates = program.command("domain-templates").description("Browse and apply domain templates").addHelpText(
|
|
4566
4713
|
"after",
|
|
4567
|
-
|
|
4714
|
+
dedent19`
|
|
4568
4715
|
|
|
4569
4716
|
A domain template is an industry-specific starter pack of fact
|
|
4570
4717
|
definitions and sample rules. Applying one provisions a ready-to-use
|
|
@@ -4612,7 +4759,7 @@ function registerDomainTemplateCommands(program) {
|
|
|
4612
4759
|
});
|
|
4613
4760
|
templates.command("preview").description("Preview what a domain template provisions").requiredOption("--template <key>", "Domain template key (e.g. ECOMMERCE)").addHelpText(
|
|
4614
4761
|
"after",
|
|
4615
|
-
|
|
4762
|
+
dedent19`
|
|
4616
4763
|
|
|
4617
4764
|
Read-only dry run — shows the fact definitions and sample rules the
|
|
4618
4765
|
template will create. Nothing is provisioned.
|
|
@@ -4641,7 +4788,7 @@ function registerDomainTemplateCommands(program) {
|
|
|
4641
4788
|
});
|
|
4642
4789
|
templates.command("apply").description("Apply a domain template to the current tenant").requiredOption("--template <key>", "Domain template key (e.g. ECOMMERCE)").option("--name <n>", "Custom name for the policy group that gets created").option("--force", "Skip confirmation prompt").addHelpText(
|
|
4643
4790
|
"after",
|
|
4644
|
-
|
|
4791
|
+
dedent19`
|
|
4645
4792
|
|
|
4646
4793
|
Creates the template's fact definitions and a new DRAFT policy group
|
|
4647
4794
|
populated with its sample rules. Existing facts are skipped — apply is
|
|
@@ -4716,6 +4863,7 @@ function createCli() {
|
|
|
4716
4863
|
registerDomainTemplateCommands(program);
|
|
4717
4864
|
registerDeployCommands(program);
|
|
4718
4865
|
registerAnalyticsCommands(program);
|
|
4866
|
+
registerProfileCommands(program);
|
|
4719
4867
|
registerHistoryCommands(program);
|
|
4720
4868
|
registerReplayCommands(program);
|
|
4721
4869
|
registerProvenanceCommands(program);
|