@sassoftware/sas-score-mcp-serverjs 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +2 -2
- package/package.json +1 -1
- package/src/oauthHandlers/authorize.js +7 -2
- package/src/toolHelpers/_casScore.js +31 -31
- package/src/toolSet/casModelScore.js +93 -93
- package/src/toolSet/casProgramScore.js +105 -105
- package/src/toolSet/devaScore.js +66 -66
- package/src/toolSet/findJob.js +74 -74
- package/src/toolSet/findJobdef.js +67 -67
- package/src/toolSet/findLibrary.js +73 -73
- package/src/toolSet/findMas.js +2 -2
- package/src/toolSet/getEnv.js +57 -57
- package/src/toolSet/jobDescribe.js +65 -65
- package/src/toolSet/jobScore.js +90 -90
- package/src/toolSet/jobdefDescribe.js +67 -67
- package/src/toolSet/jobdefScore.js +85 -85
- package/src/toolSet/listJobdefs.js +70 -70
- package/src/toolSet/listJobs.js +68 -68
- package/src/toolSet/listLibraries.js +84 -84
- package/src/toolSet/masScore.js +95 -95
- package/src/toolSet/programScore.js +96 -96
- package/src/toolSet/readTable.js +80 -80
- package/src/toolSet/sasQuery.js +83 -83
- package/src/toolSet/setContext.js +70 -70
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import _listJobdefs from '../toolHelpers/_listJobdefs.js';
|
|
7
|
-
function listJobdefs(_appContext) {
|
|
8
|
-
const isAgent = _appContext && _appContext.agent;
|
|
9
|
-
let description = isAgent ? `
|
|
10
|
-
list-jobdefs — list available JobDef models.
|
|
11
|
-
PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
|
|
12
|
-
RETURNS: array of jobdef names and metadata
|
|
13
|
-
` : `
|
|
14
|
-
list-jobdefs — enumerate SAS Viya job definitions (jobdefs) assets.
|
|
15
|
-
|
|
16
|
-
USE when: list jobdefs, show jobdefs, browse jobdefs, list available jobdefs, next page
|
|
17
|
-
DO NOT USE for: find single jobdef (use ${_appContext.brand}-find-jobdef), score jobdef (use ${_appContext.brand}-jobdef-score), find job (use ${_appContext.brand}-find-job), sas code (use ${_appContext.brand}-program-score)
|
|
18
|
-
|
|
19
|
-
PARAMETERS
|
|
20
|
-
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobdefs. Do NOT use for find, verify, or execute.
|
|
21
|
-
- limit: number (default: 10) — number of jobdefs per page
|
|
22
|
-
- start: number (default: 1) — 1-based page offset
|
|
23
|
-
- where: string (default: '') — optional filter expression
|
|
24
|
-
|
|
25
|
-
ROUTING RULES
|
|
26
|
-
- list jobdefs → { start: 1, limit: 10 }
|
|
27
|
-
- show me 25 jobdefs → { start: 1, limit: 25 }
|
|
28
|
-
- next jobdefs → { start: previousStart + previousLimit, limit: previousLimit }
|
|
29
|
-
|
|
30
|
-
EXAMPLES
|
|
31
|
-
- list jobdefs → { start: 1, limit: 10 }
|
|
32
|
-
- list 25 jobdefs → { start: 1, limit: 25 }
|
|
33
|
-
- next jobdefs → { start: 11, limit: 10 }
|
|
34
|
-
|
|
35
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
36
|
-
- find jobdef abc (use ${_appContext.brand}-find-jobdef)
|
|
37
|
-
- does jobdef X exist (use ${_appContext.brand}-find-jobdef)
|
|
38
|
-
- is jobdef X available (use ${_appContext.brand}-find-jobdef)
|
|
39
|
-
- list jobs (use ${_appContext.brand}-list-jobs)
|
|
40
|
-
- score jobdef abc (use ${_appContext.brand}-jobdef-score)
|
|
41
|
-
- list models (use ${_appContext.brand}-list-models)
|
|
42
|
-
|
|
43
|
-
PAGINATION
|
|
44
|
-
If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
|
|
45
|
-
|
|
46
|
-
ERRORS
|
|
47
|
-
Surface backend error directly; never fabricate jobdef names.
|
|
48
|
-
`;
|
|
49
|
-
|
|
50
|
-
let spec = {
|
|
51
|
-
name: 'list-jobdefs',
|
|
52
|
-
description: description,
|
|
53
|
-
inputSchema: z.object({
|
|
54
|
-
intent: z.literal('list'),
|
|
55
|
-
limit: z.number().optional(),
|
|
56
|
-
start: z.number().optional(),
|
|
57
|
-
where: z.string().optional()
|
|
58
|
-
}),
|
|
59
|
-
// No 'server' required; backend context is implicit in helper
|
|
60
|
-
handler: async (params) => {
|
|
61
|
-
// _listJobdefs handles all validation and defaults
|
|
62
|
-
const { intent, ...rest } = params;
|
|
63
|
-
const result = await _listJobdefs(rest);
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return spec;
|
|
68
|
-
}
|
|
69
|
-
export default listJobdefs;
|
|
70
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import _listJobdefs from '../toolHelpers/_listJobdefs.js';
|
|
7
|
+
function listJobdefs(_appContext) {
|
|
8
|
+
const isAgent = _appContext && _appContext.agent;
|
|
9
|
+
let description = isAgent ? `
|
|
10
|
+
list-jobdefs — list available JobDef models.
|
|
11
|
+
PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
|
|
12
|
+
RETURNS: array of jobdef names and metadata
|
|
13
|
+
` : `
|
|
14
|
+
list-jobdefs — enumerate SAS Viya job definitions (jobdefs) assets.
|
|
15
|
+
|
|
16
|
+
USE when: list jobdefs, show jobdefs, browse jobdefs, list available jobdefs, next page
|
|
17
|
+
DO NOT USE for: find single jobdef (use ${_appContext.brand}-find-jobdef), score jobdef (use ${_appContext.brand}-jobdef-score), find job (use ${_appContext.brand}-find-job), sas code (use ${_appContext.brand}-program-score)
|
|
18
|
+
|
|
19
|
+
PARAMETERS
|
|
20
|
+
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobdefs. Do NOT use for find, verify, or execute.
|
|
21
|
+
- limit: number (default: 10) — number of jobdefs per page
|
|
22
|
+
- start: number (default: 1) — 1-based page offset
|
|
23
|
+
- where: string (default: '') — optional filter expression
|
|
24
|
+
|
|
25
|
+
ROUTING RULES
|
|
26
|
+
- list jobdefs → { start: 1, limit: 10 }
|
|
27
|
+
- show me 25 jobdefs → { start: 1, limit: 25 }
|
|
28
|
+
- next jobdefs → { start: previousStart + previousLimit, limit: previousLimit }
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
- list jobdefs → { start: 1, limit: 10 }
|
|
32
|
+
- list 25 jobdefs → { start: 1, limit: 25 }
|
|
33
|
+
- next jobdefs → { start: 11, limit: 10 }
|
|
34
|
+
|
|
35
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
36
|
+
- find jobdef abc (use ${_appContext.brand}-find-jobdef)
|
|
37
|
+
- does jobdef X exist (use ${_appContext.brand}-find-jobdef)
|
|
38
|
+
- is jobdef X available (use ${_appContext.brand}-find-jobdef)
|
|
39
|
+
- list jobs (use ${_appContext.brand}-list-jobs)
|
|
40
|
+
- score jobdef abc (use ${_appContext.brand}-jobdef-score)
|
|
41
|
+
- list models (use ${_appContext.brand}-list-models)
|
|
42
|
+
|
|
43
|
+
PAGINATION
|
|
44
|
+
If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
|
|
45
|
+
|
|
46
|
+
ERRORS
|
|
47
|
+
Surface backend error directly; never fabricate jobdef names.
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
let spec = {
|
|
51
|
+
name: 'list-jobdefs',
|
|
52
|
+
description: description,
|
|
53
|
+
inputSchema: z.object({
|
|
54
|
+
intent: z.literal('list'),
|
|
55
|
+
limit: z.number().optional(),
|
|
56
|
+
start: z.number().optional(),
|
|
57
|
+
where: z.string().optional()
|
|
58
|
+
}),
|
|
59
|
+
// No 'server' required; backend context is implicit in helper
|
|
60
|
+
handler: async (params) => {
|
|
61
|
+
// _listJobdefs handles all validation and defaults
|
|
62
|
+
const { intent, ...rest } = params;
|
|
63
|
+
const result = await _listJobdefs(rest);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return spec;
|
|
68
|
+
}
|
|
69
|
+
export default listJobdefs;
|
|
70
|
+
|
package/src/toolSet/listJobs.js
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import _listJobs from '../toolHelpers/_listJobs.js';
|
|
7
|
-
function listJobs(_appContext) {
|
|
8
|
-
const isAgent = _appContext && _appContext.agent;
|
|
9
|
-
let description = isAgent ? `
|
|
10
|
-
list-jobs — list available Job models.
|
|
11
|
-
PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
|
|
12
|
-
RETURNS: array of job names and metadata
|
|
13
|
-
` : `
|
|
14
|
-
list-jobs — enumerate SAS Viya job assets.
|
|
15
|
-
|
|
16
|
-
USE when: list jobs, show jobs, browse jobs, list available jobs, next page
|
|
17
|
-
DO NOT USE for: find single job (use ${_appContext.brand}-find-job), score job (use ${_appContext.brand}-job-score), score jobdef (use ${_appContext.brand}-jobdef-score), sas code (use ${_appContext.brand}-program-score)
|
|
18
|
-
|
|
19
|
-
PARAMETERS
|
|
20
|
-
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobs. Do NOT use for find, verify, or execute.
|
|
21
|
-
- limit: number (default: 10) — number of jobs per page
|
|
22
|
-
- start: number (default: 1) — 1-based page offset
|
|
23
|
-
- where: string (default: '') — optional filter expression
|
|
24
|
-
|
|
25
|
-
ROUTING RULES
|
|
26
|
-
- list jobs → { start: 1, limit: 10 }
|
|
27
|
-
- show me 25 jobs → { start: 1, limit: 25 }
|
|
28
|
-
- next jobs → { start: previousStart + previousLimit, limit: previousLimit }
|
|
29
|
-
|
|
30
|
-
EXAMPLES
|
|
31
|
-
- list jobs → { start: 1, limit: 10 }
|
|
32
|
-
- list 25 jobs → { start: 1, limit: 25 }
|
|
33
|
-
- next jobs → { start: 11, limit: 10 }
|
|
34
|
-
|
|
35
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
36
|
-
- find job abc (use ${_appContext.brand}-find-job)
|
|
37
|
-
- score job abc (use ${_appContext.brand}-job-score)
|
|
38
|
-
- list models (use ${_appContext.brand}-list-models)
|
|
39
|
-
- list tables in lib xyz (use ${_appContext.brand}-list-tables)
|
|
40
|
-
|
|
41
|
-
PAGINATION
|
|
42
|
-
If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
|
|
43
|
-
|
|
44
|
-
ERRORS
|
|
45
|
-
Surface backend error directly; never fabricate job names.
|
|
46
|
-
`;
|
|
47
|
-
|
|
48
|
-
let spec = {
|
|
49
|
-
name: 'list-jobs',
|
|
50
|
-
description: description,
|
|
51
|
-
inputSchema: z.object({
|
|
52
|
-
intent: z.literal('list'),
|
|
53
|
-
limit: z.number().optional(),
|
|
54
|
-
start: z.number().optional(),
|
|
55
|
-
where: z.string().optional()
|
|
56
|
-
}),
|
|
57
|
-
// No 'server' required; backend context is implicit in helper
|
|
58
|
-
handler: async (params) => {
|
|
59
|
-
// _listJob handles all validation and defaults
|
|
60
|
-
const { intent, ...rest } = params;
|
|
61
|
-
const result = await _listJobs(rest);
|
|
62
|
-
return result;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return spec;
|
|
66
|
-
}
|
|
67
|
-
export default listJobs;
|
|
68
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import _listJobs from '../toolHelpers/_listJobs.js';
|
|
7
|
+
function listJobs(_appContext) {
|
|
8
|
+
const isAgent = _appContext && _appContext.agent;
|
|
9
|
+
let description = isAgent ? `
|
|
10
|
+
list-jobs — list available Job models.
|
|
11
|
+
PARAMS: intent ('list', required), start (number, default 1), limit (number, default 10)
|
|
12
|
+
RETURNS: array of job names and metadata
|
|
13
|
+
` : `
|
|
14
|
+
list-jobs — enumerate SAS Viya job assets.
|
|
15
|
+
|
|
16
|
+
USE when: list jobs, show jobs, browse jobs, list available jobs, next page
|
|
17
|
+
DO NOT USE for: find single job (use ${_appContext.brand}-find-job), score job (use ${_appContext.brand}-job-score), score jobdef (use ${_appContext.brand}-jobdef-score), sas code (use ${_appContext.brand}-program-score)
|
|
18
|
+
|
|
19
|
+
PARAMETERS
|
|
20
|
+
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate jobs. Do NOT use for find, verify, or execute.
|
|
21
|
+
- limit: number (default: 10) — number of jobs per page
|
|
22
|
+
- start: number (default: 1) — 1-based page offset
|
|
23
|
+
- where: string (default: '') — optional filter expression
|
|
24
|
+
|
|
25
|
+
ROUTING RULES
|
|
26
|
+
- list jobs → { start: 1, limit: 10 }
|
|
27
|
+
- show me 25 jobs → { start: 1, limit: 25 }
|
|
28
|
+
- next jobs → { start: previousStart + previousLimit, limit: previousLimit }
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
- list jobs → { start: 1, limit: 10 }
|
|
32
|
+
- list 25 jobs → { start: 1, limit: 25 }
|
|
33
|
+
- next jobs → { start: 11, limit: 10 }
|
|
34
|
+
|
|
35
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
36
|
+
- find job abc (use ${_appContext.brand}-find-job)
|
|
37
|
+
- score job abc (use ${_appContext.brand}-job-score)
|
|
38
|
+
- list models (use ${_appContext.brand}-list-models)
|
|
39
|
+
- list tables in lib xyz (use ${_appContext.brand}-list-tables)
|
|
40
|
+
|
|
41
|
+
PAGINATION
|
|
42
|
+
If returned length === limit, hint: next start = start + limit. Empty result with start > 1 means paged past end.
|
|
43
|
+
|
|
44
|
+
ERRORS
|
|
45
|
+
Surface backend error directly; never fabricate job names.
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
let spec = {
|
|
49
|
+
name: 'list-jobs',
|
|
50
|
+
description: description,
|
|
51
|
+
inputSchema: z.object({
|
|
52
|
+
intent: z.literal('list'),
|
|
53
|
+
limit: z.number().optional(),
|
|
54
|
+
start: z.number().optional(),
|
|
55
|
+
where: z.string().optional()
|
|
56
|
+
}),
|
|
57
|
+
// No 'server' required; backend context is implicit in helper
|
|
58
|
+
handler: async (params) => {
|
|
59
|
+
// _listJob handles all validation and defaults
|
|
60
|
+
const { intent, ...rest } = params;
|
|
61
|
+
const result = await _listJobs(rest);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return spec;
|
|
66
|
+
}
|
|
67
|
+
export default listJobs;
|
|
68
|
+
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import _listLibrary from '../toolHelpers/_listLibrary.js';
|
|
7
|
-
function listLibraries(_appContext) {
|
|
8
|
-
const isAgent = _appContext && _appContext.agent;
|
|
9
|
-
let description = isAgent ? `
|
|
10
|
-
list-libraries — list available libraries.
|
|
11
|
-
PARAMS: intent ('list', required), server ('cas'|'sas'|'all', optional), start (number, default 1), limit (number, default 10)
|
|
12
|
-
RETURNS: array of library names and server assignments
|
|
13
|
-
` : `
|
|
14
|
-
list-libraries — enumerate CAS or SAS libraries.
|
|
15
|
-
|
|
16
|
-
USE ONLY when: user explicitly asks to list, browse, or enumerate libraries — "list libraries", "show all libs", "browse libraries", "what libraries are available", "next page". Never use to verify if a specific library exists.
|
|
17
|
-
DO NOT USE for: verify or check if a specific library exists (use ${_appContext.brand}-find-library instead), listing tables in a library (→ ${_appContext.brand}-list-tables), column/table metadata, job execution, models, scoring.
|
|
18
|
-
|
|
19
|
-
PARAMETERS
|
|
20
|
-
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate libraries. Do NOT use for read, find, or verify.
|
|
21
|
-
- server: 'cas' | 'sas' | 'all' (default: 'all')
|
|
22
|
-
- limit: integer > 0 (default: 10)
|
|
23
|
-
- start: 1-based offset (default: 1)
|
|
24
|
-
- where: optional filter expression (default: '')
|
|
25
|
-
|
|
26
|
-
ROUTING RULES
|
|
27
|
-
- "cas libs / cas libraries / in cas" → { server: 'cas' }
|
|
28
|
-
- "sas libs / sas libraries / in sas" → { server: 'sas' }
|
|
29
|
-
- "all libs / all libraries" → { server: 'all' }
|
|
30
|
-
- "list tables in <libname>" → route to list-tables, NOT here
|
|
31
|
-
- server unspecified → default { server: 'all' }
|
|
32
|
-
- "all cas libs" with no limit specified → { server: 'cas', limit: 50 } + paging note
|
|
33
|
-
- "next" after prior call (start:S, limit:L) → { start: S + L, limit: L }
|
|
34
|
-
- ambiguous "list" or "libs" with no context → assume { server: 'cas' }
|
|
35
|
-
|
|
36
|
-
EXAMPLES
|
|
37
|
-
- "list libraries" → { server: 'all', start: 1, limit: 10 }
|
|
38
|
-
- "list libs " → { server: 'all', start: 1, limit: 10 }
|
|
39
|
-
|
|
40
|
-
- "list all libs" → { server: 'all', start: 1, limit: 10 }
|
|
41
|
-
- "list cas libraries" → { server: 'cas', start: 1, limit: 10 }
|
|
42
|
-
- "show me 25 sas libs" → { server: 'sas', limit: 25, start: 1 }
|
|
43
|
-
- "next" (prev: start:1,limit:10) → { server: <same>, start: 11, limit: 10 }
|
|
44
|
-
- "filter cas libs" (no filter given) → ask: "What filter expression should I apply?"
|
|
45
|
-
|
|
46
|
-
NEGATIVE EXAMPLES (do not route here)
|
|
47
|
-
-- "list tables in SASHELP" → ${_appContext.brand}-list-tables
|
|
48
|
-
-- "list models / jobs / jobdefs"→ respective tools
|
|
49
|
-
-- "score a program to create a lib" → ${_appContext.brand}-program-score
|
|
50
|
-
|
|
51
|
-
PAGINATION
|
|
52
|
-
If returned item count === limit, hint: next start = start + limit.
|
|
53
|
-
If start > 1 and result is empty, note paging may have exceeded available items.
|
|
54
|
-
|
|
55
|
-
ERRORS
|
|
56
|
-
Return structured error with a message field. Never hallucinate library names.
|
|
57
|
-
`;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// Canonical kebab-case tool name; legacy aliases preserved for compatibility
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let spec = {
|
|
64
|
-
name: 'list-libraries',
|
|
65
|
-
description: description,
|
|
66
|
-
inputSchema: z.object({
|
|
67
|
-
intent: z.literal('list'),
|
|
68
|
-
server: z.string().optional(),
|
|
69
|
-
limit: z.number().optional(),
|
|
70
|
-
start: z.number().optional(),
|
|
71
|
-
where: z.string().optional()
|
|
72
|
-
}),
|
|
73
|
-
// 'server' has a default so we don't mark it required
|
|
74
|
-
handler: async (params) => {
|
|
75
|
-
const { intent, ...rest } = params;
|
|
76
|
-
rest.server = (rest.server || 'all').toLowerCase();
|
|
77
|
-
let r = await _listLibrary(rest);
|
|
78
|
-
return r;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
return spec;
|
|
82
|
-
}
|
|
83
|
-
export default listLibraries;
|
|
84
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import _listLibrary from '../toolHelpers/_listLibrary.js';
|
|
7
|
+
function listLibraries(_appContext) {
|
|
8
|
+
const isAgent = _appContext && _appContext.agent;
|
|
9
|
+
let description = isAgent ? `
|
|
10
|
+
list-libraries — list available libraries.
|
|
11
|
+
PARAMS: intent ('list', required), server ('cas'|'sas'|'all', optional), start (number, default 1), limit (number, default 10)
|
|
12
|
+
RETURNS: array of library names and server assignments
|
|
13
|
+
` : `
|
|
14
|
+
list-libraries — enumerate CAS or SAS libraries.
|
|
15
|
+
|
|
16
|
+
USE ONLY when: user explicitly asks to list, browse, or enumerate libraries — "list libraries", "show all libs", "browse libraries", "what libraries are available", "next page". Never use to verify if a specific library exists.
|
|
17
|
+
DO NOT USE for: verify or check if a specific library exists (use ${_appContext.brand}-find-library instead), listing tables in a library (→ ${_appContext.brand}-list-tables), column/table metadata, job execution, models, scoring.
|
|
18
|
+
|
|
19
|
+
PARAMETERS
|
|
20
|
+
- intent: must be 'list' — only pass if user explicitly asked to list/enumerate libraries. Do NOT use for read, find, or verify.
|
|
21
|
+
- server: 'cas' | 'sas' | 'all' (default: 'all')
|
|
22
|
+
- limit: integer > 0 (default: 10)
|
|
23
|
+
- start: 1-based offset (default: 1)
|
|
24
|
+
- where: optional filter expression (default: '')
|
|
25
|
+
|
|
26
|
+
ROUTING RULES
|
|
27
|
+
- "cas libs / cas libraries / in cas" → { server: 'cas' }
|
|
28
|
+
- "sas libs / sas libraries / in sas" → { server: 'sas' }
|
|
29
|
+
- "all libs / all libraries" → { server: 'all' }
|
|
30
|
+
- "list tables in <libname>" → route to list-tables, NOT here
|
|
31
|
+
- server unspecified → default { server: 'all' }
|
|
32
|
+
- "all cas libs" with no limit specified → { server: 'cas', limit: 50 } + paging note
|
|
33
|
+
- "next" after prior call (start:S, limit:L) → { start: S + L, limit: L }
|
|
34
|
+
- ambiguous "list" or "libs" with no context → assume { server: 'cas' }
|
|
35
|
+
|
|
36
|
+
EXAMPLES
|
|
37
|
+
- "list libraries" → { server: 'all', start: 1, limit: 10 }
|
|
38
|
+
- "list libs " → { server: 'all', start: 1, limit: 10 }
|
|
39
|
+
|
|
40
|
+
- "list all libs" → { server: 'all', start: 1, limit: 10 }
|
|
41
|
+
- "list cas libraries" → { server: 'cas', start: 1, limit: 10 }
|
|
42
|
+
- "show me 25 sas libs" → { server: 'sas', limit: 25, start: 1 }
|
|
43
|
+
- "next" (prev: start:1,limit:10) → { server: <same>, start: 11, limit: 10 }
|
|
44
|
+
- "filter cas libs" (no filter given) → ask: "What filter expression should I apply?"
|
|
45
|
+
|
|
46
|
+
NEGATIVE EXAMPLES (do not route here)
|
|
47
|
+
-- "list tables in SASHELP" → ${_appContext.brand}-list-tables
|
|
48
|
+
-- "list models / jobs / jobdefs"→ respective tools
|
|
49
|
+
-- "score a program to create a lib" → ${_appContext.brand}-program-score
|
|
50
|
+
|
|
51
|
+
PAGINATION
|
|
52
|
+
If returned item count === limit, hint: next start = start + limit.
|
|
53
|
+
If start > 1 and result is empty, note paging may have exceeded available items.
|
|
54
|
+
|
|
55
|
+
ERRORS
|
|
56
|
+
Return structured error with a message field. Never hallucinate library names.
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// Canonical kebab-case tool name; legacy aliases preserved for compatibility
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
let spec = {
|
|
64
|
+
name: 'list-libraries',
|
|
65
|
+
description: description,
|
|
66
|
+
inputSchema: z.object({
|
|
67
|
+
intent: z.literal('list'),
|
|
68
|
+
server: z.string().optional(),
|
|
69
|
+
limit: z.number().optional(),
|
|
70
|
+
start: z.number().optional(),
|
|
71
|
+
where: z.string().optional()
|
|
72
|
+
}),
|
|
73
|
+
// 'server' has a default so we don't mark it required
|
|
74
|
+
handler: async (params) => {
|
|
75
|
+
const { intent, ...rest } = params;
|
|
76
|
+
rest.server = (rest.server || 'all').toLowerCase();
|
|
77
|
+
let r = await _listLibrary(rest);
|
|
78
|
+
return r;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return spec;
|
|
82
|
+
}
|
|
83
|
+
export default listLibraries;
|
|
84
|
+
|
package/src/toolSet/masScore.js
CHANGED
|
@@ -1,95 +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
|
-
|
|
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
|
+
|