@sassoftware/sas-score-mcp-serverjs 0.0.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/.babelrc +6 -0
- package/.env +13 -0
- package/.env.http +29 -0
- package/CHANGES.md +2 -0
- package/CONTRIBUTING.md +14 -0
- package/ContributorAgreement.txt +56 -0
- package/LICENSE +205 -0
- package/LICENSES.json +105 -0
- package/QUICK_REFERENCE.md +378 -0
- package/README.md +267 -0
- package/SECURITY.md +31 -0
- package/SUPPORT.md +3 -0
- package/TOOL_DESCRIPTION_TEMPLATE.md +157 -0
- package/TOOL_UPDATES_SUMMARY.md +208 -0
- package/cli.js +214 -0
- package/labs/.subclass.json +13 -0
- package/labs/README.md +4 -0
- package/mcpConfigurations/README.md +3 -0
- package/mcpConfigurations/http.json +8 -0
- package/mcpConfigurations/stdio.json +20 -0
- package/mcpConfigurations/stdiodev.json +20 -0
- package/mcpserver.png +0 -0
- package/openApi.json +106 -0
- package/openApi.yaml +84 -0
- package/package.json +72 -0
- package/sas-mcp-tools-reference.md +600 -0
- package/sasCode/sas-sql-query.sas +33 -0
- package/sasCode/sas_sql_tool.json +237 -0
- package/scripts/getViyaca.sh +8 -0
- package/src/core.js +19 -0
- package/src/coreSSE.js +14 -0
- package/src/corehttp.js +335 -0
- package/src/createHttpTransport.js +26 -0
- package/src/createMcpServer.js +76 -0
- package/src/db/scrModels.js +23 -0
- package/src/toolSet/devaScore.js +69 -0
- package/src/toolSet/findJob.js +90 -0
- package/src/toolSet/findJobdef.js +95 -0
- package/src/toolSet/findLibrary.js +100 -0
- package/src/toolSet/findModel.js +83 -0
- package/src/toolSet/findTable.js +94 -0
- package/src/toolSet/getEnv.js +72 -0
- package/src/toolSet/listJobdefs.js +96 -0
- package/src/toolSet/listJobs.js +110 -0
- package/src/toolSet/listLibraries.js +90 -0
- package/src/toolSet/listModels.js +83 -0
- package/src/toolSet/listTables.js +95 -0
- package/src/toolSet/makeTools.js +75 -0
- package/src/toolSet/mcp server .png +0 -0
- package/src/toolSet/modelInfo.js +87 -0
- package/src/toolSet/modelScore.js +131 -0
- package/src/toolSet/readTable.js +104 -0
- package/src/toolSet/runCasProgram.js +118 -0
- package/src/toolSet/runJob.js +81 -0
- package/src/toolSet/runJobdef.js +85 -0
- package/src/toolSet/runMacro.js +82 -0
- package/src/toolSet/runProgram.js +145 -0
- package/src/toolSet/sasQuery.js +126 -0
- package/src/toolSet/sasQueryTemplate.js +148 -0
- package/src/toolSet/sasQueryTemplate2.js +140 -0
- package/src/toolSet/scrInfo.js +55 -0
- package/src/toolSet/scrScore.js +71 -0
- package/src/toolSet/searchAssets.js +52 -0
- package/src/toolSet/setContext.js +98 -0
- package/src/toolSet/superstat.js +60 -0
- package/src/toolSet/tableInfo.js +102 -0
- package/src/toolhelpers/_catalogSearch.js +87 -0
- package/src/toolhelpers/_getEnv.js +10 -0
- package/src/toolhelpers/_itemsData.js +28 -0
- package/src/toolhelpers/_jobSubmit.js +78 -0
- package/src/toolhelpers/_listJobdefs.js +59 -0
- package/src/toolhelpers/_listJobs.js +63 -0
- package/src/toolhelpers/_listLibrary.js +56 -0
- package/src/toolhelpers/_listModels.js +41 -0
- package/src/toolhelpers/_listTables.js +52 -0
- package/src/toolhelpers/_masDescribe.js +27 -0
- package/src/toolhelpers/_masScoring.js +64 -0
- package/src/toolhelpers/_readTable.js +69 -0
- package/src/toolhelpers/_scrInfo.js +32 -0
- package/src/toolhelpers/_scrScore.js +49 -0
- package/src/toolhelpers/_submitCasl.js +34 -0
- package/src/toolhelpers/_submitCode.js +96 -0
- package/src/toolhelpers/_submitMacro.js +24 -0
- package/src/toolhelpers/_tableColumns.js +61 -0
- package/src/toolhelpers/_tableInfo.js +72 -0
- package/src/toolhelpers/deleteSession.js +13 -0
- package/src/toolhelpers/getLogonPayload.js +100 -0
- package/src/toolhelpers/getOpts.js +43 -0
- package/src/toolhelpers/getOptsViya.js +38 -0
- package/src/toolhelpers/getStoreOpts.js +18 -0
- package/src/toolhelpers/getToken.js +40 -0
- package/src/toolhelpers/refreshToken.js +48 -0
- package/test/README.md +63 -0
- package/test/listLibraries.test.js +245 -0
- package/tool-developer-guide.md +80 -0
- package/types.js +25 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restaf from '@sassoftware/restaf';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async function _listJobdefs(params) {
|
|
9
|
+
let { limit, start, name, _appContext } = params;
|
|
10
|
+
|
|
11
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
12
|
+
let msg = await store.logon(_appContext.logonPayload);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
let { jobDefinitions } = await store.addServices('jobDefinitions');
|
|
16
|
+
let payload = {
|
|
17
|
+
qs: {
|
|
18
|
+
limit: (limit != null) ? limit : 10,
|
|
19
|
+
start: start - 1
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (name != null && name.trim().length > 0) {
|
|
24
|
+
payload.qs = {
|
|
25
|
+
filter: `eq(name, '${name}')`
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
let jobDefList = await store.apiCall(jobDefinitions.links('job-definitions'), payload);
|
|
29
|
+
if (jobDefList.itemsList().size === 0) {
|
|
30
|
+
return { content: [{ type: 'text', text: 'No jobDefinitions found' }] };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let names = {};
|
|
34
|
+
jobDefList.itemsList().map((id, n) => {
|
|
35
|
+
let jname = jobDefList.items(id, 'name');
|
|
36
|
+
let p = jobDefList.items(id, 'data', 'parameters');
|
|
37
|
+
if (names[jname] == null) {
|
|
38
|
+
names[jname] = { parameters: (p == null) ? {} : p.toJS() };
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
let response = {jobDefinitions: Object.keys(names)};
|
|
43
|
+
if (name != null) {
|
|
44
|
+
response = { name: name, parameters: names[name].parameters };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
49
|
+
structuredContent: response,
|
|
50
|
+
hint: (Object.keys(names).length === (limit || 10)) ? `next page start=${(start || 1) + (limit || 10)}` : undefined
|
|
51
|
+
};
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error('Error in _listJobdefs', err);
|
|
54
|
+
return { isError: true, content: [{ type: 'text', text: `Error retrieving job definitions: ${err}` }] };
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default _listJobdefs;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import restaf from '@sassoftware/restaf';
|
|
7
|
+
|
|
8
|
+
async function _listJobs(params) {
|
|
9
|
+
let { limit, start, name, _appContext } = params;
|
|
10
|
+
|
|
11
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
12
|
+
let msg = await store.logon(_appContext.logonPayload);
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
let { jobExecution } = await store.addServices('jobExecution');
|
|
16
|
+
try {
|
|
17
|
+
let payload = {
|
|
18
|
+
qs: {
|
|
19
|
+
limit: (limit != null) ? limit : 10,
|
|
20
|
+
start: start - 1
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (name != null && name.trim().length > 0) {
|
|
25
|
+
payload.qs = {
|
|
26
|
+
filter: `eq(name, '${name}')`
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.error('payload', JSON.stringify(payload, null, 2));
|
|
30
|
+
let jobList = await store.apiCall(jobExecution.links('jobs'), payload);
|
|
31
|
+
if (jobList.itemsList().size === 0) {
|
|
32
|
+
return { content: [{ type: 'text', text: 'No jobs found' }] };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let names = {};
|
|
36
|
+
|
|
37
|
+
jobList.itemsList().map((id, n) => {
|
|
38
|
+
let jname = jobList.items(id, 'data', 'jobRequest', 'name');
|
|
39
|
+
|
|
40
|
+
if (names[jname] == null) {
|
|
41
|
+
let value = jobList.items(id, 'data', 'jobRequest', 'jobDefinition', 'parameters');
|
|
42
|
+
names[jname] = {parameters: (value == null) ? {} : value.toJS() };
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
let response = {jobs: Object.keys(names)};
|
|
47
|
+
|
|
48
|
+
if (name != null) {
|
|
49
|
+
response = { name: name, parameters: names[name].parameters };
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
53
|
+
structuredContent: response,
|
|
54
|
+
hint: (Object.keys(names).length === (limit || 10)) ? `next page start=${(start || 1) + (limit || 10)}` : undefined
|
|
55
|
+
};
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('Error in _listJobs', err);
|
|
58
|
+
return { isError: true, content: [{ type: 'text', text: `Error retrieving jobs: ${err}` }] };
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default _listJobs;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import restafedit from '@sassoftware/restafedit';
|
|
7
|
+
import deleteSession from './deleteSession.js';
|
|
8
|
+
|
|
9
|
+
async function _listLibrary(params ){
|
|
10
|
+
|
|
11
|
+
let { server, limit, start, name, _appContext } = params;
|
|
12
|
+
|
|
13
|
+
let config = {
|
|
14
|
+
casServerName: _appContext.cas,
|
|
15
|
+
computeContext: _appContext.sas,
|
|
16
|
+
source: (server === 'sas') ? 'compute' : server,
|
|
17
|
+
table: null
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// setup request control
|
|
22
|
+
let appControl = await restafedit.setup(
|
|
23
|
+
_appContext.logonPayload,
|
|
24
|
+
config
|
|
25
|
+
,null,{},'user',{}, {}, _appContext.storeConfig
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// query parameters
|
|
29
|
+
let payload = {
|
|
30
|
+
qs: {
|
|
31
|
+
limit: (limit != null) ? limit : 10,
|
|
32
|
+
start: start - 1
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
if (name != null) {
|
|
37
|
+
payload.qs = {
|
|
38
|
+
filter: `eq(name, '${name}')`
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let items = await restafedit.getLibraryList(appControl, payload);
|
|
43
|
+
let response = {libraries: items};
|
|
44
|
+
await deleteSession(appControl);
|
|
45
|
+
|
|
46
|
+
return { content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
47
|
+
structuredContent: response
|
|
48
|
+
};
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error(JSON.stringify(err));
|
|
51
|
+
await deleteSession(appControl);
|
|
52
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default _listLibrary;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import restaf from '@sassoftware/restaf';
|
|
7
|
+
|
|
8
|
+
async function _listModels(params) {
|
|
9
|
+
let { limit, start , name, _appContext} = params;;
|
|
10
|
+
// setup
|
|
11
|
+
|
|
12
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
await store.logon(_appContext.logonPayload);
|
|
16
|
+
let { microanalyticScore } = await store.addServices('microanalyticScore');
|
|
17
|
+
let payload = {
|
|
18
|
+
qs: {
|
|
19
|
+
limit: Math.max(limit,1),
|
|
20
|
+
start: Math.max(start-1, 0)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (name != null) {
|
|
24
|
+
payload.qs = {
|
|
25
|
+
filter: `eq(name, '${name}')`
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
let result = await store.apiCall(microanalyticScore.links('modules'), payload);
|
|
29
|
+
if (result.itemsList().size === 0) {
|
|
30
|
+
return { content: [{ type: 'text', text: `No models exist in MAS server` }]};
|
|
31
|
+
}
|
|
32
|
+
let list = {models: result.itemsList().toJS()};
|
|
33
|
+
return { content: [{ type: 'text', text: JSON.stringify(list) }],
|
|
34
|
+
structuredContent: list
|
|
35
|
+
};
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default _listModels;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import restafedit from '@sassoftware/restafedit';
|
|
7
|
+
|
|
8
|
+
async function _listTables(params) {
|
|
9
|
+
let { server, lib, limit, start, name, _appContext} = params;
|
|
10
|
+
|
|
11
|
+
let config = {
|
|
12
|
+
casServerName: _appContext.cas,
|
|
13
|
+
computeContext: _appContext.sas,
|
|
14
|
+
source: (server === 'sas') ? 'compute' : server,
|
|
15
|
+
table: null
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
let appControl = await restafedit.setup(
|
|
20
|
+
_appContext.logonPayload,
|
|
21
|
+
config,
|
|
22
|
+
null,/* create a session */
|
|
23
|
+
{},
|
|
24
|
+
'user',
|
|
25
|
+
_appContext.storeConfig
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
let payload = {
|
|
29
|
+
qs: {
|
|
30
|
+
limit: (typeof limit === 'number') ? limit : 10, // Use provided limit or default to 10
|
|
31
|
+
start: (typeof start === 'number') ? Math.max(0, start - 1) : 0,
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (name != null) {
|
|
36
|
+
// Normalize to upper-case to match table name casing in CAS (e.g. COSTCHANGE)
|
|
37
|
+
const nameVal = ('' + name).toUpperCase();
|
|
38
|
+
payload.qs.filter = `eq(name, '${nameVal}')`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let items = await restafedit.getTableList(lib, appControl, payload);
|
|
42
|
+
let response = {tables: items};
|
|
43
|
+
return {content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
44
|
+
structuredContent: response};
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error(JSON.stringify(err));
|
|
47
|
+
return {isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default _listTables;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restaflib from '@sassoftware/restaflib';
|
|
6
|
+
import restaf from '@sassoftware/restaf';
|
|
7
|
+
|
|
8
|
+
async function _masDescribe(params) {
|
|
9
|
+
// setup
|
|
10
|
+
let {model, _appContext} = params;
|
|
11
|
+
let { masSetup, masDescribe } = restaflib;
|
|
12
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
let masControl = await masSetup(store, [model], _appContext.logonPayload);
|
|
16
|
+
let describe = await masDescribe(masControl, model, null,true);
|
|
17
|
+
let response = {decription: describe};
|
|
18
|
+
return { content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
19
|
+
structuredContent: response
|
|
20
|
+
};
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error(err);
|
|
23
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default _masDescribe;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restaflib from '@sassoftware/restaflib';
|
|
6
|
+
import restaf from '@sassoftware/restaf';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async function _masScoring(params) {
|
|
10
|
+
|
|
11
|
+
// setup
|
|
12
|
+
let {model, scenario, uflag, _appContext} = params;
|
|
13
|
+
let { masSetup, masDescribe, masRun } = restaflib;
|
|
14
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
15
|
+
|
|
16
|
+
let inputs = {};
|
|
17
|
+
let masControl;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
|
|
21
|
+
masControl = await masSetup(store, [model], _appContext.logonPayload);
|
|
22
|
+
let describe = await masDescribe(masControl, model);
|
|
23
|
+
let inputs = {};
|
|
24
|
+
let types = {};
|
|
25
|
+
describe.forEach(d => {
|
|
26
|
+
inputs[d.name] = null;
|
|
27
|
+
types[d.name] = d.type;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (scenario === null) {
|
|
31
|
+
// if scenario is empty, return the inputs
|
|
32
|
+
return { content: [{ type: 'text', text: JSON.stringify(inputs) }] };
|
|
33
|
+
}
|
|
34
|
+
let iscenario = {};
|
|
35
|
+
|
|
36
|
+
for (let v in inputs) {
|
|
37
|
+
let v1 = (uflag === true) ? v.substring(0, v.length - 1) : v;
|
|
38
|
+
let t = (scenario[v1] == null) ? null : scenario[v1];
|
|
39
|
+
t = (types[v] === 'decimal' && typeof t === 'string' ) ? parseFloat(t) : t;
|
|
40
|
+
iscenario[v] = t;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let result = await masRun(store, masControl, model, iscenario);
|
|
44
|
+
|
|
45
|
+
// add a unique key for the result
|
|
46
|
+
|
|
47
|
+
let r = {...result, ...iscenario};
|
|
48
|
+
let t = '';
|
|
49
|
+
let sep = ''
|
|
50
|
+
for (let k in r) {
|
|
51
|
+
t += sep + k + '=' + r[k];
|
|
52
|
+
sep = ', ';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { content: [{ type: 'text', text: JSON.stringify(r)}], structuredContent: r};
|
|
56
|
+
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error('Error in _masScoring:', err);
|
|
59
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify({ status: { statusCode: 2, msg: err } }) }] };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default _masScoring;
|
|
64
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restafedit from '@sassoftware/restafedit';
|
|
6
|
+
import deleteSession from './deleteSession.js';
|
|
7
|
+
|
|
8
|
+
async function _readTable(params) {
|
|
9
|
+
let { table, lib, start, limit, server, format, where, _appContext } = params;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if (table.includes('.')) {
|
|
13
|
+
let parts = table.split('.');
|
|
14
|
+
lib = parts[0];
|
|
15
|
+
table = parts[1];
|
|
16
|
+
}
|
|
17
|
+
let itable = { name: table };
|
|
18
|
+
if (server === 'cas') {
|
|
19
|
+
itable.caslib = lib;
|
|
20
|
+
} else {
|
|
21
|
+
itable.libref = lib;
|
|
22
|
+
}
|
|
23
|
+
let config = {
|
|
24
|
+
casServerName: _appContext.cas,
|
|
25
|
+
computeContext: _appContext.sas,
|
|
26
|
+
source: (server === 'sas') ? 'compute' : server,
|
|
27
|
+
casServer: _appContext.cas,
|
|
28
|
+
table: itable,
|
|
29
|
+
|
|
30
|
+
initialFetch: {
|
|
31
|
+
qs: {
|
|
32
|
+
start: (start == null) ? 0 : start - 1, // Adjust for 0-based index
|
|
33
|
+
limit: limit,
|
|
34
|
+
format: format || false,
|
|
35
|
+
where: where || ''
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let appControl = {};
|
|
41
|
+
try {
|
|
42
|
+
appControl = await restafedit.setup(
|
|
43
|
+
_appContext.logonPayload,
|
|
44
|
+
config,
|
|
45
|
+
null,/* create a sessiion */
|
|
46
|
+
{},
|
|
47
|
+
'user',
|
|
48
|
+
_appContext.storeConfig
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
await restafedit.scrollTable('first', appControl);
|
|
52
|
+
|
|
53
|
+
let outdata = appControl.state.data.map((d) => {
|
|
54
|
+
delete d._rowIndex;
|
|
55
|
+
delete d._modified;
|
|
56
|
+
delete d._index_;
|
|
57
|
+
return d;
|
|
58
|
+
});
|
|
59
|
+
let tabled = { tabled: outdata };
|
|
60
|
+
let t = (limit === 1) ? JSON.stringify(outdata[0]) : JSON.stringify(tabled);
|
|
61
|
+
return { content: [{ type: 'text', text: t }], structuredContent: tabled };
|
|
62
|
+
|
|
63
|
+
} catch (err) {
|
|
64
|
+
await deleteSession(appControl);
|
|
65
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export default _readTable;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
|
|
8
|
+
async function _scrInfo(params) {
|
|
9
|
+
let {url} = params;
|
|
10
|
+
let config = {
|
|
11
|
+
method: 'GET',
|
|
12
|
+
url: url + '/apiMeta/api',
|
|
13
|
+
headers: {
|
|
14
|
+
'Accept': 'application/json'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
console.error('[Note] Config:', config);
|
|
19
|
+
let response = await axios(config);
|
|
20
|
+
console.error('[Note] Response status:', response.status);
|
|
21
|
+
let r = {
|
|
22
|
+
input: response.data.components.schemas.SCRInput.properties.data.properties,
|
|
23
|
+
output: response.data.components.schemas.SCROutput.properties.data.properties
|
|
24
|
+
};
|
|
25
|
+
console.error('[Note] Response data:', JSON.stringify(r, null, 2));
|
|
26
|
+
return {content: [{ type: 'text', text: JSON.stringify(r)}], structuredContent: r};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return {isError: true,content: [{ type: 'text', text: JSON.stringify(error) }]};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export default _scrInfo;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async function _scrScore(params) {
|
|
10
|
+
let { url, scenario} = params;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
let data = scenario.split(',').reduce((acc, pair) => {
|
|
14
|
+
let [key, value] = pair.split('=');
|
|
15
|
+
acc[key.trim()] = value.trim();
|
|
16
|
+
return acc;
|
|
17
|
+
}, {});
|
|
18
|
+
|
|
19
|
+
let config = {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
url: url,
|
|
22
|
+
headers: {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'Accept': 'application/json'
|
|
25
|
+
},
|
|
26
|
+
data: data
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
console.error('[Note] Config:', config);
|
|
31
|
+
let response = await axios(config);
|
|
32
|
+
console.error('[Note] Response status:', response.status);
|
|
33
|
+
console.error('[Note] Response data:', response.data);
|
|
34
|
+
let t = ' ';
|
|
35
|
+
let sep = ''
|
|
36
|
+
for (let k in r) {
|
|
37
|
+
t += sep + k + '=' + r[k];
|
|
38
|
+
sep = ', ';
|
|
39
|
+
}
|
|
40
|
+
console.error('t', t);
|
|
41
|
+
let r = { ...response.data, ...scenario }; // merge the response with the scenario and add a unique key
|
|
42
|
+
return { content: [{ type: 'text', text: JSON.stringify(r) }], structuredContent: r };
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(error) }] };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export default _scrScore;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restaflib from '@sassoftware/restaflib';
|
|
6
|
+
|
|
7
|
+
async function _submitCasl(params) {
|
|
8
|
+
let { src, args, _appContext } = params;
|
|
9
|
+
|
|
10
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
11
|
+
|
|
12
|
+
let session = await restaflib.casSetup(store, _appContext.logonPayload, null, _appContext.cas);
|
|
13
|
+
if (session == null) {
|
|
14
|
+
return {content: [{ type: 'text', text: 'Could not create a cas session' }]};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
try {
|
|
19
|
+
let r = await caslRun(store, session, src, (args == null) ? {} : args, true);
|
|
20
|
+
await store.apiCall( session.links( 'delete' ) );
|
|
21
|
+
|
|
22
|
+
return {content: [{ type: 'text', text: JSON.stringify(r.items()) }], structuredContent: r.items() };
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.error(err);
|
|
25
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
console.error(err);
|
|
30
|
+
await store.apiCall( session.links( 'delete' ) );
|
|
31
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export default _submitCasl;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import restaf from '@sassoftware/restaf';
|
|
6
|
+
import restaflib from '@sassoftware/restaflib';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async function _submitCode(params) {
|
|
10
|
+
let { output, limit, args, src, _appContext } = params;
|
|
11
|
+
try {
|
|
12
|
+
// setup
|
|
13
|
+
let store = restaf.initStore(_appContext.storeConfig);
|
|
14
|
+
|
|
15
|
+
// get compute sessio, run sas code and retrieve result
|
|
16
|
+
|
|
17
|
+
let computeSession = await restaflib.computeSetup(store, _appContext.sas, _appContext.logonPayload);
|
|
18
|
+
let computeSummary = await restaflib.computeRun(store, computeSession, src, args);
|
|
19
|
+
|
|
20
|
+
let jobStatus = computeSummary.SASJobStatus;
|
|
21
|
+
let structuredOutput = {};
|
|
22
|
+
if (jobStatus === 'failed' || jobStatus === 'error' || jobStatus === 'running') {
|
|
23
|
+
let msg = `Job ended with status of ${jobStatus}. Please check the log for errors.`;
|
|
24
|
+
let log = await computeResults(store, computeSummary, 'log');
|
|
25
|
+
let status = { status: { statusCode: 2, msg: msg } };
|
|
26
|
+
structuredOutput = { status, log: log2html(log) };
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
let ods = await restaflib.computeResults(store, computeSummary, "ods");
|
|
30
|
+
let log = await restaflib.computeResults(store, computeSummary, "log");
|
|
31
|
+
let listing = await restaflib.computeResults(store, computeSummary, "listing");
|
|
32
|
+
let tables = await restaflib.computeResults(store, computeSummary, 'tables');
|
|
33
|
+
let cc = jobStatus === 'warning' ? 1 : 0;
|
|
34
|
+
let status = { status: { statusCode: cc, msg: `Job completed with status ${jobStatus}` } };
|
|
35
|
+
|
|
36
|
+
let rows = [];
|
|
37
|
+
let notes = ' ';
|
|
38
|
+
let tabled = [];
|
|
39
|
+
if (output != null && output.trim().length > 0 && output.trim().toLowerCase() !== 'none') {
|
|
40
|
+
if (tables.includes(output.toUpperCase()) === false) {
|
|
41
|
+
let msg = `The requested output table ${output} was not found in the response.
|
|
42
|
+
Please check the tables element for available tables.`;
|
|
43
|
+
notes = { status: { statusCode: 1, msg: msg } };
|
|
44
|
+
} else {
|
|
45
|
+
let tpayload = {
|
|
46
|
+
qs: {
|
|
47
|
+
limit: (limit != null) ? limit : 100,
|
|
48
|
+
start: 0
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
rows = await restaflib.computeFetchData(store, computeSummary, output, null, tpayload);
|
|
52
|
+
let schema = rows.schema;
|
|
53
|
+
let data = rows.rows;
|
|
54
|
+
tabled = data.map(row => {
|
|
55
|
+
let obj = {};
|
|
56
|
+
schema.forEach((col, index) => {
|
|
57
|
+
obj[col.name] = row[index];
|
|
58
|
+
});
|
|
59
|
+
return obj; });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
structuredOutput = { status, ods, log: log2html(log), listing: log2html(listing), tables: tables, output: output, tabled: tabled, notes: notes };
|
|
63
|
+
}
|
|
64
|
+
// add output tables next
|
|
65
|
+
|
|
66
|
+
// cleanup
|
|
67
|
+
await store.apiCall(computeSession.links('delete'));
|
|
68
|
+
|
|
69
|
+
// return results in the format the LLM expects
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
content: [{ type: 'text', text: JSON.stringify(structuredOutput) }],
|
|
73
|
+
structuredContent: structuredOutput
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Oops! Something went wrong
|
|
78
|
+
console.error(`Error in _submitCode: ${JSON.stringify(error)}`);
|
|
79
|
+
let e = { error: error };
|
|
80
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(e) }], structuredContent: e };
|
|
81
|
+
}
|
|
82
|
+
function log2html(log) {
|
|
83
|
+
let logText = '';
|
|
84
|
+
// eslint-disable-next-line array-callback-return
|
|
85
|
+
log.map((data) => {
|
|
86
|
+
let line = data.line.replace(/(\r\n|\n|\r)/gm, "");
|
|
87
|
+
if (line.length === 0) {
|
|
88
|
+
logText = logText + '\n';
|
|
89
|
+
} else { }
|
|
90
|
+
logText = logText + line + '\n';
|
|
91
|
+
});
|
|
92
|
+
return logText;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default _submitCode;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import _submitCode from './_submitCode.js';
|
|
7
|
+
|
|
8
|
+
async function _submitMacro(params) {
|
|
9
|
+
let {macro, scenario, _appContext} = params;
|
|
10
|
+
try {
|
|
11
|
+
let src = ` %${macro};$scenario; `;
|
|
12
|
+
// setup
|
|
13
|
+
let iparams = {src: src, _appContext: _appContext};
|
|
14
|
+
return await _submitCode( iparams);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
// Oops! Something went wrong
|
|
18
|
+
console.error(`Error in _submitCode: ${JSON.stringify(error)}`);
|
|
19
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify(error) }] }
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export default _submitMacro;
|