@sassoftware/sas-score-mcp-serverjs 1.0.1-32 → 1.0.1-34
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/agents/sas-score-mcp-serverjs-agent.md +16 -179
- package/.skills/copilot-instructions.md +38 -255
- package/.skills/decision-trees/_primitives.yaml +8 -0
- package/.skills/decision-trees/job.yaml +33 -0
- package/.skills/decision-trees/jobdef.yaml +33 -0
- package/.skills/decision-trees/mas.yaml +35 -0
- package/.skills/decision-trees/scr.yaml +16 -0
- package/.skills/decision-trees/table.yaml +57 -0
- package/.skills/skills/README.md +1 -1
- package/.skills/skills/detail-strategy/SKILL.md +9 -10
- package/.skills/skills/find-resources/SKILL.md +13 -7
- package/.skills/skills/list-resource/SKILL.md +7 -0
- package/.skills/skills/read-strategy/SKILL.md +6 -1
- package/.skills/skills/request-routing/SKILL.md +72 -98
- package/.skills/skills/score-strategy/SKILL.md +5 -0
- package/package.json +1 -1
- package/scripts/plot_msrp_usa.py +49 -49
- package/src/toolHelpers/_findMas.js +11 -11
- package/src/toolHelpers/_findScr.js +31 -0
- package/src/toolSet/devaScore.js +5 -5
- package/src/toolSet/findJob.js +9 -6
- package/src/toolSet/findJobdef.js +7 -7
- package/src/toolSet/findLibrary.js +7 -7
- package/src/toolSet/findMas.js +6 -6
- package/src/toolSet/findTable.js +6 -6
- package/src/toolSet/getEnv.js +6 -6
- package/src/toolSet/jobInfo.js +4 -4
- package/src/toolSet/jobdefInfo.js +4 -4
- package/src/toolSet/listJobdefs.js +5 -5
- package/src/toolSet/listJobs.js +5 -5
- package/src/toolSet/listLibraries.js +4 -4
- package/src/toolSet/listMas.js +4 -4
- package/src/toolSet/listTables.js +5 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
resource: "table"
|
|
3
|
+
description: "Decision tree for table operations. Use sas-score-sas-query for aggregation/query requests; otherwise use sas-score-read-table for raw rows."
|
|
4
|
+
intents:
|
|
5
|
+
list:
|
|
6
|
+
parse:
|
|
7
|
+
lib: "$lib"
|
|
8
|
+
exec:
|
|
9
|
+
tool: "list-tables"
|
|
10
|
+
args:
|
|
11
|
+
lib: "$lib"
|
|
12
|
+
start: 1
|
|
13
|
+
limit: 10
|
|
14
|
+
format: "list of tables"
|
|
15
|
+
find:
|
|
16
|
+
parse:
|
|
17
|
+
lib: "$lib"
|
|
18
|
+
name: "$name"
|
|
19
|
+
exec:
|
|
20
|
+
tool: "find-table"
|
|
21
|
+
args:
|
|
22
|
+
lib: "$lib"
|
|
23
|
+
name: "$name"
|
|
24
|
+
format: "find response"
|
|
25
|
+
read:
|
|
26
|
+
parse:
|
|
27
|
+
lib: "$lib"
|
|
28
|
+
table: "$table"
|
|
29
|
+
where: "$where"
|
|
30
|
+
aggregation_requested: "$aggregation_requested" # boolean inferred from request
|
|
31
|
+
aggregation_query: "$aggregation_query"
|
|
32
|
+
verify:
|
|
33
|
+
tool: "find-table"
|
|
34
|
+
args:
|
|
35
|
+
lib: "$lib"
|
|
36
|
+
name: "$table"
|
|
37
|
+
decision:
|
|
38
|
+
- condition: "aggregation_requested == true"
|
|
39
|
+
exec:
|
|
40
|
+
tool: "sas-score-sas-query"
|
|
41
|
+
args:
|
|
42
|
+
table: "$lib.$table"
|
|
43
|
+
query: "$aggregation_query"
|
|
44
|
+
- condition: "default"
|
|
45
|
+
exec:
|
|
46
|
+
tool: "sas-score-read-table"
|
|
47
|
+
args:
|
|
48
|
+
lib: "$lib"
|
|
49
|
+
table: "$table"
|
|
50
|
+
where: "$where"
|
|
51
|
+
format: "rows or aggregated result"
|
|
52
|
+
read_and_score:
|
|
53
|
+
description: "Compose read then score (read decision chooses sas-query vs read-table)."
|
|
54
|
+
compose:
|
|
55
|
+
- step: "table.read"
|
|
56
|
+
- step: "mas.score"
|
|
57
|
+
format: "rows with appended predictions"
|
package/.skills/skills/README.md
CHANGED
|
@@ -66,7 +66,7 @@ Always verify resources exist before executing (except SCR which has no pre-chec
|
|
|
66
66
|
|---|---|
|
|
67
67
|
| Find library | sas-score-find-library |
|
|
68
68
|
| Find table | sas-score-find-table |
|
|
69
|
-
| Find model (MAS) | sas-score-find-
|
|
69
|
+
| Find model (MAS) | sas-score-find-mas |
|
|
70
70
|
| Find job | sas-score-find-job |
|
|
71
71
|
| Find jobdef | sas-score-find-jobdef |
|
|
72
72
|
| Read table | sas-score-read-table |
|
|
@@ -14,15 +14,14 @@ If the specified resource is ambiguous, ask the user for clarification (e.g. "Ar
|
|
|
14
14
|
|
|
15
15
|
**Model**: If user just says "model X" without specifying type, default to MAS model (this is an explicit exception to the 'never invent' rule, but it is a predefined convention in SAS).
|
|
16
16
|
|
|
17
|
-
Verification
|
|
17
|
+
Verification rules
|
|
18
|
+
- Always verify the target resource exists using the appropriate `find-*` tool before attempting retrieval, except for SCR models (see Exceptions below).
|
|
19
|
+
- For tables, determine server (CAS vs SAS) during verification; if ambiguous, ask the user for the full `lib.table` or server.
|
|
20
|
+
- For models, strip suffixes such as `.mas`, `.job`, `.jobdef` or `.scr` before lookup to avoid lookup failures.
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- Exception for SCR models: document the exception inline — SCR models may be queried directly with `sas-score-scr-info` when the user provides a specific SCR endpoint. Even when skipping verification, still validate the endpoint/URL format before calling the tool.
|
|
24
|
-
|
|
25
|
-
Apply this separation consistently across MAS models, Job models, JobDef models, SCR models, and tables.
|
|
22
|
+
Defaults & exceptions
|
|
23
|
+
- Default model type: MAS when the user says `model X` without specifying a type.
|
|
24
|
+
- If verification fails, inform the user and ask for corrected or more specific identifiers.
|
|
26
25
|
|
|
27
26
|
---
|
|
28
27
|
|
|
@@ -98,7 +97,7 @@ sas-score-mas-info({
|
|
|
98
97
|
```
|
|
99
98
|
User: "What inputs does mas model churnRisk need?"
|
|
100
99
|
|
|
101
|
-
1. Find: sas-score-find-
|
|
100
|
+
1. Find: sas-score-find-mas({ name: "churnRisk" })
|
|
102
101
|
2. Get info: sas-score-mas-info({ model: "churnRisk" })
|
|
103
102
|
3. Return: { inputs: [...], outputs: [...], description: "..." }
|
|
104
103
|
```
|
|
@@ -267,7 +266,7 @@ If a request fails:
|
|
|
267
266
|
**Workflow**:
|
|
268
267
|
1. Classify: MAS model detail request
|
|
269
268
|
2. Verify: Find model creditScore → Found ✓
|
|
270
|
-
3. Execute: `sas-score-
|
|
269
|
+
3. Execute: `sas-score-mas-info({ model: "creditScore" })`
|
|
271
270
|
4. Return: Model inputs, outputs, and description
|
|
272
271
|
|
|
273
272
|
### Example 2: SCR Model Schema
|
|
@@ -9,6 +9,12 @@ description: >
|
|
|
9
9
|
|
|
10
10
|
Use this strategy to verify that a resource exists before executing any action.
|
|
11
11
|
|
|
12
|
+
Verification rules
|
|
13
|
+
- Use `find-*` tools to confirm resource existence; do not use `list-*` tools for verification.
|
|
14
|
+
- For tables, determine server (CAS vs SAS) from the library; if unknown, try CAS first then SAS (uppercase lib for SAS).
|
|
15
|
+
- For models with no explicit type, default to MAS unless the user specifies otherwise.
|
|
16
|
+
- SCR models require a URL/endpoint; ask the user for the endpoint rather than attempting a find.
|
|
17
|
+
|
|
12
18
|
Do **not** use list tools for verifying or finding specific resources. List tools are for discovery and exploration only, not for confirming the existence of a specific resource.
|
|
13
19
|
|
|
14
20
|
## Resource Types and Find Tools
|
|
@@ -66,7 +72,7 @@ Do **not** use list tools for verifying or finding specific resources. List tool
|
|
|
66
72
|
|
|
67
73
|
### 3. Find Scoring Model
|
|
68
74
|
|
|
69
|
-
**Trigger**: "find model X", "find mas model X", "find job model X", "find jobdef model X",
|
|
75
|
+
**Trigger**: "find model X.mas", "find mas model X", "find job model X", "find jobdef model X",
|
|
70
76
|
"find scr model X", "does model X exist", "locate model X", "find job X", "does job X exist",
|
|
71
77
|
"find jobdef X", "does jobdef X exist"
|
|
72
78
|
|
|
@@ -74,19 +80,19 @@ Do **not** use list tools for verifying or finding specific resources. List tool
|
|
|
74
80
|
|
|
75
81
|
| User phrase / suffix | Model type | Find Tool |
|
|
76
82
|
|------------------------------------------------|------------|------------------------|
|
|
77
|
-
| `find mas model X` / `X.mas` / `mas X` | MAS | `sas-score-find-
|
|
83
|
+
| `find mas model X` / `X.mas` / `mas X` | MAS | `sas-score-find-mas` |
|
|
78
84
|
| `find job model X` / `X.job` / `job X` | Job | `sas-score-find-job` |
|
|
79
85
|
| `find jobdef model X` / `X.jobdef` / `jobdef X`| JobDef | `sas-score-find-jobdef`|
|
|
80
86
|
| `find scr model X` / `X.scr` / `scr X` | SCR | *(no tool — ask for URL)*|
|
|
81
|
-
|
|
87
|
+
|
|
82
88
|
|
|
83
89
|
#### MAS Model
|
|
84
90
|
|
|
85
|
-
**Tool**: `sas-score-find-
|
|
91
|
+
**Tool**: `sas-score-find-mas`
|
|
86
92
|
|
|
87
93
|
**Logic**: Strip `.mas` suffix if present, use base name.
|
|
88
94
|
```
|
|
89
|
-
sas-score-find-
|
|
95
|
+
sas-score-find-mas({ name: "<model>" })
|
|
90
96
|
```
|
|
91
97
|
|
|
92
98
|
#### Job Model
|
|
@@ -123,11 +129,11 @@ If user says "find model X" without a type qualifier, infer the type from the su
|
|
|
123
129
|
|
|
124
130
|
| Pattern | Type | Find Tool |
|
|
125
131
|
|--------------------------------------|---------|-------------------------|
|
|
126
|
-
| `X.mas` / `mas model X` / `mas X` | MAS | `sas-score-find-
|
|
132
|
+
| `X.mas` / `mas model X` / `mas X` | MAS | `sas-score-find-mas` |
|
|
127
133
|
| `X.job` / `job model X` / `job X` | Job | `sas-score-find-job` |
|
|
128
134
|
| `X.jobdef` / `jobdef model X` / `jobdef X` | JobDef | `sas-score-find-jobdef` |
|
|
129
135
|
| `X.scr` / `scr model X` / `scr X` | SCR | Skip (no find tool) |
|
|
130
|
-
| (none) | Default to MAS | `sas-score-find-
|
|
136
|
+
| (none) | Default to MAS | `sas-score-find-mas` |
|
|
131
137
|
|
|
132
138
|
---
|
|
133
139
|
|
|
@@ -8,8 +8,15 @@ description: >
|
|
|
8
8
|
# Unified Resource Listing Strategy
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
Use this strategy to list available resources (libraries, tables, models, jobs, jobdefs).
|
|
12
13
|
|
|
14
|
+
Listing rules
|
|
15
|
+
- Use `list-*` tools for discovery and browsing only; do not use `list-*` to verify a specific resource's existence.
|
|
16
|
+
- If the user specifies a server, list from that server; otherwise list from all servers when appropriate.
|
|
17
|
+
- When a library is ambiguous for table listing, attempt both CAS and SAS and label results by server, or ask the user to clarify.
|
|
18
|
+
|
|
19
|
+
|
|
13
20
|
## Resource Type to Tool Mapping
|
|
14
21
|
|
|
15
22
|
| Resource Type | Aliases / Adjective Form | List Tool |
|
|
@@ -8,6 +8,11 @@ description: >
|
|
|
8
8
|
|
|
9
9
|
Use this strategy when the user requests to read, fetch, or query data from a table.
|
|
10
10
|
|
|
11
|
+
Rules summary
|
|
12
|
+
- Verification rules: verify the table exists using `find-*` and determine the server (CAS vs SAS); ask the user if ambiguous. Do not assume a default server unless explicitly instructed.
|
|
13
|
+
- Execution rules: choose `sas-score-read-table` for raw row reads and `sas-score-sas-query` for aggregations/joins/groupings; if intent is ambiguous, ask the user.
|
|
14
|
+
- Error handling: surface clear guidance when table or column names are missing or misspelled.
|
|
15
|
+
|
|
11
16
|
## Prerequisites
|
|
12
17
|
|
|
13
18
|
Before reading:
|
|
@@ -100,7 +105,7 @@ If the user's intent is ambiguous or mixes aggregation and raw reads, ask the us
|
|
|
100
105
|
|
|
101
106
|
## Table Name Format
|
|
102
107
|
|
|
103
|
-
- **CAS tables**: `Caslib.table` or `Public.customers` (
|
|
108
|
+
- **CAS tables**: `Caslib.table` or `Public.customers` (mixed case table)
|
|
104
109
|
- **SAS tables**: `LIBREF.table` or `SASHELP.cars` (uppercase libref, case-insensitive table)
|
|
105
110
|
|
|
106
111
|
---
|
|
@@ -1,108 +1,82 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: request-routing
|
|
3
3
|
description: >
|
|
4
|
-
|
|
4
|
+
Canonical, compact request-routing strategy for SAS Viya requests.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
7
|
+
# Request Routing — Canonical SKILL
|
|
8
|
+
|
|
9
|
+
Purpose: single source-of-truth for routing SAS Viya actions (read, query, score, describe, list).
|
|
10
|
+
|
|
11
|
+
Quick workflow
|
|
12
|
+
- Verify — confirm resources exist (use find-*).
|
|
13
|
+
- Execute — run the mapped execution tool (read, query, score, describe, list).
|
|
14
|
+
- Format — return results and append a short Strategy Summary.
|
|
15
|
+
|
|
16
|
+
**Important Reminder**: If the category is "Find resource" do not use the list-* rules below, use the specific find-* tool for that resource type. The list-* tools are for discovery when the user does not have a specific resource in mind.
|
|
17
|
+
|
|
18
|
+
Classification
|
|
19
|
+
| Category | Triggers | Primary Action | Primary Tool(s) |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| Find resource | "find", "does X exist", "locate", "verify" | Verify resource | `sas-score-find-library`, `sas-score-find-table`, `sas-score-find-mas`, `sas-score-find-job`, `sas-score-find-jobdef` |
|
|
22
|
+
| Read / Query | "read", "show rows", "how many", "count", "average", "query" | Read / aggregate | `sas-score-read-table`, `sas-score-sas-query` |
|
|
23
|
+
| Score | "score", "predict", "run model" | Score inputs | `sas-score-mas-score`, `sas-score-run-job`, `sas-score-run-jobdef`, `sas-score-scr-score` |
|
|
24
|
+
| List / Discover | "list", "show all", "browse" | List resources | `list-*` tools (e.g., `list-mas`, `list-jobs`) |
|
|
25
|
+
| Describe | "describe", "what inputs", "metadata" | Return metadata | `sas-score-*-info` (mas/job/jobdef/scr), `sas-score-table-info` |
|
|
26
|
+
|
|
27
|
+
Verification rules
|
|
28
|
+
- Always verify resources using the appropriate `find-*` tool before executing actions
|
|
29
|
+
|
|
30
|
+
Execution rules
|
|
31
|
+
- Execute only after verification; choose the execution tool per the Execute mapping section.
|
|
32
|
+
- Scoring flows:
|
|
33
|
+
- Inline scenario: verify model → call scoring tool.
|
|
34
|
+
- Table rows: verify model + table → read rows → map columns to model inputs → score → merge predictions with rows.
|
|
35
|
+
- Read/query flows:
|
|
36
|
+
- Use `sas-score-sas-query` for aggregations and groupings.
|
|
37
|
+
- Use `sas-score-read-table` for row reads.
|
|
38
|
+
- When mapping between table columns and model inputs is ambiguous, ask the user for explicit mapping.
|
|
39
|
+
|
|
40
|
+
Defaults & exceptions
|
|
41
|
+
- Default model type: MAS unless the user specifies otherwise.
|
|
42
|
+
- Skip `find-*` verification for SCR models; SCR endpoints may be scored directly.
|
|
43
|
+
- If server determination is ambiguous, prompt the user for clarification.
|
|
44
|
+
|
|
45
|
+
Execute mapping (concise)
|
|
46
|
+
- Read rows: `sas-score-read-table` (lib, table, server)
|
|
47
|
+
- Aggregation/query: `sas-score-sas-query` (lib.table, query)
|
|
48
|
+
- MAS scoring: `sas-score-mas-score` (mas, scenario)
|
|
49
|
+
- Job scoring: `sas-score-run-job` (job, scenario)
|
|
50
|
+
- JobDef scoring: `sas-score-run-jobdef` (jobdef, scenario)
|
|
51
|
+
- SCR scoring: `sas-score-scr-score` (url, scenario)
|
|
52
|
+
- Describe: `sas-score-*-info`, `sas-score-table-info`
|
|
53
|
+
|
|
54
|
+
Combined Read + Score (short)
|
|
55
|
+
1. Verify: find table (server) and find the model (mas,job,jobdef,scr). If table/model not found, ask user to clarify resource and server.
|
|
56
|
+
2. Read: fetch rows (read-table or sas-query).
|
|
57
|
+
3. Map: ensure table columns match model inputs; ask for mapping if needed.
|
|
58
|
+
4. Score: call the appropriate scoring tool.
|
|
59
|
+
5. Merge: attach predictions to rows and return.
|
|
60
|
+
|
|
61
|
+
Strategy Summary (append to responses)
|
|
56
62
|
---
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
1. **Verify**
|
|
64
|
-
- Find the table (determine server as described above)
|
|
65
|
-
- Find the model
|
|
66
|
-
2. **Read**
|
|
67
|
-
- Fetch rows from the table using `sas-score-read-table` or `sas-score-sas-query`
|
|
68
|
-
3. **Map**
|
|
69
|
-
- Check if table columns match model input variables
|
|
70
|
-
- If not, ask user for mapping
|
|
71
|
-
4. **Score**
|
|
72
|
-
- Score each row using `sas-score-mas-score` (for MAS) or `sas-score-scr-score` (for SCR)
|
|
73
|
-
5. **Merge**
|
|
74
|
-
- Combine predictions with original rows
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## Error Handling
|
|
79
|
-
|
|
80
|
-
| Error | Action |
|
|
81
|
-
|---|---|
|
|
82
|
-
| Resource not found | Ask user to verify name and server (for tables). |
|
|
83
|
-
| Column/input mismatch | Ask user to map table columns to model inputs. |
|
|
84
|
-
| Empty result | Ask whether to adjust filter/criteria. |
|
|
85
|
-
|
|
63
|
+
**Strategy Summary:**
|
|
64
|
+
- Classification: [Find / Read / Score / List / Describe]
|
|
65
|
+
- Verification: [Resources verified / skipped]
|
|
66
|
+
- Tool(s): [Primary tool(s) invoked]
|
|
67
|
+
- Decision: [Server chosen, model type, mapping]
|
|
68
|
+
- Next steps: [Follow-ups or clarifications]
|
|
86
69
|
---
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
2. Read table customers in Public (CAS)
|
|
94
|
-
3. Return rows
|
|
71
|
+
Error handling (short)
|
|
72
|
+
- Resource not found → ask for exact resource name and server (for tables).
|
|
73
|
+
- Column/input mismatch → request mapping from user.
|
|
74
|
+
- Empty result → ask to relax filters or confirm criteria.
|
|
75
|
+
- Execution error → return tool error verbatim.
|
|
95
76
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
1
|
|
99
|
-
|
|
100
|
-
3. Return result
|
|
77
|
+
Examples (minimal)
|
|
78
|
+
- Read: "read customers in Public" → find Public (CAS) → read-table → return rows.
|
|
79
|
+
- Score inline: "score a=1,b=2 with job simplejob" → find job → run-job → return merged result.
|
|
80
|
+
- Score table: "score Public.customers with model risk" → find table (CAS) & model (MAS) → read rows → score → return merged.
|
|
101
81
|
|
|
102
|
-
|
|
103
|
-
**Request**: "score records from Public.customers with model risk_model.mas"
|
|
104
|
-
1. Find table customers in Public → Verified (CAS)
|
|
105
|
-
2. Find model risk_model → Verified (MAS)
|
|
106
|
-
3. Read rows from Public.customers
|
|
107
|
-
4. Score each row with risk_model
|
|
108
|
-
5. Return merged predictions + original data
|
|
82
|
+
Notes: Keep this SKILL as the canonical, compact router; agent wrappers should be short and reference this document for details and examples.
|
|
@@ -11,6 +11,11 @@ description: >
|
|
|
11
11
|
|
|
12
12
|
Use this strategy when the user requests model scoring, predictions, or running jobs/jobdefs.
|
|
13
13
|
|
|
14
|
+
Rules summary
|
|
15
|
+
- Verification rules: always verify model existence with `find-*` (except SCR); for table scoring verify both model and table and determine server.
|
|
16
|
+
- Execution rules: inline scenarios → verify model → score; table rows → verify table → read → score (batch). Ask for column-to-input mapping when needed.
|
|
17
|
+
- Defaults & exceptions: default model type to MAS when unspecified; skip pre-verification for SCR models and require a valid SCR endpoint.
|
|
18
|
+
|
|
14
19
|
## Prerequisites
|
|
15
20
|
|
|
16
21
|
1. Verify the model/job exists using find-resources skill
|
package/package.json
CHANGED
package/scripts/plot_msrp_usa.py
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import matplotlib
|
|
2
|
-
matplotlib.use('Agg')
|
|
3
|
-
import matplotlib.pyplot as plt
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
data = [
|
|
7
|
-
("Cadillac", 50474.375),
|
|
8
|
-
("Hummer", 49995.0),
|
|
9
|
-
("Lincoln", 42875.555556),
|
|
10
|
-
("Buick", 30537.777778),
|
|
11
|
-
("GMC", 29560.5),
|
|
12
|
-
("Mercury", 27972.777778),
|
|
13
|
-
("Chrysler", 27252.0),
|
|
14
|
-
("Chevrolet", 26587.037037),
|
|
15
|
-
("Dodge", 26253.846154),
|
|
16
|
-
("Jeep", 24518.333333),
|
|
17
|
-
("Pontiac", 24156.363636),
|
|
18
|
-
("Ford", 24015.869565),
|
|
19
|
-
("Oldsmobile", 23763.333333),
|
|
20
|
-
("Saturn", 17234.375),
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
# Sort by value descending
|
|
24
|
-
data.sort(key=lambda x: x[1], reverse=True)
|
|
25
|
-
makes = [d[0] for d in data]
|
|
26
|
-
values = [d[1] for d in data]
|
|
27
|
-
|
|
28
|
-
out_dir = Path('outputs')
|
|
29
|
-
out_dir.mkdir(parents=True, exist_ok=True)
|
|
30
|
-
out_file = out_dir / 'make_avg_msrp_usa.png'
|
|
31
|
-
|
|
32
|
-
plt.figure(figsize=(12, 6))
|
|
33
|
-
bars = plt.bar(makes, values, color='tab:blue')
|
|
34
|
-
plt.title('Average MSRP by Make (Origin = USA)')
|
|
35
|
-
plt.ylabel('Average MSRP')
|
|
36
|
-
plt.xticks(rotation=45, ha='right')
|
|
37
|
-
plt.tight_layout()
|
|
38
|
-
|
|
39
|
-
# Annotate bars
|
|
40
|
-
for bar in bars:
|
|
41
|
-
height = bar.get_height()
|
|
42
|
-
plt.annotate(f'{height:,.0f}',
|
|
43
|
-
xy=(bar.get_x() + bar.get_width() / 2, height),
|
|
44
|
-
xytext=(0, 3),
|
|
45
|
-
textcoords='offset points',
|
|
46
|
-
ha='center', va='bottom', fontsize=8)
|
|
47
|
-
|
|
48
|
-
plt.savefig(out_file)
|
|
49
|
-
print(f'Plot saved to {out_file}')
|
|
1
|
+
import matplotlib
|
|
2
|
+
matplotlib.use('Agg')
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
data = [
|
|
7
|
+
("Cadillac", 50474.375),
|
|
8
|
+
("Hummer", 49995.0),
|
|
9
|
+
("Lincoln", 42875.555556),
|
|
10
|
+
("Buick", 30537.777778),
|
|
11
|
+
("GMC", 29560.5),
|
|
12
|
+
("Mercury", 27972.777778),
|
|
13
|
+
("Chrysler", 27252.0),
|
|
14
|
+
("Chevrolet", 26587.037037),
|
|
15
|
+
("Dodge", 26253.846154),
|
|
16
|
+
("Jeep", 24518.333333),
|
|
17
|
+
("Pontiac", 24156.363636),
|
|
18
|
+
("Ford", 24015.869565),
|
|
19
|
+
("Oldsmobile", 23763.333333),
|
|
20
|
+
("Saturn", 17234.375),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
# Sort by value descending
|
|
24
|
+
data.sort(key=lambda x: x[1], reverse=True)
|
|
25
|
+
makes = [d[0] for d in data]
|
|
26
|
+
values = [d[1] for d in data]
|
|
27
|
+
|
|
28
|
+
out_dir = Path('outputs')
|
|
29
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
out_file = out_dir / 'make_avg_msrp_usa.png'
|
|
31
|
+
|
|
32
|
+
plt.figure(figsize=(12, 6))
|
|
33
|
+
bars = plt.bar(makes, values, color='tab:blue')
|
|
34
|
+
plt.title('Average MSRP by Make (Origin = USA)')
|
|
35
|
+
plt.ylabel('Average MSRP')
|
|
36
|
+
plt.xticks(rotation=45, ha='right')
|
|
37
|
+
plt.tight_layout()
|
|
38
|
+
|
|
39
|
+
# Annotate bars
|
|
40
|
+
for bar in bars:
|
|
41
|
+
height = bar.get_height()
|
|
42
|
+
plt.annotate(f'{height:,.0f}',
|
|
43
|
+
xy=(bar.get_x() + bar.get_width() / 2, height),
|
|
44
|
+
xytext=(0, 3),
|
|
45
|
+
textcoords='offset points',
|
|
46
|
+
ha='center', va='bottom', fontsize=8)
|
|
47
|
+
|
|
48
|
+
plt.savefig(out_file)
|
|
49
|
+
print(f'Plot saved to {out_file}')
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import _listMas from './_listMas.js';
|
|
7
|
-
async function _findMas(params) {
|
|
8
|
-
let r = await _listMas(params);
|
|
9
|
-
console.log ("findMas result:" , r);
|
|
10
|
-
return r;
|
|
11
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2025, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import _listMas from './_listMas.js';
|
|
7
|
+
async function _findMas(params) {
|
|
8
|
+
let r = await _listMas(params);
|
|
9
|
+
console.log ("findMas result:" , r);
|
|
10
|
+
return r;
|
|
11
|
+
}
|
|
12
12
|
export default _findMas;
|
|
@@ -0,0 +1,31 @@
|
|
|
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 _findScr(params) {
|
|
9
|
+
let {url} = params;
|
|
10
|
+
let config = {
|
|
11
|
+
method: 'HEAD',
|
|
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
|
+
if (response.status !== 200) {
|
|
22
|
+
return {isError: true, content: [{ type: 'text', text: `SCR model ${url} not found` }]};
|
|
23
|
+
} else if (response.status === 200) {
|
|
24
|
+
return { content: [{ type: 'text', text: `Model ${url} is available` }]};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
return {isError: true,content: [{ type: 'text', text: JSON.stringify(error) }]};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export default _findScr;
|
package/src/toolSet/devaScore.js
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
|
|
7
7
|
function devaScore(_appContext) {
|
|
8
|
-
|
|
8
|
+
let brand = _appContext.brand + '-';
|
|
9
9
|
let description = `
|
|
10
10
|
deva-score — compute a numeric score based on two input values.
|
|
11
11
|
|
|
12
12
|
USE when: calculate deva score, score these values, compute score for numbers
|
|
13
|
-
DO NOT USE for: model scoring (use model-score), statistical calculations, data lookup
|
|
13
|
+
DO NOT USE for: model scoring (use ${brand}model-score), statistical calculations, data lookup
|
|
14
14
|
|
|
15
15
|
PARAMETERS
|
|
16
16
|
- a: number (required) — first input value
|
|
@@ -30,9 +30,9 @@ EXAMPLES
|
|
|
30
30
|
- "Deva score 20 and 30" → { a: 20, b: 30 } returns 2100
|
|
31
31
|
|
|
32
32
|
NEGATIVE EXAMPLES (do not route here)
|
|
33
|
-
- "Score this customer with credit model" (use model-score)
|
|
34
|
-
- "Calculate the mean of these values" (use run-sas-program or sas-query)
|
|
35
|
-
- "Statistical analysis of numbers" (use sas-query)
|
|
33
|
+
- "Score this customer with credit model" (use ${brand}model-score)
|
|
34
|
+
- "Calculate the mean of these values" (use ${brand}run-sas-program or ${brand}sas-query)
|
|
35
|
+
- "Statistical analysis of numbers" (use ${brand}sas-query)
|
|
36
36
|
|
|
37
37
|
RESPONSE
|
|
38
38
|
Returns { score: (a + b) * 42 }
|
package/src/toolSet/findJob.js
CHANGED
|
@@ -11,19 +11,22 @@ function findJob(_appContext) {
|
|
|
11
11
|
find-job — locate a specific SAS Viya job.
|
|
12
12
|
|
|
13
13
|
USE when: find job, does job exist, is there a job named, lookup job, verify job exists
|
|
14
|
-
DO NOT USE for: list jobs (use list-jobs), run job (use run-job), execute jobdef (use run-jobdef), find lib/table/model (use respective tools)
|
|
14
|
+
DO NOT USE for: list jobs (use ${_appContext.brand}-list-jobs), run job (use ${_appContext.brand}-run-job), execute jobdef (use ${_appContext.brand}-run-jobdef), find lib/table/model (use respective tools)
|
|
15
15
|
|
|
16
16
|
PARAMETERS
|
|
17
17
|
- name: string (required) — job name to locate; if multiple supplied, use first
|
|
18
18
|
|
|
19
|
+
Naming Rules:
|
|
20
|
+
- If user provides name with "job" suffix ".job", strip the suffix (e.g., "cars_job_v4.job"), and look for "cars_job_v4".
|
|
21
|
+
|
|
19
22
|
ROUTING RULES
|
|
20
23
|
- "find job <name>" → { name: "<name>" }
|
|
21
24
|
- "does job <name> exist" → { name: "<name>" }
|
|
22
25
|
- "is there a job named <name>" → { name: "<name>" }
|
|
23
26
|
- "lookup/verify job <name>" → { name: "<name>" }
|
|
24
27
|
- "find job" with no name → ask "Which job name would you like to find?"
|
|
25
|
-
- "find all jobs / list jobs" → use list-jobs instead
|
|
26
|
-
- "run job <name>" → use run-job instead
|
|
28
|
+
- "find all jobs / list jobs" → use ${_appContext.brand}-list-jobs instead
|
|
29
|
+
- "run job <name>" → use ${_appContext.brand}-run-job instead
|
|
27
30
|
|
|
28
31
|
EXAMPLES
|
|
29
32
|
- "find job cars_job_v4" → { name: "cars_job_v4" }
|
|
@@ -31,9 +34,9 @@ EXAMPLES
|
|
|
31
34
|
- "is there a job named metricsRefresh" → { name: "metricsRefresh" }
|
|
32
35
|
|
|
33
36
|
NEGATIVE EXAMPLES (do not route here)
|
|
34
|
-
- "list jobs" (use list-jobs)
|
|
35
|
-
- "run job cars_job_v4" (use run-job)
|
|
36
|
-
- "execute jobdef cars_job_v4" (use run-jobdef)
|
|
37
|
+
- "list jobs" (use ${_appContext.brand}-list-jobs)
|
|
38
|
+
- "run job cars_job_v4" (use ${_appContext.brand}-run-job)
|
|
39
|
+
- "execute jobdef cars_job_v4" (use ${_appContext.brand}-run-jobdef)
|
|
37
40
|
|
|
38
41
|
ERRORS
|
|
39
42
|
Returns { jobs: [] } if not found; { jobs: [name, ...] } if found. Never hallucinate job names.
|