@sassoftware/sas-score-mcp-serverjs 1.0.1-9 → 1.1.1
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/.skills/.claude-plugin/plugin.json +59 -0
- package/.skills/agents/sas-score-mcp-serverjs-agent.md +26 -0
- package/.skills/copilot-instructions.md +62 -0
- package/.skills/skills/README.md +204 -0
- package/.skills/skills/detail-strategy/SKILL.md +316 -0
- package/.skills/skills/find-library-server/SKILL.md +62 -0
- package/.skills/skills/find-resources/SKILL.md +66 -0
- package/.skills/skills/list-library/SKILL.md +30 -0
- package/.skills/skills/list-mas-job-jobdef/SKILL.md +31 -0
- package/.skills/skills/list-tables/SKILL.md +30 -0
- package/.skills/skills/read-strategy/SKILL.md +87 -0
- package/.skills/skills/request-routing/SKILL.md +112 -0
- package/.skills/skills/score-cas/SKILL.md +95 -0
- package/.skills/skills/score-job-jobdef/SKILL.md +58 -0
- package/.skills/skills/score-mas-scr/SKILL.md +58 -0
- package/.skills/skills/score-program/SKILL.md +59 -0
- package/.skills/skills/score-strategy/SKILL.md +39 -0
- package/README.md +96 -54
- package/cli.js +11 -13
- package/openApi.yaml +121 -121
- package/package.json +16 -14
- package/scripts/docs/SCORE_SKILL_REFERENCE.md +17 -16
- package/scripts/docs/TOOL_DESCRIPTION_TEMPLATE.md +3 -3
- package/scripts/docs/TOOL_UPDATES_SUMMARY.md +65 -63
- package/scripts/docs/oauth-http-transport.md +2 -2
- package/scripts/docs/sas-mcp-tools-reference.md +43 -32
- package/scripts/plot_msrp_usa.py +49 -0
- package/scripts/refreshtoken.js +58 -0
- package/scripts/runListScr.mjs +16 -0
- package/src/createMcpServer.js +4 -1
- package/src/expressMcpServer.js +47 -49
- package/src/oauthHandlers/authorize.js +4 -1
- package/src/oauthHandlers/baseUrl.js +4 -0
- package/src/oauthHandlers/callback.js +4 -0
- package/src/oauthHandlers/getMetadata.js +4 -0
- package/src/oauthHandlers/index.js +4 -0
- package/src/oauthHandlers/token.js +4 -0
- package/src/openApi.yaml +121 -121
- package/src/processHeaders.js +10 -7
- package/src/setupSkills.js +1 -18
- package/src/toolHelpers/_casScore.js +32 -0
- package/src/toolHelpers/_desc.js +14 -0
- package/src/toolHelpers/_findJob.js +12 -0
- package/src/toolHelpers/_findJobdef.js +10 -0
- package/src/toolHelpers/_findLibrary.js +11 -0
- package/src/toolHelpers/_findMas.js +13 -0
- package/src/toolHelpers/_findScr.js +36 -0
- package/src/toolHelpers/_findTable.js +11 -0
- package/src/toolHelpers/_listJobdefs.js +12 -2
- package/src/toolHelpers/_listJobs.js +19 -8
- package/src/toolHelpers/{_listModels.js → _listMas.js} +4 -4
- package/src/toolHelpers/_listScr.js +13 -0
- package/src/toolHelpers/{_scrInfo.js → _scrDescribe.js} +4 -4
- package/src/toolHelpers/_scrScore.js +2 -2
- package/src/toolHelpers/_submitCasl.js +19 -17
- package/src/toolHelpers/{_tableInfo.js → _tableDescribe.js} +2 -2
- package/src/toolHelpers/getLogonPayload.js +2 -2
- package/src/toolSet/casModelScore.js +93 -0
- package/src/toolSet/casProgramScore.js +105 -0
- package/src/toolSet/devaScore.js +11 -6
- package/src/toolSet/findJob.js +74 -59
- package/src/toolSet/findJobdef.js +67 -64
- package/src/toolSet/findLibrary.js +28 -23
- package/src/toolSet/findMas.js +72 -0
- package/src/toolSet/findScr.js +69 -0
- package/src/toolSet/findTable.js +34 -27
- package/src/toolSet/getEnv.js +57 -57
- package/src/toolSet/jobDescribe.js +65 -0
- package/src/toolSet/jobScore.js +90 -0
- package/src/toolSet/jobdefDescribe.js +67 -0
- package/src/toolSet/jobdefScore.js +85 -0
- package/src/toolSet/listJobdefs.js +17 -8
- package/src/toolSet/listJobs.js +15 -8
- package/src/toolSet/listLibraries.js +16 -10
- package/src/toolSet/listMas.js +71 -0
- package/src/toolSet/listScr.js +62 -0
- package/src/toolSet/listTables.js +78 -66
- package/src/toolSet/{runMacro.js → macroScore.js} +86 -82
- package/src/toolSet/makeTools.js +39 -25
- package/src/toolSet/masDescribe.js +67 -0
- package/src/toolSet/masScore.js +95 -0
- package/src/toolSet/{runProgram.js → programScore.js} +96 -93
- package/src/toolSet/readTable.js +43 -26
- package/src/toolSet/sasQuery.js +24 -18
- package/src/toolSet/scrDescribe.js +55 -0
- package/src/toolSet/scrScore.js +63 -70
- package/src/toolSet/searchAssets.js +1 -1
- package/src/toolSet/setContext.js +8 -3
- package/src/toolSet/superstat.js +61 -61
- package/src/toolSet/tableDescribe.js +65 -0
- package/.agents/sas-score-mcp-serverjs-agent.md +0 -58
- package/.instructions/copilot-instructions.md +0 -201
- package/.instructions/enforce-find-resource-strategy.md +0 -35
- package/.skills/sas-find-library-smart/SKILL.md +0 -155
- package/.skills/sas-find-resource-strategy/SKILL.md +0 -105
- package/.skills/sas-list-resource-strategy/SKILL.md +0 -124
- package/.skills/sas-list-tables-smart/SKILL.md +0 -128
- package/.skills/sas-read-and-score-strategy/SKILL.md +0 -113
- package/.skills/sas-read-strategy/SKILL.md +0 -154
- package/.skills/sas-request-classifier/SKILL.md +0 -74
- package/.skills/sas-score-workflow-strategy/SKILL.md +0 -314
- package/scripts/optimize_final.py +0 -140
- package/scripts/optimize_tools.py +0 -99
- package/scripts/setup-skills.js +0 -34
- package/scripts/update_descriptions.py +0 -46
- package/src/authpkce.js +0 -219
- package/src/handleGetDelete.js +0 -34
- package/src/handleRequest.js +0 -112
- package/src/hapiMcpServer.js +0 -241
- package/src/toolSet/findModel.js +0 -60
- package/src/toolSet/listModels.js +0 -56
- package/src/toolSet/modelInfo.js +0 -55
- package/src/toolSet/modelScore.js +0 -89
- package/src/toolSet/runCasProgram.js +0 -98
- package/src/toolSet/runJob.js +0 -81
- package/src/toolSet/runJobdef.js +0 -82
- package/src/toolSet/scrInfo.js +0 -52
- package/src/toolSet/tableInfo.js +0 -58
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import _listScr from '../toolHelpers/_listScr.js';
|
|
8
|
+
|
|
9
|
+
function listScr(_appContext) {
|
|
10
|
+
const isAgent = _appContext && _appContext.agent;
|
|
11
|
+
let description = isAgent ? `
|
|
12
|
+
list-scr — list available SCR models.
|
|
13
|
+
PARAMS: start (number, default 1), limit (number, default 10)
|
|
14
|
+
RETURNS: array of SCR model names and metadata
|
|
15
|
+
` : `
|
|
16
|
+
list-scr — enumerate models published to scr.
|
|
17
|
+
|
|
18
|
+
USE when: list scr, show scr next page
|
|
19
|
+
DO NOT USE for: ${_appContext.brand}-find model, ${_appContext.brand}-find scr, ${_appContext.brand}-model metadata, ${_appContext.brand}-score model, ${_appContext.brand}-list jobs/tables/libraries
|
|
20
|
+
|
|
21
|
+
PARAMETERS
|
|
22
|
+
- limit: number (default: 10) — page size
|
|
23
|
+
- start: number (default: 1) — 1-based offset
|
|
24
|
+
|
|
25
|
+
ROUTING RULES
|
|
26
|
+
- "list scr" → { start:1, limit:10 }
|
|
27
|
+
- "list 25 scr" → { start:1, limit:25 }
|
|
28
|
+
- "next scr" → { start: start+limit, limit:10 }
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
- "list scr" → { start:1, limit:10 }
|
|
32
|
+
- "list 25 scr" → { start:1, limit:25 }
|
|
33
|
+
|
|
34
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
35
|
+
- "find scr X" (use ${_appContext.brand}-find-scr)
|
|
36
|
+
- "describe scr X" (use ${_appContext.brand}-scr-describe)
|
|
37
|
+
- "score scr X" (use ${_appContext.brand}-scr-score)
|
|
38
|
+
- "list jobs" (use ${_appContext.brand}-list-jobs)
|
|
39
|
+
|
|
40
|
+
ERRORS
|
|
41
|
+
Returns empty array if no scrs found.
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
let spec = {
|
|
45
|
+
name: 'list-scr',
|
|
46
|
+
description: description,
|
|
47
|
+
inputSchema: z.object({
|
|
48
|
+
limit: z.number().optional(),
|
|
49
|
+
start: z.number().optional()
|
|
50
|
+
}),
|
|
51
|
+
handler: async (params) => {
|
|
52
|
+
let r = await _listScr(params);
|
|
53
|
+
return r;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return spec;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default listScr;
|
|
61
|
+
|
|
62
|
+
|
|
@@ -1,66 +1,78 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import debug from 'debug';
|
|
8
|
-
import _listTables from '../toolHelpers/_listTables.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function listTables(_appContext) {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- "
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- "
|
|
40
|
-
- "
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import debug from 'debug';
|
|
8
|
+
import _listTables from '../toolHelpers/_listTables.js';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
function listTables(_appContext) {
|
|
12
|
+
const isAgent = _appContext && _appContext.agent;
|
|
13
|
+
const log = debug('tools');
|
|
14
|
+
|
|
15
|
+
let description = isAgent ? `
|
|
16
|
+
list-tables — list tables in a library.
|
|
17
|
+
PARAMS: intent ('list', required), lib (string, required), server ('cas'|'sas', optional), start (number, default 1), limit (number, default 10)
|
|
18
|
+
RETURNS: array of table names and metadata
|
|
19
|
+
` : `
|
|
20
|
+
list-tables — enumerate tables within a library.
|
|
21
|
+
|
|
22
|
+
USE when: list tables in <lib>, show tables in <lib>, next page
|
|
23
|
+
DO NOT USE for: find table, list libraries, get table structure (use ${_appContext.brand}-table-describe), read data (use ${_appContext.brand}-read-table)
|
|
24
|
+
|
|
25
|
+
PARAMETERS
|
|
26
|
+
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate tables. Do NOT use for read, find, or verify.
|
|
27
|
+
- lib: string — library to inspect (required)
|
|
28
|
+
- server: string (default: 'cas') — 'cas' or 'sas'
|
|
29
|
+
- limit: number (default: 10) — page size
|
|
30
|
+
- start: number (default: 1) — 1-based offset
|
|
31
|
+
- where: string — optional filter expression
|
|
32
|
+
|
|
33
|
+
ROUTING RULES
|
|
34
|
+
- "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
|
|
35
|
+
- "list 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
|
|
36
|
+
- "list cas tables in Public" → { lib: "Public", server: "cas", start: 1, limit: 10 }
|
|
37
|
+
|
|
38
|
+
EXAMPLES
|
|
39
|
+
- "list tables in Samples" → { lib: "Samples", start: 1, limit: 10 }
|
|
40
|
+
- "show 25 tables in sashelp" → { lib: "sashelp", limit: 25, start: 1 }
|
|
41
|
+
|
|
42
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
43
|
+
-- "list libs" (use ${_appContext.brand}-list-libraries)
|
|
44
|
+
-- "find lib Public" (use ${_appContext.brand}-find-library)
|
|
45
|
+
-- "describe table cars" (use ${_appContext.brand}-table-describe)
|
|
46
|
+
-- "read table cars" (use ${_appContext.brand}-read-table)
|
|
47
|
+
-- "does table cars exist in Samples" (use ${_appContext.brand}-find-table)
|
|
48
|
+
-- "is table iris in Public" (use ${_appContext.brand}-find-table)
|
|
49
|
+
-- "verify table orders in mylib" (use ${_appContext.brand}-find-table)
|
|
50
|
+
|
|
51
|
+
ERRORS
|
|
52
|
+
Returns empty array if no tables found.
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
let spec = {
|
|
56
|
+
name: 'list-tables',
|
|
57
|
+
description: description,
|
|
58
|
+
|
|
59
|
+
inputSchema: z.object({
|
|
60
|
+
intent: z.literal('list'),
|
|
61
|
+
lib: z.string(),
|
|
62
|
+
server: z.string().optional(),
|
|
63
|
+
limit: z.number().optional(),
|
|
64
|
+
start: z.number().optional(),
|
|
65
|
+
where: z.string().optional()
|
|
66
|
+
}),
|
|
67
|
+
handler: async (params) => {
|
|
68
|
+
const { intent, ...rest } = params;
|
|
69
|
+
let r = await _listTables(rest);
|
|
70
|
+
return r;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return spec;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default listTables;
|
|
77
|
+
|
|
78
|
+
|
|
@@ -1,82 +1,86 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import _submitCode from '../toolHelpers/_submitCode.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- "
|
|
28
|
-
- "
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- "
|
|
33
|
-
- "
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import _submitCode from '../toolHelpers/_submitCode.js';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function macroScore(_appContext) {
|
|
11
|
+
const isAgent = _appContext && _appContext.agent;
|
|
12
|
+
let description = isAgent ? `
|
|
13
|
+
macro-score — execute a SAS macro model.
|
|
14
|
+
PARAMS: macro (string, required — name without %), scenario (string, optional — "x=1,y=2" or %let syntax)
|
|
15
|
+
RETURNS: log, ODS output, and tables created by macro
|
|
16
|
+
` : `
|
|
17
|
+
macro-score — submit and execute a SAS macro model on SAS Viya server.
|
|
18
|
+
|
|
19
|
+
USE when: score macro, execute macro with parameters
|
|
20
|
+
DO NOT USE for: arbitrary SAS code (use program-score), jobs (use job-score), jobdefs (use jobdef-score)
|
|
21
|
+
|
|
22
|
+
PARAMETERS
|
|
23
|
+
- macro: string — macro name without "%" (required)
|
|
24
|
+
- scenario: string — parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
|
|
25
|
+
|
|
26
|
+
ROUTING RULES
|
|
27
|
+
- "score macro abc" → { macro: "abc", scenario: "" }
|
|
28
|
+
- "score macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
|
|
29
|
+
- "score macro xyz with %let a=1; %let b=2;" → { macro: "xyz", scenario: "%let a=1; %let b=2;" }
|
|
30
|
+
|
|
31
|
+
EXAMPLES
|
|
32
|
+
- "score macro abc" → { macro: "abc", scenario: "" }
|
|
33
|
+
- "score macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
|
|
34
|
+
|
|
35
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
36
|
+
- "score SAS code" (use program-score)
|
|
37
|
+
- "score job X" (use job-score)
|
|
38
|
+
- "score jobdef X" (use jobdef-score)
|
|
39
|
+
|
|
40
|
+
ERRORS
|
|
41
|
+
Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
let spec = {
|
|
45
|
+
name: 'macro-score',
|
|
46
|
+
description: description,
|
|
47
|
+
|
|
48
|
+
inputSchema: z.object({
|
|
49
|
+
macro: z.string(),
|
|
50
|
+
scenario: z.string().optional()
|
|
51
|
+
}),
|
|
52
|
+
|
|
53
|
+
handler: async (params) => {
|
|
54
|
+
const scenarioRaw = (params.scenario || '').trim();
|
|
55
|
+
let setup = '';
|
|
56
|
+
if (scenarioRaw) {
|
|
57
|
+
// If the scenario already contains macro syntax, send it through unchanged
|
|
58
|
+
const hasMacroSyntax = /%let\b|%[a-zA-Z_]\w*\s*\(|%[a-zA-Z_]\w*\s*;/.test(scenarioRaw) || scenarioRaw.includes('%');
|
|
59
|
+
if (hasMacroSyntax) {
|
|
60
|
+
setup = scenarioRaw;
|
|
61
|
+
} else {
|
|
62
|
+
// Convert "x=1,y=abc" -> "%let x=1; %let y=abc;"
|
|
63
|
+
setup = scenarioRaw.split(',')
|
|
64
|
+
.map(p => p.trim())
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.map(p => {
|
|
67
|
+
const [k, ...rest] = p.split('=');
|
|
68
|
+
if (!k) return '';
|
|
69
|
+
const key = k.trim();
|
|
70
|
+
const val = rest.join('=').trim();
|
|
71
|
+
return `%let ${key}=${val};`;
|
|
72
|
+
})
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.join(' ');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const src = `${setup} %${params.macro};`;
|
|
78
|
+
params.src = src;
|
|
79
|
+
let r = await _submitCode(params);
|
|
80
|
+
return r;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return spec;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default macroScore;
|
package/src/toolSet/makeTools.js
CHANGED
|
@@ -3,67 +3,81 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
6
|
+
import listMas from './listMas.js';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import masScore from './masScore.js';
|
|
10
|
+
import masDescribe from './masDescribe.js';
|
|
11
|
+
import findMas from './findMas.js';
|
|
12
|
+
|
|
10
13
|
import findLibrary from './findLibrary.js';
|
|
11
|
-
import readTable from './readTable.js';
|
|
12
|
-
import tableInfo from './tableInfo.js';
|
|
13
14
|
import listLibraries from './listLibraries.js';
|
|
14
15
|
|
|
15
|
-
import
|
|
16
|
+
import listTables from './listTables.js';
|
|
17
|
+
import findTable from './findTable.js';
|
|
18
|
+
import tableDescribe from './tableDescribe.js';
|
|
19
|
+
import readTable from './readTable.js';
|
|
20
|
+
|
|
21
|
+
import findScr from './findScr.js';
|
|
22
|
+
import listScr from './listScr.js';
|
|
23
|
+
import scrDescribe from './scrDescribe.js';
|
|
16
24
|
import scrScore from './scrScore.js';
|
|
17
25
|
|
|
18
26
|
import devaScore from './devaScore.js';
|
|
19
27
|
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import
|
|
24
|
-
import
|
|
28
|
+
import programScore from './programScore.js';
|
|
29
|
+
import casProgramScore from './casProgramScore.js';
|
|
30
|
+
import casModelScore from './casModelScore.js';
|
|
31
|
+
import macroScore from './macroScore.js';
|
|
32
|
+
import jobScore from './jobScore.js';
|
|
25
33
|
import listJobs from './listJobs.js';
|
|
26
|
-
import
|
|
34
|
+
import jobdefScore from './jobdefScore.js';
|
|
27
35
|
import findJob from './findJob.js';
|
|
28
36
|
import listJobdefs from './listJobdefs.js';
|
|
29
37
|
import findJobdef from './findJobdef.js';
|
|
38
|
+
import jobDescribe from './jobDescribe.js';
|
|
39
|
+
import jobdefDescribe from './jobdefDescribe.js';
|
|
30
40
|
|
|
31
41
|
import sasQuery from './sasQuery.js';
|
|
32
42
|
import setContext from './setContext.js';
|
|
33
43
|
|
|
34
|
-
|
|
35
44
|
function makeTools(_appContext) {
|
|
36
45
|
// wrap all tools with
|
|
37
46
|
let customTools = [];
|
|
38
47
|
|
|
39
48
|
// get the tool definitions and handler
|
|
40
49
|
let list = [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
listMas(_appContext),
|
|
51
|
+
listScr(_appContext),
|
|
52
|
+
findMas(_appContext),
|
|
53
|
+
masDescribe(_appContext),
|
|
54
|
+
masScore(_appContext),
|
|
46
55
|
|
|
47
|
-
|
|
56
|
+
scrDescribe(_appContext),
|
|
48
57
|
scrScore(_appContext),
|
|
58
|
+
findScr(_appContext),
|
|
49
59
|
|
|
50
60
|
findLibrary(_appContext),
|
|
51
61
|
listLibraries(_appContext),
|
|
52
62
|
findTable(_appContext),
|
|
53
|
-
|
|
63
|
+
tableDescribe(_appContext),
|
|
54
64
|
listTables(_appContext),
|
|
55
65
|
readTable(_appContext),
|
|
56
66
|
sasQuery(_appContext),
|
|
57
67
|
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
programScore(_appContext),
|
|
69
|
+
casProgramScore(_appContext),
|
|
70
|
+
casModelScore(_appContext),
|
|
71
|
+
macroScore(_appContext),
|
|
60
72
|
|
|
61
73
|
findJob(_appContext),
|
|
62
74
|
listJobs(_appContext),
|
|
63
|
-
|
|
75
|
+
jobScore(_appContext),
|
|
64
76
|
listJobdefs(_appContext),
|
|
65
77
|
findJobdef(_appContext),
|
|
66
|
-
|
|
78
|
+
jobDescribe(_appContext),
|
|
79
|
+
jobdefDescribe(_appContext),
|
|
80
|
+
jobdefScore(_appContext),
|
|
67
81
|
|
|
68
82
|
devaScore(_appContext),
|
|
69
83
|
setContext(_appContext)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import debug from 'debug';
|
|
8
|
+
import _masDescribe from '../toolHelpers/_masDescribe.js';
|
|
9
|
+
const log = debug('tools');
|
|
10
|
+
|
|
11
|
+
function masDescribe(_appContext) {
|
|
12
|
+
const isAgent = _appContext && _appContext.agent;
|
|
13
|
+
let description = isAgent ? `
|
|
14
|
+
mas-describe — return input/output schema for a MAS model.
|
|
15
|
+
PARAMS: intent ('describe', required), name (string, required)
|
|
16
|
+
RETURNS: input variables, output variables, model type, description
|
|
17
|
+
` : `
|
|
18
|
+
mas-describe — return detailed information about a specific MAS model, including its inputs, outputs, and metadata.
|
|
19
|
+
|
|
20
|
+
USE when: what inputs does model need, describe model, show variables for model, model inputs/outputs
|
|
21
|
+
DO NOT USE for: find model, list models, score model, table/job operations
|
|
22
|
+
|
|
23
|
+
PARAMETERS
|
|
24
|
+
- intent: must be 'describe' — only pass if user explicitly asked to describe/inspect a MAS model. Do NOT use for find or verify existence.
|
|
25
|
+
- model: string — model name (required, exact match)
|
|
26
|
+
|
|
27
|
+
ROUTING RULES
|
|
28
|
+
- "what inputs does mas X need?" → { model: "X" }
|
|
29
|
+
- "describe mas Y" → { model: "Y" }
|
|
30
|
+
- "describe mas Y.mas" → { model: "Y" }
|
|
31
|
+
- "show variables for mas Z" → { model: "Z" }
|
|
32
|
+
|
|
33
|
+
EXAMPLES
|
|
34
|
+
- "What inputs does mas churnRisk need?" → { model: "churnRisk" }
|
|
35
|
+
- "Describe mas creditScore" → { model: "creditScore" }
|
|
36
|
+
- "Show variables for myModel" → { model: "myModel" }
|
|
37
|
+
|
|
38
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
39
|
+
- "list mas" (use list-models)
|
|
40
|
+
- "find mas X" (use find-model)
|
|
41
|
+
- "score with mas X" (use model-score)
|
|
42
|
+
|
|
43
|
+
ERRORS
|
|
44
|
+
Returns model metadata: inputs (name, type, role), outputs (name, type, possible_values), model_type, description.
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
let spec = {
|
|
48
|
+
name: 'mas-describe',
|
|
49
|
+
description: description,
|
|
50
|
+
inputSchema: z.object({
|
|
51
|
+
intent: z.literal('describe'),
|
|
52
|
+
model: z.string()
|
|
53
|
+
}),
|
|
54
|
+
handler: async (params) => {
|
|
55
|
+
const { intent, ...rest } = params;
|
|
56
|
+
if (rest.model != null && rest.model.endsWith('.mas')) {
|
|
57
|
+
rest.model = rest.model.slice(0, -4);
|
|
58
|
+
}
|
|
59
|
+
let r = await _masDescribe(rest);
|
|
60
|
+
return r;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return spec;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default masDescribe;
|
|
67
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import debug from 'debug';
|
|
8
|
+
import _masScoring from '../toolHelpers/_masScoring.js';
|
|
9
|
+
const log = debug('tools');
|
|
10
|
+
|
|
11
|
+
function masScore(_appContext) {
|
|
12
|
+
const isAgent = _appContext && _appContext.agent;
|
|
13
|
+
let description = isAgent ? `
|
|
14
|
+
mas-score — score data using a deployed MAS model.
|
|
15
|
+
PARAMS: model (string, required), scenario (object, optional key=value pairs)
|
|
16
|
+
RETURNS: predictions merged with input values
|
|
17
|
+
` : `
|
|
18
|
+
mas-score — score data using a deployed model on MAS.
|
|
19
|
+
|
|
20
|
+
USE when: score with model, predict using model, batch scoring, model predictions
|
|
21
|
+
DO NOT USE for: find model, model metadata, list models, run programs/jobs, query tables
|
|
22
|
+
|
|
23
|
+
PARAMETERS
|
|
24
|
+
- model: string — model name (required, exact match)
|
|
25
|
+
- scenario: object — input data as JSON (optional, defaults to {}). Example: {age:45, income:60000}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
ROUTING RULES
|
|
29
|
+
- "score with mas model X using a=1, b=2" → { model: "X", scenario: {a:1, b:2} }
|
|
30
|
+
- "score Y.mas for a=1, b=2" → { model: "Y", scenario: {a:1, b:2} }
|
|
31
|
+
- "predict using mas model Y with age=45, income=60000" → { model: "Y", scenario: {age:45, income:60000} }
|
|
32
|
+
|
|
33
|
+
EXAMPLES
|
|
34
|
+
- "score with mas model churn using age=45, income=60000" → { model: "churn", scenario: {age:45, income:60000} }
|
|
35
|
+
- "predict mas model creditScore for credit=700, debt=20000" → { model: "creditScore", scenario: {credit:700, debt:20000} }
|
|
36
|
+
|
|
37
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
38
|
+
- "find model X" (use find-model)
|
|
39
|
+
- "what inputs does model need" (use model-info)
|
|
40
|
+
- "list models" (use list-models)
|
|
41
|
+
- "score job X" (use job-score)
|
|
42
|
+
|
|
43
|
+
ERRORS
|
|
44
|
+
Returns predictions, probabilities, scores merged with input data. Returns error if model not found or scoring fails.
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
let spec = {
|
|
49
|
+
name: 'mas-score',
|
|
50
|
+
description: description,
|
|
51
|
+
inputSchema: z.object({
|
|
52
|
+
model: z.string(),
|
|
53
|
+
scenario: z.any()
|
|
54
|
+
}),
|
|
55
|
+
|
|
56
|
+
handler: async (iparams) => {
|
|
57
|
+
let params = {...iparams};
|
|
58
|
+
let scenario = params.scenario;
|
|
59
|
+
|
|
60
|
+
// Convert the scenario string to an object
|
|
61
|
+
// Example: "x=1, y=2, z=3" to { x: 1, y: 2, z: 3 }
|
|
62
|
+
let scenarioObj = {};
|
|
63
|
+
let count = 0;
|
|
64
|
+
if (typeof scenario === 'object') {
|
|
65
|
+
scenarioObj = scenario;
|
|
66
|
+
} else if (Array.isArray(scenario)) {
|
|
67
|
+
scenarioObj = scenario[0];
|
|
68
|
+
} else {
|
|
69
|
+
//console.error('Incoming scenario', scenario);
|
|
70
|
+
scenarioObj = scenario.split(',').reduce((acc, pair) => {
|
|
71
|
+
let [key, value] = pair.split('=');
|
|
72
|
+
acc[key.trim()] = value;
|
|
73
|
+
count++;
|
|
74
|
+
return acc;
|
|
75
|
+
}, {});
|
|
76
|
+
}
|
|
77
|
+
params.scenario = scenarioObj;
|
|
78
|
+
// Drop model extension (e.g., .job, .model)
|
|
79
|
+
if (params.model != null) {
|
|
80
|
+
if (params.model.endsWith('.mas')) {
|
|
81
|
+
params.model = params.model.slice(0, -4);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
log('masScore params', params);
|
|
86
|
+
// Check if the params.scenario is a string and parse it
|
|
87
|
+
let r = await _masScoring(params)
|
|
88
|
+
return r;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return spec;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default masScore;
|
|
95
|
+
|