@sassoftware/sas-score-mcp-serverjs 1.0.1-9 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +66 -61
- package/src/toolSet/findJob.js +24 -9
- package/src/toolSet/findJobdef.js +22 -19
- package/src/toolSet/findLibrary.js +73 -68
- 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 +6 -6
- 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 +70 -61
- package/src/toolSet/listJobs.js +68 -61
- package/src/toolSet/listLibraries.js +84 -78
- 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} +21 -18
- package/src/toolSet/readTable.js +80 -63
- package/src/toolSet/sasQuery.js +83 -77
- 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 +70 -65
- 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
|
@@ -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
|
+
|
|
@@ -6,12 +6,17 @@
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import _submitCode from '../toolHelpers/_submitCode.js';
|
|
8
8
|
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
function programScore(_appContext) {
|
|
10
|
+
const isAgent = _appContext && _appContext.agent;
|
|
11
|
+
let description = isAgent ? `
|
|
12
|
+
program-score — execute a SAS program model.
|
|
13
|
+
PARAMS: src (string, required), folder (string, optional), scenario (string|object, optional), output (string, optional), limit (number, optional)
|
|
14
|
+
RETURNS: log, ODS output, optional output table rows
|
|
15
|
+
` : `
|
|
16
|
+
program-score — execute a SAS program model on SAS Viya server.
|
|
12
17
|
|
|
13
|
-
USE when:
|
|
14
|
-
DO NOT USE for: macros (use
|
|
18
|
+
USE when: score program, execute SAS code, run .sas file
|
|
19
|
+
DO NOT USE for: macros (use macro-score), jobs (use job-score), jobdefs (use jobdef-score), SQL queries (use sas-query), read data (use read-table)
|
|
15
20
|
|
|
16
21
|
PARAMETERS
|
|
17
22
|
- src: string — SAS code or .sas filename (required)
|
|
@@ -21,18 +26,18 @@ PARAMETERS
|
|
|
21
26
|
- limit: number (default: 100) — max rows from output
|
|
22
27
|
|
|
23
28
|
ROUTING RULES
|
|
24
|
-
- "
|
|
25
|
-
- "
|
|
26
|
-
- "
|
|
29
|
+
- "score program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
|
|
30
|
+
- "score sas program sample folder=/Public/models" → { src: "sample", folder: "/Public/models", output: "", limit: 100 }
|
|
31
|
+
- "score program with name=John, age=45" → { src: "<code>", scenario: {name:"John", age:45}, output: "", limit: 100 }
|
|
27
32
|
|
|
28
33
|
EXAMPLES
|
|
29
|
-
- "
|
|
30
|
-
- "
|
|
34
|
+
- "score program 'data a; x=1; run;'" → { src: "data a; x=1; run;", folder: "", output: "", limit: 100 }
|
|
35
|
+
- "score sas file sample in /Public" → { src: "sample", folder: "/Public", output: "", limit: 100 }
|
|
31
36
|
|
|
32
37
|
NEGATIVE EXAMPLES (do not route here)
|
|
33
|
-
- "
|
|
34
|
-
- "
|
|
35
|
-
- "
|
|
38
|
+
- "score macro X" (use macro-score)
|
|
39
|
+
- "score job X" (use job-score)
|
|
40
|
+
- "score jobdef X" (use jobdef-score)
|
|
36
41
|
- "SQL query" (use sas-query)
|
|
37
42
|
- "read table" (use read-table)
|
|
38
43
|
|
|
@@ -41,7 +46,7 @@ Returns log, ods, tables array, data (if output specified). Error if execution f
|
|
|
41
46
|
`;
|
|
42
47
|
|
|
43
48
|
let spec = {
|
|
44
|
-
name: '
|
|
49
|
+
name: 'program-score',
|
|
45
50
|
description: description,
|
|
46
51
|
inputSchema: z.object({
|
|
47
52
|
src: z.string(),
|
|
@@ -65,7 +70,7 @@ Returns log, ods, tables array, data (if output specified). Error if execution f
|
|
|
65
70
|
`;
|
|
66
71
|
}
|
|
67
72
|
// figure out macros
|
|
68
|
-
|
|
73
|
+
|
|
69
74
|
if (typeof scenario === 'string' && scenario.includes('=')) {
|
|
70
75
|
scenario = scenario.split(',').reduce((acc, pair) => {
|
|
71
76
|
const [k, ...rest] = pair.split('=');
|
|
@@ -81,7 +86,6 @@ Returns log, ods, tables array, data (if output specified). Error if execution f
|
|
|
81
86
|
src: isrc,
|
|
82
87
|
_appContext: _appContext
|
|
83
88
|
}
|
|
84
|
-
// console.error('iparms', iparms);
|
|
85
89
|
let r = await _submitCode(iparms);
|
|
86
90
|
return r;
|
|
87
91
|
}
|
|
@@ -89,5 +93,4 @@ Returns log, ods, tables array, data (if output specified). Error if execution f
|
|
|
89
93
|
return spec;
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
export default
|
|
93
|
-
|
|
96
|
+
export default programScore;
|