@sassoftware/sas-score-mcp-serverjs 1.0.1-30 → 1.0.1-32

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.
Files changed (50) hide show
  1. package/.skills/agents/sas-score-mcp-serverjs-agent.md +1 -1
  2. package/.skills/copilot-instructions.md +57 -26
  3. package/.skills/skills/detail-strategy/SKILL.md +95 -49
  4. package/.skills/skills/find-resources/SKILL.md +38 -31
  5. package/.skills/skills/list-resource/SKILL.md +93 -33
  6. package/.skills/skills/request-routing/SKILL.md +9 -4
  7. package/.skills/skills/score-strategy/SKILL.md +21 -3
  8. package/README.md +62 -43
  9. package/openApi.yaml +121 -121
  10. package/package.json +7 -5
  11. package/scripts/docs/oauth-http-transport.md +2 -2
  12. package/scripts/plot_msrp_usa.py +49 -0
  13. package/scripts/refreshtoken.js +57 -57
  14. package/src/createMcpServer.js +0 -1
  15. package/src/openApi.yaml +121 -121
  16. package/src/toolHelpers/_findJob.js +12 -0
  17. package/src/toolHelpers/_findJobdef.js +10 -0
  18. package/src/toolHelpers/_findLibrary.js +10 -0
  19. package/src/toolHelpers/_findMas.js +12 -0
  20. package/src/toolHelpers/_findTable.js +10 -0
  21. package/src/toolHelpers/_listJobs.js +2 -2
  22. package/src/toolHelpers/{_listModels.js → _listMas.js} +4 -4
  23. package/src/toolSet/devaScore.js +61 -61
  24. package/src/toolSet/findJob.js +2 -1
  25. package/src/toolSet/findJobdef.js +2 -2
  26. package/src/toolSet/findLibrary.js +68 -68
  27. package/src/toolSet/findMas.js +59 -0
  28. package/src/toolSet/findTable.js +2 -2
  29. package/src/toolSet/jobInfo.js +59 -0
  30. package/src/toolSet/jobdefInfo.js +59 -0
  31. package/src/toolSet/listJobdefs.js +61 -61
  32. package/src/toolSet/listJobs.js +61 -61
  33. package/src/toolSet/listLibraries.js +78 -78
  34. package/src/toolSet/{listModels.js → listMas.js} +61 -56
  35. package/src/toolSet/listTables.js +66 -66
  36. package/src/toolSet/makeTools.js +21 -12
  37. package/src/toolSet/{modelInfo.js → masInfo.js} +12 -12
  38. package/src/toolSet/{modelScore.js → masScore.js} +3 -3
  39. package/src/toolSet/readTable.js +63 -63
  40. package/src/toolSet/runMacro.js +82 -82
  41. package/src/toolSet/sasQuery.js +77 -77
  42. package/src/toolSet/setContext.js +65 -65
  43. package/src/toolSet/superstat.js +61 -61
  44. package/src/toolSet/tableInfo.js +58 -58
  45. package/scripts/optimize_final.py +0 -140
  46. package/scripts/optimize_tools.py +0 -99
  47. package/scripts/setup-skills.js +0 -34
  48. package/scripts/token.txt +0 -1
  49. package/scripts/update_descriptions.py +0 -46
  50. package/src/toolSet/findModel.js +0 -60
@@ -1,82 +1,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 runMacro(_appContext) {
11
- let description = `
12
- run-macro — submit and execute a SAS macro on SAS Viya server.
13
-
14
- USE when: run macro, execute macro with parameters
15
- DO NOT USE for: arbitrary SAS code (use run-sas-program), jobs, jobdefs
16
-
17
- PARAMETERS
18
- - macro: string — macro name without "%" (required)
19
- - scenario: string — parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
20
-
21
- ROUTING RULES
22
- - "run macro abc" → { macro: "abc", scenario: "" }
23
- - "run macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
24
- - "run macro xyz with %let a=1; %let b=2;" → { macro: "xyz", scenario: "%let a=1; %let b=2;" }
25
-
26
- EXAMPLES
27
- - "run macro abc" → { macro: "abc", scenario: "" }
28
- - "run macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
29
-
30
- NEGATIVE EXAMPLES (do not route here)
31
- - "run SAS code" (use run-sas-program)
32
- - "run job X" (use run-job)
33
- - "run jobdef X" (use run-jobdef)
34
-
35
- ERRORS
36
- Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
37
- `;
38
-
39
- let spec = {
40
- name: 'run-macro',
41
- description: description,
42
-
43
- inputSchema: z.object({
44
- macro: z.string(),
45
- scenario: z.string().optional()
46
- }),
47
-
48
- handler: async (params) => {
49
- const scenarioRaw = (params.scenario || '').trim();
50
- let setup = '';
51
- if (scenarioRaw) {
52
- // If the scenario already contains macro syntax, send it through unchanged
53
- const hasMacroSyntax = /%let\b|%[a-zA-Z_]\w*\s*\(|%[a-zA-Z_]\w*\s*;/.test(scenarioRaw) || scenarioRaw.includes('%');
54
- if (hasMacroSyntax) {
55
- setup = scenarioRaw;
56
- } else {
57
- // Convert "x=1,y=abc" -> "%let x=1; %let y=abc;"
58
- setup = scenarioRaw.split(',')
59
- .map(p => p.trim())
60
- .filter(Boolean)
61
- .map(p => {
62
- const [k, ...rest] = p.split('=');
63
- if (!k) return '';
64
- const key = k.trim();
65
- const val = rest.join('=').trim();
66
- return `%let ${key}=${val};`;
67
- })
68
- .filter(Boolean)
69
- .join(' ');
70
- }
71
- }
72
- const src = `${setup} %${params.macro};`;
73
- params.src = src;
74
- let r = await _submitCode(params);
75
- return r;
76
- }
77
- }
78
- return spec;
79
- }
80
-
81
- export default runMacro;
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 runMacro(_appContext) {
11
+ let description = `
12
+ run-macro — submit and execute a SAS macro on SAS Viya server.
13
+
14
+ USE when: run macro, execute macro with parameters
15
+ DO NOT USE for: arbitrary SAS code (use run-sas-program), jobs, jobdefs
16
+
17
+ PARAMETERS
18
+ - macro: string — macro name without "%" (required)
19
+ - scenario: string — parameters or setup code (optional). Accepts: "x=1, y=abc" or "%let x=1; %let y=abc;"
20
+
21
+ ROUTING RULES
22
+ - "run macro abc" → { macro: "abc", scenario: "" }
23
+ - "run macro abc with x=1, y=2" → { macro: "abc", scenario: "x=1, y=2" }
24
+ - "run macro xyz with %let a=1; %let b=2;" → { macro: "xyz", scenario: "%let a=1; %let b=2;" }
25
+
26
+ EXAMPLES
27
+ - "run macro abc" → { macro: "abc", scenario: "" }
28
+ - "run macro summarize with x=1, y=2" → { macro: "summarize", scenario: "x=1, y=2" }
29
+
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "run SAS code" (use run-sas-program)
32
+ - "run job X" (use run-job)
33
+ - "run jobdef X" (use run-jobdef)
34
+
35
+ ERRORS
36
+ Returns log, ods, tables created by macro. Auto-converts "x=1, y=2" to "%let x=1; %let y=2;" format.
37
+ `;
38
+
39
+ let spec = {
40
+ name: 'run-macro',
41
+ description: description,
42
+
43
+ inputSchema: z.object({
44
+ macro: z.string(),
45
+ scenario: z.string().optional()
46
+ }),
47
+
48
+ handler: async (params) => {
49
+ const scenarioRaw = (params.scenario || '').trim();
50
+ let setup = '';
51
+ if (scenarioRaw) {
52
+ // If the scenario already contains macro syntax, send it through unchanged
53
+ const hasMacroSyntax = /%let\b|%[a-zA-Z_]\w*\s*\(|%[a-zA-Z_]\w*\s*;/.test(scenarioRaw) || scenarioRaw.includes('%');
54
+ if (hasMacroSyntax) {
55
+ setup = scenarioRaw;
56
+ } else {
57
+ // Convert "x=1,y=abc" -> "%let x=1; %let y=abc;"
58
+ setup = scenarioRaw.split(',')
59
+ .map(p => p.trim())
60
+ .filter(Boolean)
61
+ .map(p => {
62
+ const [k, ...rest] = p.split('=');
63
+ if (!k) return '';
64
+ const key = k.trim();
65
+ const val = rest.join('=').trim();
66
+ return `%let ${key}=${val};`;
67
+ })
68
+ .filter(Boolean)
69
+ .join(' ');
70
+ }
71
+ }
72
+ const src = `${setup} %${params.macro};`;
73
+ params.src = src;
74
+ let r = await _submitCode(params);
75
+ return r;
76
+ }
77
+ }
78
+ return spec;
79
+ }
80
+
81
+ export default runMacro;
82
+
@@ -1,77 +1,77 @@
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
7
-
8
- function sasQuery() {
9
-
10
- let description = `
11
- sas-query — convert natural language questions into SQL queries and execute them.
12
-
13
- USE when: how many/count/total/average by, aggregated analytics, complex filtering, statistical summaries
14
- DO NOT USE for: raw reads without filtering (use read-table), table structure (use table-info), SAS programs (use run-sas-program), jobs/jobdefs
15
-
16
- PARAMETERS
17
- - table: string — table in lib.table format (required), e.g. "Public.cars" or "sashelp.class"
18
- - query: string — natural language question (required)
19
- - sql: string — pre-generated SQL SELECT (optional, LLM generates)
20
- - job: string (default: 'program') — job name to execute
21
-
22
- ROUTING RULES
23
- - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
24
- - "average salary by department in Public.employees" → { table: "Public.employees", query: "average salary by department", sql: "SELECT department, AVG(salary) FROM Public.employees GROUP BY department" }
25
-
26
- EXAMPLES
27
- - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
28
- - "total sales by region from mylib.sales" → { table: "mylib.sales", query: "total sales by region", sql: "SELECT region, SUM(amount) FROM mylib.sales GROUP BY region" }
29
-
30
- NEGATIVE EXAMPLES (do not route here)
31
- - "read table cars" (use read-table)
32
- - "show 10 rows" (use read-table)
33
- - "table structure" (use table-info)
34
- - "run SAS code" (use run-sas-program)
35
- - "run job/macro" (use run-job/run-macro)
36
-
37
- ERRORS
38
- Returns rows array, columns metadata, log. Returns error if SQL invalid or table not found.
39
- `;
40
-
41
-
42
- let spec = {
43
- name: 'sas-query',
44
- description: description,
45
- inputSchema: z.object({
46
- query: z.string(),
47
- table: z.string(),
48
- sql: z.string().optional()
49
- }),
50
- handler: async (params) => {
51
- let {table,query, sql, job, _appContext} = params;
52
- let sqlinput = (sql == null) ? ' ' : sql.replaceAll(';', ' ').replaceAll('\n', ' ').replaceAll('\r', ' ');
53
-
54
- let iparams = {
55
- scenario: {
56
- table: table,
57
- prompt: query,
58
- sql: sqlinput
59
- },
60
- name: (job == null) ? 'program' : job,
61
- type: 'job',
62
- query: true,
63
- _appContext: _appContext
64
- };
65
- if (sql == null || sql.trim().length === 0) {
66
- return { content: [{ type: 'text', text: 'Error: The SQL statement generated is blank. Please provide a valid natural language query that can be converted to SQL.' }] };
67
- }
68
-
69
- let r = await _jobSubmit(iparams);
70
- return r;
71
-
72
- }
73
- }
74
- return spec;
75
- }
76
- export default sasQuery;
77
-
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 _jobSubmit from '../toolHelpers/_jobSubmit.js';
7
+
8
+ function sasQuery() {
9
+
10
+ let description = `
11
+ sas-query — convert natural language questions into SQL queries and execute them.
12
+
13
+ USE when: how many/count/total/average by, aggregated analytics, complex filtering, statistical summaries
14
+ DO NOT USE for: raw reads without filtering (use read-table), table structure (use table-info), SAS programs (use run-sas-program), jobs/jobdefs
15
+
16
+ PARAMETERS
17
+ - table: string — table in lib.table format (required), e.g. "Public.cars" or "sashelp.class"
18
+ - query: string — natural language question (required)
19
+ - sql: string — pre-generated SQL SELECT (optional, LLM generates)
20
+ - job: string (default: 'program') — job name to execute
21
+
22
+ ROUTING RULES
23
+ - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
24
+ - "average salary by department in Public.employees" → { table: "Public.employees", query: "average salary by department", sql: "SELECT department, AVG(salary) FROM Public.employees GROUP BY department" }
25
+
26
+ EXAMPLES
27
+ - "how many cars by make in sashelp.cars" → { table: "sashelp.cars", query: "how many cars by make", sql: "SELECT make, COUNT(*) FROM sashelp.cars GROUP BY make" }
28
+ - "total sales by region from mylib.sales" → { table: "mylib.sales", query: "total sales by region", sql: "SELECT region, SUM(amount) FROM mylib.sales GROUP BY region" }
29
+
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "read table cars" (use read-table)
32
+ - "show 10 rows" (use read-table)
33
+ - "table structure" (use table-info)
34
+ - "run SAS code" (use run-sas-program)
35
+ - "run job/macro" (use run-job/run-macro)
36
+
37
+ ERRORS
38
+ Returns rows array, columns metadata, log. Returns error if SQL invalid or table not found.
39
+ `;
40
+
41
+
42
+ let spec = {
43
+ name: 'sas-query',
44
+ description: description,
45
+ inputSchema: z.object({
46
+ query: z.string(),
47
+ table: z.string(),
48
+ sql: z.string().optional()
49
+ }),
50
+ handler: async (params) => {
51
+ let {table,query, sql, job, _appContext} = params;
52
+ let sqlinput = (sql == null) ? ' ' : sql.replaceAll(';', ' ').replaceAll('\n', ' ').replaceAll('\r', ' ');
53
+
54
+ let iparams = {
55
+ scenario: {
56
+ table: table,
57
+ prompt: query,
58
+ sql: sqlinput
59
+ },
60
+ name: (job == null) ? 'program' : job,
61
+ type: 'job',
62
+ query: true,
63
+ _appContext: _appContext
64
+ };
65
+ if (sql == null || sql.trim().length === 0) {
66
+ return { content: [{ type: 'text', text: 'Error: The SQL statement generated is blank. Please provide a valid natural language query that can be converted to SQL.' }] };
67
+ }
68
+
69
+ let r = await _jobSubmit(iparams);
70
+ return r;
71
+
72
+ }
73
+ }
74
+ return spec;
75
+ }
76
+ export default sasQuery;
77
+
@@ -1,65 +1,65 @@
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
-
8
- function setContext(_appContext) {
9
- let description = `
10
- set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
-
12
- USE when: switch to CAS server, change compute context, check current context, set both
13
- DO NOT USE for: get variables (use get-env), read data (use read-table), run programs (use run-sas-program)
14
-
15
- PARAMETERS
16
- - cas: string — CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
17
- - sas: string — SAS compute context (optional), e.g. 'SAS Studio Compute Context', 'batch-compute'
18
-
19
- ROUTING RULES
20
- - "use finance-cas-server" → { cas: "finance-cas-server" }
21
- - "switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
22
- - "use finance-cas for CAS and batch-compute for SAS" → { cas: "finance-cas", sas: "batch-compute" }
23
- - "what context am I using" → { } (no params, returns current)
24
-
25
- EXAMPLES
26
- - "use finance-cas-server" → { cas: "finance-cas-server" }
27
- - "switch to batch-compute" → { sas: "batch-compute" }
28
- - "what's my current context" → { }
29
-
30
- NEGATIVE EXAMPLES (do not route here)
31
- - "read table cars" (use read-table)
32
- - "what's the value of X" (use get-env)
33
- - "run program" (use run-sas-program)
34
-
35
- ERRORS
36
- Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
37
- `;
38
-
39
- let spec = {
40
- name: 'set-context',
41
- description: description,
42
- inputSchema: z.object({
43
- cas: z.string().optional(),
44
- sas: z.string().optional()
45
- }),
46
- handler: async (params) => {
47
-
48
- let {cas, sas} = params;
49
- if (typeof cas === 'string' && cas.trim().length > 0) {
50
- _appContext.contexts.cas = cas.trim();
51
- }
52
- if (typeof sas === 'string' && sas.trim().length > 0) {
53
- _appContext.contexts.sas = sas.trim();
54
- }
55
- // Return a structured response without extraneous keys
56
- return {
57
- content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
58
- structuredContent: _appContext.contexts
59
- };
60
- }
61
- }
62
- return spec;
63
- }
64
- export default setContext;
65
-
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
+
8
+ function setContext(_appContext) {
9
+ let description = `
10
+ set-context — set the CAS and SAS server contexts for subsequent tool calls.
11
+
12
+ USE when: switch to CAS server, change compute context, check current context, set both
13
+ DO NOT USE for: get variables (use get-env), read data (use read-table), run programs (use run-sas-program)
14
+
15
+ PARAMETERS
16
+ - cas: string — CAS server name (optional), e.g. 'cas-shared-default', 'finance-cas-server'
17
+ - sas: string — SAS compute context (optional), e.g. 'SAS Studio Compute Context', 'batch-compute'
18
+
19
+ ROUTING RULES
20
+ - "use finance-cas-server" → { cas: "finance-cas-server" }
21
+ - "switch to SAS Studio Compute Context" → { sas: "SAS Studio Compute Context" }
22
+ - "use finance-cas for CAS and batch-compute for SAS" → { cas: "finance-cas", sas: "batch-compute" }
23
+ - "what context am I using" → { } (no params, returns current)
24
+
25
+ EXAMPLES
26
+ - "use finance-cas-server" → { cas: "finance-cas-server" }
27
+ - "switch to batch-compute" → { sas: "batch-compute" }
28
+ - "what's my current context" → { }
29
+
30
+ NEGATIVE EXAMPLES (do not route here)
31
+ - "read table cars" (use read-table)
32
+ - "what's the value of X" (use get-env)
33
+ - "run program" (use run-sas-program)
34
+
35
+ ERRORS
36
+ Returns current or updated context values {cas, sas}. Error if server not found or invalid name.
37
+ `;
38
+
39
+ let spec = {
40
+ name: 'set-context',
41
+ description: description,
42
+ inputSchema: z.object({
43
+ cas: z.string().optional(),
44
+ sas: z.string().optional()
45
+ }),
46
+ handler: async (params) => {
47
+
48
+ let {cas, sas} = params;
49
+ if (typeof cas === 'string' && cas.trim().length > 0) {
50
+ _appContext.contexts.cas = cas.trim();
51
+ }
52
+ if (typeof sas === 'string' && sas.trim().length > 0) {
53
+ _appContext.contexts.sas = sas.trim();
54
+ }
55
+ // Return a structured response without extraneous keys
56
+ return {
57
+ content: [{ type: 'text', text: JSON.stringify(_appContext.contexts) }],
58
+ structuredContent: _appContext.contexts
59
+ };
60
+ }
61
+ }
62
+ return spec;
63
+ }
64
+ export default setContext;
65
+
@@ -1,61 +1,61 @@
1
- /*
2
- * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- import { type } from 'node:os';
6
- import _submitCode from '../toolHelpers/_submitCode.js';
7
- import { z } from 'zod';
8
-
9
- function superstat(_appContext) {
10
- let desc = `
11
- ## superstat: compute superstat for two numbers using SAS programming
12
-
13
- ## Details
14
- This is a tool to demonstrate using SAS programming to score. The SAS program for suprestat is
15
- below. In a real application this would be a more complex program that is
16
- available to the SAS server.
17
-
18
-
19
- ods html style=barrettsblue;
20
- data temp;
21
- superstat = (&a + &b) * 42;
22
- run;
23
- proc print data=temp;
24
- run;
25
- ods html close;
26
- run;
27
-
28
- ## Sample Prompt
29
-
30
- - compute superstat for 1 and 2
31
- - compute superstat for 3,5
32
-
33
- `;
34
- let spec = {
35
- name: 'superstat',
36
- description: desc,
37
- inputSchema: z.object({
38
- a: z.number().optional()
39
- }),
40
- required: ['a', 'b']
41
- },
42
- handler: async (params) => {
43
- let src = `
44
- ods html style=barrettsblue;
45
- data temp;
46
- superstat = (&a + &b) * 42;
47
- run;
48
- proc print data=temp;
49
- run;
50
- ods html close;
51
- run;
52
- `;
53
- params.src = src;
54
- let r = await _submitCode(params);
55
- return r;
56
- }
57
-
58
- };
59
- return spec;
60
- }
61
- export default superstat;
1
+ /*
2
+ * Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type } from 'node:os';
6
+ import _submitCode from '../toolHelpers/_submitCode.js';
7
+ import { z } from 'zod';
8
+
9
+ function superstat(_appContext) {
10
+ let desc = `
11
+ ## superstat: compute superstat for two numbers using SAS programming
12
+
13
+ ## Details
14
+ This is a tool to demonstrate using SAS programming to score. The SAS program for suprestat is
15
+ below. In a real application this would be a more complex program that is
16
+ available to the SAS server.
17
+
18
+
19
+ ods html style=barrettsblue;
20
+ data temp;
21
+ superstat = (&a + &b) * 42;
22
+ run;
23
+ proc print data=temp;
24
+ run;
25
+ ods html close;
26
+ run;
27
+
28
+ ## Sample Prompt
29
+
30
+ - compute superstat for 1 and 2
31
+ - compute superstat for 3,5
32
+
33
+ `;
34
+ let spec = {
35
+ name: 'superstat',
36
+ description: desc,
37
+ inputSchema: z.object({
38
+ a: z.number().optional()
39
+ }),
40
+ required: ['a', 'b']
41
+ },
42
+ handler: async (params) => {
43
+ let src = `
44
+ ods html style=barrettsblue;
45
+ data temp;
46
+ superstat = (&a + &b) * 42;
47
+ run;
48
+ proc print data=temp;
49
+ run;
50
+ ods html close;
51
+ run;
52
+ `;
53
+ params.src = src;
54
+ let r = await _submitCode(params);
55
+ return r;
56
+ }
57
+
58
+ };
59
+ return spec;
60
+ }
61
+ export default superstat;