@lexq/cli 0.1.14 → 0.1.16
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 +70 -60
- package/dist/mcp/register.js +61 -51
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -910,7 +910,7 @@ function buildUpdateBody2(opts) {
|
|
|
910
910
|
import "commander";
|
|
911
911
|
function registerDeployCommands(program) {
|
|
912
912
|
const deploy = program.command("deploy").description("Deployment lifecycle and history");
|
|
913
|
-
deploy.command("publish").description("Publish a DRAFT version (DRAFT \u2192 ACTIVE)").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--version-id <versionId>", "Version ID to publish").
|
|
913
|
+
deploy.command("publish").description("Publish a DRAFT version (DRAFT \u2192 ACTIVE)").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--version-id <versionId>", "Version ID to publish").requiredOption("--memo <memo>", "Publish Deployment memo").action(async (opts) => {
|
|
914
914
|
try {
|
|
915
915
|
const globalOpts = program.opts();
|
|
916
916
|
await apiRequest(
|
|
@@ -921,7 +921,7 @@ function registerDeployCommands(program) {
|
|
|
921
921
|
baseUrl: globalOpts.baseUrl,
|
|
922
922
|
dryRun: globalOpts.dryRun,
|
|
923
923
|
verbose: globalOpts.verbose,
|
|
924
|
-
body: { memo: opts.memo
|
|
924
|
+
body: { memo: opts.memo }
|
|
925
925
|
}
|
|
926
926
|
);
|
|
927
927
|
console.log(`\u2713 Version ${opts.versionId} published.`);
|
|
@@ -930,7 +930,7 @@ function registerDeployCommands(program) {
|
|
|
930
930
|
process.exit(1);
|
|
931
931
|
}
|
|
932
932
|
});
|
|
933
|
-
deploy.command("live").description("Deploy an ACTIVE version to live traffic").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--version-id <versionId>", "Version ID to deploy").
|
|
933
|
+
deploy.command("live").description("Deploy an ACTIVE version to live traffic").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--version-id <versionId>", "Version ID to deploy").requiredOption("--memo <memo>", "Live Deployment memo").action(async (opts) => {
|
|
934
934
|
try {
|
|
935
935
|
const globalOpts = program.opts();
|
|
936
936
|
await apiRequest("POST", `policy-groups/${opts.groupId}/deploy`, {
|
|
@@ -938,7 +938,7 @@ function registerDeployCommands(program) {
|
|
|
938
938
|
baseUrl: globalOpts.baseUrl,
|
|
939
939
|
dryRun: globalOpts.dryRun,
|
|
940
940
|
verbose: globalOpts.verbose,
|
|
941
|
-
body: { versionId: opts.versionId, memo: opts.memo
|
|
941
|
+
body: { versionId: opts.versionId, memo: opts.memo }
|
|
942
942
|
});
|
|
943
943
|
console.log(`\u2713 Version ${opts.versionId} deployed to live.`);
|
|
944
944
|
} catch (error) {
|
|
@@ -946,7 +946,7 @@ function registerDeployCommands(program) {
|
|
|
946
946
|
process.exit(1);
|
|
947
947
|
}
|
|
948
948
|
});
|
|
949
|
-
deploy.command("rollback").description("Rollback to the previous deployed version").requiredOption("--group-id <groupId>", "Policy group ID").
|
|
949
|
+
deploy.command("rollback").description("Rollback to the previous deployed version").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--memo <memo>", "Rollback reason").option("--force", "Skip confirmation prompt").action(async (opts) => {
|
|
950
950
|
try {
|
|
951
951
|
const globalOpts = program.opts();
|
|
952
952
|
if (!opts.force) {
|
|
@@ -964,7 +964,7 @@ function registerDeployCommands(program) {
|
|
|
964
964
|
baseUrl: globalOpts.baseUrl,
|
|
965
965
|
dryRun: globalOpts.dryRun,
|
|
966
966
|
verbose: globalOpts.verbose,
|
|
967
|
-
body: { memo: opts.memo
|
|
967
|
+
body: { memo: opts.memo }
|
|
968
968
|
});
|
|
969
969
|
console.log(`\u2713 Group ${opts.groupId} rolled back.`);
|
|
970
970
|
} catch (error) {
|
|
@@ -972,7 +972,7 @@ function registerDeployCommands(program) {
|
|
|
972
972
|
process.exit(1);
|
|
973
973
|
}
|
|
974
974
|
});
|
|
975
|
-
deploy.command("undeploy").description("Remove the live version from a group").requiredOption("--group-id <groupId>", "Policy group ID").
|
|
975
|
+
deploy.command("undeploy").description("Remove the live version from a group").requiredOption("--group-id <groupId>", "Policy group ID").requiredOption("--memo <memo>", "Undeploy reason").option("--force", "Skip confirmation prompt").action(async (opts) => {
|
|
976
976
|
try {
|
|
977
977
|
const globalOpts = program.opts();
|
|
978
978
|
if (!opts.force) {
|
|
@@ -990,7 +990,7 @@ function registerDeployCommands(program) {
|
|
|
990
990
|
baseUrl: globalOpts.baseUrl,
|
|
991
991
|
dryRun: globalOpts.dryRun,
|
|
992
992
|
verbose: globalOpts.verbose,
|
|
993
|
-
body: { memo: opts.memo
|
|
993
|
+
body: { memo: opts.memo }
|
|
994
994
|
});
|
|
995
995
|
console.log(`\u2713 Group ${opts.groupId} undeployed.`);
|
|
996
996
|
} catch (error) {
|
|
@@ -1553,7 +1553,7 @@ ${data.totalElements} total \xB7 page ${data.pageNo + 1}/${data.totalPages}`);
|
|
|
1553
1553
|
process.exit(1);
|
|
1554
1554
|
}
|
|
1555
1555
|
});
|
|
1556
|
-
history.command("get").description("Get execution detail").requiredOption("--id <
|
|
1556
|
+
history.command("get").description("Get execution detail").requiredOption("--id <traceId>", "Trace ID").action(async (opts) => {
|
|
1557
1557
|
try {
|
|
1558
1558
|
const globalOpts = program.opts();
|
|
1559
1559
|
const data = await apiRequest(
|
|
@@ -1973,10 +1973,10 @@ function registerGroupTools(server, callApi) {
|
|
|
1973
1973
|
name: z.string().describe("Group name (unique among non-ARCHIVED)"),
|
|
1974
1974
|
priority: z.number().int().min(0).describe("Execution priority (lower = higher)"),
|
|
1975
1975
|
description: z.string().optional().describe("Group description"),
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1976
|
+
activationMode: z.enum(["NONE", "EXCLUSIVE", "MAX_N"]).optional().describe("Conflict resolution mode"),
|
|
1977
|
+
activationStrategy: z.enum(["FIRST_MATCH", "HIGHEST_PRIORITY", "MAX_BENEFIT"]).optional().describe("Strategy when mode is EXCLUSIVE or MAX_N"),
|
|
1978
|
+
executionLimit: z.number().int().min(1).optional().describe("Max rule executions (required when mode is MAX_N)"),
|
|
1979
|
+
activationGroup: z.string().optional().describe("Activation group name")
|
|
1980
1980
|
}
|
|
1981
1981
|
},
|
|
1982
1982
|
async (args) => {
|
|
@@ -1985,12 +1985,10 @@ function registerGroupTools(server, callApi) {
|
|
|
1985
1985
|
priority: args.priority
|
|
1986
1986
|
};
|
|
1987
1987
|
if (args.description !== void 0) body.description = args.description;
|
|
1988
|
-
if (args.
|
|
1989
|
-
|
|
1990
|
-
if (args.
|
|
1991
|
-
|
|
1992
|
-
if (args.maxSelections !== void 0) body.maxSelections = args.maxSelections;
|
|
1993
|
-
if (args.activationGroupId !== void 0) body.activationGroupId = args.activationGroupId;
|
|
1988
|
+
if (args.activationMode !== void 0) body.activationMode = args.activationMode;
|
|
1989
|
+
if (args.activationStrategy !== void 0) body.activationStrategy = args.activationStrategy;
|
|
1990
|
+
if (args.executionLimit !== void 0) body.executionLimit = args.executionLimit;
|
|
1991
|
+
if (args.activationGroup !== void 0) body.activationGroup = args.activationGroup;
|
|
1994
1992
|
return callApi("POST", "policy-groups", { body });
|
|
1995
1993
|
}
|
|
1996
1994
|
);
|
|
@@ -1998,16 +1996,16 @@ function registerGroupTools(server, callApi) {
|
|
|
1998
1996
|
"lexq_groups_update",
|
|
1999
1997
|
{
|
|
2000
1998
|
title: "Update Policy Group",
|
|
2001
|
-
description: "Update
|
|
1999
|
+
description: "Update a policy group. This is a full replacement \u2014 omitted optional fields will be set to null on the server.",
|
|
2002
2000
|
inputSchema: {
|
|
2003
2001
|
groupId: z.string().uuid().describe("Policy group ID"),
|
|
2004
2002
|
name: z.string().optional().describe("New name"),
|
|
2005
2003
|
priority: z.number().int().min(0).optional().describe("New priority"),
|
|
2006
2004
|
description: z.string().optional().describe("New description"),
|
|
2007
2005
|
status: z.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2006
|
+
activationMode: z.enum(["NONE", "EXCLUSIVE", "MAX_N"]).optional().describe("Conflict resolution mode"),
|
|
2007
|
+
activationStrategy: z.enum(["FIRST_MATCH", "HIGHEST_PRIORITY", "MAX_BENEFIT"]).optional().describe("Strategy"),
|
|
2008
|
+
executionLimit: z.number().int().min(1).optional().describe("Max rule executions")
|
|
2011
2009
|
}
|
|
2012
2010
|
},
|
|
2013
2011
|
async ({ groupId, ...body }) => callApi("PUT", `policy-groups/${groupId}`, { body })
|
|
@@ -2186,17 +2184,24 @@ function registerRuleTools(server, callApi) {
|
|
|
2186
2184
|
"lexq_rules_create",
|
|
2187
2185
|
{
|
|
2188
2186
|
title: "Create Rule",
|
|
2189
|
-
description: `Create a rule in a DRAFT version. Requires name, priority, condition tree, and actions array.
|
|
2187
|
+
description: `Create a rule in a DRAFT version. Requires name, priority, condition tree, and actions array.
|
|
2188
|
+
|
|
2189
|
+
Before creating rules with new fact keys, call lexq_facts_list to check existing facts.
|
|
2190
|
+
If a required key is missing, ask the user to confirm the type, isRequired, and description
|
|
2191
|
+
before calling lexq_facts_create \u2014 registering facts enables type validation, Console UI
|
|
2192
|
+
autocomplete, and the dry-run requirements analyzer.
|
|
2193
|
+
|
|
2190
2194
|
Condition: { type: "SINGLE", field, operator, value, valueType } or { type: "GROUP", operator: "AND"|"OR", children: [...] }
|
|
2191
|
-
Operators: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, CONTAINS, IN, NOT_IN
|
|
2195
|
+
Operators: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, CONTAINS, IN, NOT_IN
|
|
2192
2196
|
Value types: STRING, NUMBER, BOOLEAN, LIST_STRING, LIST_NUMBER
|
|
2193
|
-
|
|
2197
|
+
|
|
2194
2198
|
Actions: [{ type, parameters }]
|
|
2195
|
-
|
|
2199
|
+
|
|
2196
2200
|
Action parameter schemas:
|
|
2197
2201
|
- DISCOUNT: { refVar: string, method: "PERCENTAGE"|"AMOUNT", rate?: number (when PERCENTAGE), value?: number (when AMOUNT) }
|
|
2198
2202
|
- POINT: { refVar: string, targetVar: string, method: "PERCENTAGE"|"AMOUNT", rate?: number (when PERCENTAGE), value?: number (when AMOUNT), integrationId: uuid }
|
|
2199
|
-
- COUPON_ISSUE: { couponId: string, integrationId: uuid }
|
|
2203
|
+
- COUPON_ISSUE: { couponId: string, integrationId: uuid }
|
|
2204
|
+
- BLOCK: { reason: string }
|
|
2200
2205
|
- NOTIFICATION: { channel: "SMS"|"EMAIL"|"PUSH"|"KAKAO", targetVar: string, templateId: string, integrationId: uuid }
|
|
2201
2206
|
- WEBHOOK: { url: string, method: "POST" }
|
|
2202
2207
|
- SET_FACT: { key: string, value: string|number|boolean }
|
|
@@ -2367,7 +2372,7 @@ function registerDeployTools(server, callApi) {
|
|
|
2367
2372
|
inputSchema: {
|
|
2368
2373
|
groupId: z5.string().uuid().describe("Policy group ID"),
|
|
2369
2374
|
versionId: z5.string().uuid().describe("Version ID to publish"),
|
|
2370
|
-
memo: z5.string().
|
|
2375
|
+
memo: z5.string().min(1).describe("Publish Deployment memo (required)")
|
|
2371
2376
|
}
|
|
2372
2377
|
},
|
|
2373
2378
|
async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/versions/${versionId}/publish`, { body: { memo } })
|
|
@@ -2380,7 +2385,7 @@ function registerDeployTools(server, callApi) {
|
|
|
2380
2385
|
inputSchema: {
|
|
2381
2386
|
groupId: z5.string().uuid().describe("Policy group ID"),
|
|
2382
2387
|
versionId: z5.string().uuid().describe("Version ID to deploy"),
|
|
2383
|
-
memo: z5.string().
|
|
2388
|
+
memo: z5.string().min(1).describe("Live Deployment memo (required)")
|
|
2384
2389
|
}
|
|
2385
2390
|
},
|
|
2386
2391
|
async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/deploy`, {
|
|
@@ -2464,10 +2469,8 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
2464
2469
|
{
|
|
2465
2470
|
title: "Dry Run",
|
|
2466
2471
|
description: `Execute a single dry run against a version. Tests how rules evaluate given input facts without side effects.
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
Always dry-run before publishing to validate rule behavior.`,
|
|
2472
|
+
Example input: { "facts": { "payment_amount": 100000, "customer_tier": "VIP" } }
|
|
2473
|
+
Always dry-run before publishing to validate rule behavior.`,
|
|
2471
2474
|
inputSchema: {
|
|
2472
2475
|
versionId: z6.string().uuid().describe("Policy version ID to test against"),
|
|
2473
2476
|
facts: z6.string().describe('JSON string of facts object, e.g. {"payment_amount":100000}'),
|
|
@@ -2516,14 +2519,21 @@ Always dry-run before publishing to validate rule behavior.`,
|
|
|
2516
2519
|
"lexq_simulation_start",
|
|
2517
2520
|
{
|
|
2518
2521
|
title: "Start Simulation",
|
|
2519
|
-
description: `Start a batch simulation against historical
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2522
|
+
description: `Start a batch simulation against historical or uploaded data.
|
|
2523
|
+
|
|
2524
|
+
dataset.type: "HISTORICAL" or "UPLOADED"
|
|
2525
|
+
dataset.source (when HISTORICAL): "EXECUTION_LOGS"
|
|
2526
|
+
dataset.from / dataset.to: date range (yyyy-MM-dd, when HISTORICAL)
|
|
2527
|
+
options.maxRecords: number (max 100000, default 10000)
|
|
2528
|
+
options.baselinePolicyVersionId: uuid (optional, for comparison)
|
|
2529
|
+
options.includeRuleStats: boolean
|
|
2530
|
+
|
|
2531
|
+
Example body:
|
|
2532
|
+
{
|
|
2533
|
+
"policyVersionId": "<uuid>",
|
|
2534
|
+
"dataset": { "type": "HISTORICAL", "source": "EXECUTION_LOGS", "from": "2025-01-01", "to": "2025-01-31" },
|
|
2535
|
+
"options": { "baselinePolicyVersionId": "<uuid>", "includeRuleStats": true, "maxRecords": 10000 }
|
|
2536
|
+
}`,
|
|
2527
2537
|
inputSchema: {
|
|
2528
2538
|
body: z6.string().describe("JSON string of SimulationRequest")
|
|
2529
2539
|
}
|
|
@@ -2595,16 +2605,15 @@ Example body:
|
|
|
2595
2605
|
{
|
|
2596
2606
|
title: "Upload Dataset",
|
|
2597
2607
|
description: `Upload inline CSV or JSON content as a simulation dataset.
|
|
2598
|
-
The content is uploaded to S3 and a path is returned.
|
|
2599
|
-
Use this path in simulation start with dataset type UPLOADED.
|
|
2600
|
-
|
|
2601
|
-
CSV example:
|
|
2602
|
-
user_id,payment_amount
|
|
2603
|
-
user_001,150000
|
|
2604
|
-
user_002,50000
|
|
2605
|
-
|
|
2606
|
-
JSON example:
|
|
2607
|
-
[{"user_id":"user_001","payment_amount":150000}, {"user_id":"user_002","payment_amount":50000}]`,
|
|
2608
|
+
The content is uploaded to S3 and a path is returned.
|
|
2609
|
+
Use this path in simulation start with dataset type UPLOADED.
|
|
2610
|
+
|
|
2611
|
+
CSV example:
|
|
2612
|
+
user_id,payment_amount
|
|
2613
|
+
user_001,150000
|
|
2614
|
+
user_002,50000
|
|
2615
|
+
|
|
2616
|
+
JSON example: [{"user_id":"user_001","payment_amount":150000}, {"user_id":"user_002","payment_amount":50000}]`,
|
|
2608
2617
|
inputSchema: {
|
|
2609
2618
|
content: z6.string().describe("CSV or JSON content as string"),
|
|
2610
2619
|
filename: z6.string().default("dataset.csv").describe("Filename with extension (.csv or .json)")
|
|
@@ -2667,10 +2676,10 @@ function registerHistoryTools(server, callApi) {
|
|
|
2667
2676
|
title: "Get Execution Detail",
|
|
2668
2677
|
description: "Get full execution detail including request facts, result traces, and decision traces.",
|
|
2669
2678
|
inputSchema: {
|
|
2670
|
-
|
|
2679
|
+
traceId: z7.string().describe("Trace ID from execution history")
|
|
2671
2680
|
}
|
|
2672
2681
|
},
|
|
2673
|
-
async ({
|
|
2682
|
+
async ({ traceId }) => callApi("GET", `execution/history/${traceId}`)
|
|
2674
2683
|
);
|
|
2675
2684
|
server.registerTool(
|
|
2676
2685
|
"lexq_history_stats",
|
|
@@ -2728,19 +2737,20 @@ function registerIntegrationTools(server, callApi) {
|
|
|
2728
2737
|
"lexq_integrations_save",
|
|
2729
2738
|
{
|
|
2730
2739
|
title: "Save Integration",
|
|
2731
|
-
description: "Create or update an integration. Types: COUPON, POINT, NOTIFICATION, CRM, MESSENGER, WEBHOOK.",
|
|
2740
|
+
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.",
|
|
2732
2741
|
inputSchema: {
|
|
2742
|
+
id: z8.string().uuid().optional().describe("Integration ID (omit to create, provide to update)"),
|
|
2733
2743
|
type: z8.enum(["COUPON", "POINT", "NOTIFICATION", "CRM", "MESSENGER", "WEBHOOK"]).describe("Integration type"),
|
|
2734
2744
|
name: z8.string().describe("Integration name"),
|
|
2735
2745
|
baseUrl: z8.string().describe("Base URL of the external service"),
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2746
|
+
credential: z8.string().optional().describe("API key or token for the service"),
|
|
2747
|
+
additionalConfig: z8.string().optional().describe("JSON string of additional config key-value pairs"),
|
|
2748
|
+
isActive: z8.boolean().default(true).describe("Whether the integration is active")
|
|
2739
2749
|
}
|
|
2740
2750
|
},
|
|
2741
|
-
async ({
|
|
2751
|
+
async ({ additionalConfig, ...rest }) => {
|
|
2742
2752
|
const body = { ...rest };
|
|
2743
|
-
if (
|
|
2753
|
+
if (additionalConfig) body.additionalConfig = JSON.parse(additionalConfig);
|
|
2744
2754
|
return callApi("POST", "integrations", { body });
|
|
2745
2755
|
}
|
|
2746
2756
|
);
|
package/dist/mcp/register.js
CHANGED
|
@@ -66,10 +66,10 @@ function registerGroupTools(server, callApi) {
|
|
|
66
66
|
name: z.string().describe("Group name (unique among non-ARCHIVED)"),
|
|
67
67
|
priority: z.number().int().min(0).describe("Execution priority (lower = higher)"),
|
|
68
68
|
description: z.string().optional().describe("Group description"),
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
activationMode: z.enum(["NONE", "EXCLUSIVE", "MAX_N"]).optional().describe("Conflict resolution mode"),
|
|
70
|
+
activationStrategy: z.enum(["FIRST_MATCH", "HIGHEST_PRIORITY", "MAX_BENEFIT"]).optional().describe("Strategy when mode is EXCLUSIVE or MAX_N"),
|
|
71
|
+
executionLimit: z.number().int().min(1).optional().describe("Max rule executions (required when mode is MAX_N)"),
|
|
72
|
+
activationGroup: z.string().optional().describe("Activation group name")
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
async (args) => {
|
|
@@ -78,12 +78,10 @@ function registerGroupTools(server, callApi) {
|
|
|
78
78
|
priority: args.priority
|
|
79
79
|
};
|
|
80
80
|
if (args.description !== void 0) body.description = args.description;
|
|
81
|
-
if (args.
|
|
82
|
-
|
|
83
|
-
if (args.
|
|
84
|
-
|
|
85
|
-
if (args.maxSelections !== void 0) body.maxSelections = args.maxSelections;
|
|
86
|
-
if (args.activationGroupId !== void 0) body.activationGroupId = args.activationGroupId;
|
|
81
|
+
if (args.activationMode !== void 0) body.activationMode = args.activationMode;
|
|
82
|
+
if (args.activationStrategy !== void 0) body.activationStrategy = args.activationStrategy;
|
|
83
|
+
if (args.executionLimit !== void 0) body.executionLimit = args.executionLimit;
|
|
84
|
+
if (args.activationGroup !== void 0) body.activationGroup = args.activationGroup;
|
|
87
85
|
return callApi("POST", "policy-groups", { body });
|
|
88
86
|
}
|
|
89
87
|
);
|
|
@@ -91,16 +89,16 @@ function registerGroupTools(server, callApi) {
|
|
|
91
89
|
"lexq_groups_update",
|
|
92
90
|
{
|
|
93
91
|
title: "Update Policy Group",
|
|
94
|
-
description: "Update
|
|
92
|
+
description: "Update a policy group. This is a full replacement \u2014 omitted optional fields will be set to null on the server.",
|
|
95
93
|
inputSchema: {
|
|
96
94
|
groupId: z.string().uuid().describe("Policy group ID"),
|
|
97
95
|
name: z.string().optional().describe("New name"),
|
|
98
96
|
priority: z.number().int().min(0).optional().describe("New priority"),
|
|
99
97
|
description: z.string().optional().describe("New description"),
|
|
100
98
|
status: z.enum(["ACTIVE", "DISABLED"]).optional().describe("Status (DISABLED = emergency stop)"),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
activationMode: z.enum(["NONE", "EXCLUSIVE", "MAX_N"]).optional().describe("Conflict resolution mode"),
|
|
100
|
+
activationStrategy: z.enum(["FIRST_MATCH", "HIGHEST_PRIORITY", "MAX_BENEFIT"]).optional().describe("Strategy"),
|
|
101
|
+
executionLimit: z.number().int().min(1).optional().describe("Max rule executions")
|
|
104
102
|
}
|
|
105
103
|
},
|
|
106
104
|
async ({ groupId, ...body }) => callApi("PUT", `policy-groups/${groupId}`, { body })
|
|
@@ -279,17 +277,24 @@ function registerRuleTools(server, callApi) {
|
|
|
279
277
|
"lexq_rules_create",
|
|
280
278
|
{
|
|
281
279
|
title: "Create Rule",
|
|
282
|
-
description: `Create a rule in a DRAFT version. Requires name, priority, condition tree, and actions array.
|
|
280
|
+
description: `Create a rule in a DRAFT version. Requires name, priority, condition tree, and actions array.
|
|
281
|
+
|
|
282
|
+
Before creating rules with new fact keys, call lexq_facts_list to check existing facts.
|
|
283
|
+
If a required key is missing, ask the user to confirm the type, isRequired, and description
|
|
284
|
+
before calling lexq_facts_create \u2014 registering facts enables type validation, Console UI
|
|
285
|
+
autocomplete, and the dry-run requirements analyzer.
|
|
286
|
+
|
|
283
287
|
Condition: { type: "SINGLE", field, operator, value, valueType } or { type: "GROUP", operator: "AND"|"OR", children: [...] }
|
|
284
|
-
Operators: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, CONTAINS, IN, NOT_IN
|
|
288
|
+
Operators: EQUALS, NOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, CONTAINS, IN, NOT_IN
|
|
285
289
|
Value types: STRING, NUMBER, BOOLEAN, LIST_STRING, LIST_NUMBER
|
|
286
|
-
|
|
290
|
+
|
|
287
291
|
Actions: [{ type, parameters }]
|
|
288
|
-
|
|
292
|
+
|
|
289
293
|
Action parameter schemas:
|
|
290
294
|
- DISCOUNT: { refVar: string, method: "PERCENTAGE"|"AMOUNT", rate?: number (when PERCENTAGE), value?: number (when AMOUNT) }
|
|
291
295
|
- POINT: { refVar: string, targetVar: string, method: "PERCENTAGE"|"AMOUNT", rate?: number (when PERCENTAGE), value?: number (when AMOUNT), integrationId: uuid }
|
|
292
|
-
- COUPON_ISSUE: { couponId: string, integrationId: uuid }
|
|
296
|
+
- COUPON_ISSUE: { couponId: string, integrationId: uuid }
|
|
297
|
+
- BLOCK: { reason: string }
|
|
293
298
|
- NOTIFICATION: { channel: "SMS"|"EMAIL"|"PUSH"|"KAKAO", targetVar: string, templateId: string, integrationId: uuid }
|
|
294
299
|
- WEBHOOK: { url: string, method: "POST" }
|
|
295
300
|
- SET_FACT: { key: string, value: string|number|boolean }
|
|
@@ -460,7 +465,7 @@ function registerDeployTools(server, callApi) {
|
|
|
460
465
|
inputSchema: {
|
|
461
466
|
groupId: z5.string().uuid().describe("Policy group ID"),
|
|
462
467
|
versionId: z5.string().uuid().describe("Version ID to publish"),
|
|
463
|
-
memo: z5.string().
|
|
468
|
+
memo: z5.string().min(1).describe("Publish Deployment memo (required)")
|
|
464
469
|
}
|
|
465
470
|
},
|
|
466
471
|
async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/versions/${versionId}/publish`, { body: { memo } })
|
|
@@ -473,7 +478,7 @@ function registerDeployTools(server, callApi) {
|
|
|
473
478
|
inputSchema: {
|
|
474
479
|
groupId: z5.string().uuid().describe("Policy group ID"),
|
|
475
480
|
versionId: z5.string().uuid().describe("Version ID to deploy"),
|
|
476
|
-
memo: z5.string().
|
|
481
|
+
memo: z5.string().min(1).describe("Live Deployment memo (required)")
|
|
477
482
|
}
|
|
478
483
|
},
|
|
479
484
|
async ({ groupId, versionId, memo }) => callApi("POST", `policy-groups/${groupId}/deploy`, {
|
|
@@ -557,10 +562,8 @@ function registerAnalyticsTools(server, callApi) {
|
|
|
557
562
|
{
|
|
558
563
|
title: "Dry Run",
|
|
559
564
|
description: `Execute a single dry run against a version. Tests how rules evaluate given input facts without side effects.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
Always dry-run before publishing to validate rule behavior.`,
|
|
565
|
+
Example input: { "facts": { "payment_amount": 100000, "customer_tier": "VIP" } }
|
|
566
|
+
Always dry-run before publishing to validate rule behavior.`,
|
|
564
567
|
inputSchema: {
|
|
565
568
|
versionId: z6.string().uuid().describe("Policy version ID to test against"),
|
|
566
569
|
facts: z6.string().describe('JSON string of facts object, e.g. {"payment_amount":100000}'),
|
|
@@ -609,14 +612,21 @@ Always dry-run before publishing to validate rule behavior.`,
|
|
|
609
612
|
"lexq_simulation_start",
|
|
610
613
|
{
|
|
611
614
|
title: "Start Simulation",
|
|
612
|
-
description: `Start a batch simulation against historical
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
615
|
+
description: `Start a batch simulation against historical or uploaded data.
|
|
616
|
+
|
|
617
|
+
dataset.type: "HISTORICAL" or "UPLOADED"
|
|
618
|
+
dataset.source (when HISTORICAL): "EXECUTION_LOGS"
|
|
619
|
+
dataset.from / dataset.to: date range (yyyy-MM-dd, when HISTORICAL)
|
|
620
|
+
options.maxRecords: number (max 100000, default 10000)
|
|
621
|
+
options.baselinePolicyVersionId: uuid (optional, for comparison)
|
|
622
|
+
options.includeRuleStats: boolean
|
|
623
|
+
|
|
624
|
+
Example body:
|
|
625
|
+
{
|
|
626
|
+
"policyVersionId": "<uuid>",
|
|
627
|
+
"dataset": { "type": "HISTORICAL", "source": "EXECUTION_LOGS", "from": "2025-01-01", "to": "2025-01-31" },
|
|
628
|
+
"options": { "baselinePolicyVersionId": "<uuid>", "includeRuleStats": true, "maxRecords": 10000 }
|
|
629
|
+
}`,
|
|
620
630
|
inputSchema: {
|
|
621
631
|
body: z6.string().describe("JSON string of SimulationRequest")
|
|
622
632
|
}
|
|
@@ -688,16 +698,15 @@ Example body:
|
|
|
688
698
|
{
|
|
689
699
|
title: "Upload Dataset",
|
|
690
700
|
description: `Upload inline CSV or JSON content as a simulation dataset.
|
|
691
|
-
The content is uploaded to S3 and a path is returned.
|
|
692
|
-
Use this path in simulation start with dataset type UPLOADED.
|
|
693
|
-
|
|
694
|
-
CSV example:
|
|
695
|
-
user_id,payment_amount
|
|
696
|
-
user_001,150000
|
|
697
|
-
user_002,50000
|
|
698
|
-
|
|
699
|
-
JSON example:
|
|
700
|
-
[{"user_id":"user_001","payment_amount":150000}, {"user_id":"user_002","payment_amount":50000}]`,
|
|
701
|
+
The content is uploaded to S3 and a path is returned.
|
|
702
|
+
Use this path in simulation start with dataset type UPLOADED.
|
|
703
|
+
|
|
704
|
+
CSV example:
|
|
705
|
+
user_id,payment_amount
|
|
706
|
+
user_001,150000
|
|
707
|
+
user_002,50000
|
|
708
|
+
|
|
709
|
+
JSON example: [{"user_id":"user_001","payment_amount":150000}, {"user_id":"user_002","payment_amount":50000}]`,
|
|
701
710
|
inputSchema: {
|
|
702
711
|
content: z6.string().describe("CSV or JSON content as string"),
|
|
703
712
|
filename: z6.string().default("dataset.csv").describe("Filename with extension (.csv or .json)")
|
|
@@ -760,10 +769,10 @@ function registerHistoryTools(server, callApi) {
|
|
|
760
769
|
title: "Get Execution Detail",
|
|
761
770
|
description: "Get full execution detail including request facts, result traces, and decision traces.",
|
|
762
771
|
inputSchema: {
|
|
763
|
-
|
|
772
|
+
traceId: z7.string().describe("Trace ID from execution history")
|
|
764
773
|
}
|
|
765
774
|
},
|
|
766
|
-
async ({
|
|
775
|
+
async ({ traceId }) => callApi("GET", `execution/history/${traceId}`)
|
|
767
776
|
);
|
|
768
777
|
server.registerTool(
|
|
769
778
|
"lexq_history_stats",
|
|
@@ -821,19 +830,20 @@ function registerIntegrationTools(server, callApi) {
|
|
|
821
830
|
"lexq_integrations_save",
|
|
822
831
|
{
|
|
823
832
|
title: "Save Integration",
|
|
824
|
-
description: "Create or update an integration. Types: COUPON, POINT, NOTIFICATION, CRM, MESSENGER, WEBHOOK.",
|
|
833
|
+
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.",
|
|
825
834
|
inputSchema: {
|
|
835
|
+
id: z8.string().uuid().optional().describe("Integration ID (omit to create, provide to update)"),
|
|
826
836
|
type: z8.enum(["COUPON", "POINT", "NOTIFICATION", "CRM", "MESSENGER", "WEBHOOK"]).describe("Integration type"),
|
|
827
837
|
name: z8.string().describe("Integration name"),
|
|
828
838
|
baseUrl: z8.string().describe("Base URL of the external service"),
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
839
|
+
credential: z8.string().optional().describe("API key or token for the service"),
|
|
840
|
+
additionalConfig: z8.string().optional().describe("JSON string of additional config key-value pairs"),
|
|
841
|
+
isActive: z8.boolean().default(true).describe("Whether the integration is active")
|
|
832
842
|
}
|
|
833
843
|
},
|
|
834
|
-
async ({
|
|
844
|
+
async ({ additionalConfig, ...rest }) => {
|
|
835
845
|
const body = { ...rest };
|
|
836
|
-
if (
|
|
846
|
+
if (additionalConfig) body.additionalConfig = JSON.parse(additionalConfig);
|
|
837
847
|
return callApi("POST", "integrations", { body });
|
|
838
848
|
}
|
|
839
849
|
);
|