systemlink-cli 1.13.5__tar.gz → 1.13.6__tar.gz
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.
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/PKG-INFO +1 -1
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/pyproject.toml +1 -1
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/_version.py +1 -1
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/main.py +2 -2
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/SKILL.md +30 -20
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-notebook/SKILL.md +114 -10
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-notebook/references/interfaces.md +91 -1
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-notebook/references/notebook-patterns.md +53 -12
- systemlink_cli-1.13.6/slcli/skills/systemlink-webapp/SKILL.md +188 -0
- systemlink_cli-1.13.6/slcli/skills/systemlink-webapp/references/angular-ui-packages.md +154 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-webapp/references/deployment.md +7 -5
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-webapp/references/nimble-angular.md +2 -0
- systemlink_cli-1.13.6/slcli/skills/systemlink-webapp/references/troubleshooting.md +100 -0
- systemlink_cli-1.13.5/slcli/skills/systemlink-webapp/SKILL.md +0 -855
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/LICENSE +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/dff-editor/editor.js +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/dff-editor/index.html +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/__init__.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/__main__.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/asset_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/cli_formatters.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/cli_utils.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/comment_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/completion_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/config.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/config_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/dataframe_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/dff_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/dff_decorators.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/example_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/example_loader.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/example_provisioner.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/_schema/schema-v1.0.json +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/demo-complete-workflow/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/demo-complete-workflow/config.yaml +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/demo-test-plans/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/demo-test-plans/config.yaml +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/feed_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/file_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/function_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/function_templates.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/mcp_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/mcp_reachability.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/mcp_server.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/notebook_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/platform.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/policy_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/policy_utils.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/profiles.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/response_handlers.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/rich_output.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/routine_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skill_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/nipkg-file-package/SKILL.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/references/commands.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/references/filtering.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/slcli/references/troubleshooting.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-job-debugging/SKILL.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-python-test/SKILL.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-webapp/references/layout-patterns.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/skills/systemlink-webapp/references/systemlink-services.md +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/spec_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/ssl_trust.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/state_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/system_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/system_query_utils.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/table_utils.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/tag_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/templates_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/testmonitor_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/universal_handlers.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/user_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/utils.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/web_editor.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/webapp_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/workflow_preview.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/workflows_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/workitem_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/workspace_click.py +0 -0
- {systemlink_cli-1.13.5 → systemlink_cli-1.13.6}/slcli/workspace_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "systemlink-cli"
|
|
3
|
-
version = "1.13.
|
|
3
|
+
version = "1.13.6"
|
|
4
4
|
description = "SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates."
|
|
5
5
|
authors = ["Fred Visser <fred.visser@emerson.com>"]
|
|
6
6
|
packages = [{ include = "slcli" }]
|
|
@@ -64,7 +64,7 @@ def _configure_rich_click_command_groups() -> None:
|
|
|
64
64
|
"slcli": [
|
|
65
65
|
{
|
|
66
66
|
"name": "Configure",
|
|
67
|
-
"commands": ["config", "login", "logout", "info", "completion"],
|
|
67
|
+
"commands": ["config", "login", "logout", "info", "completion", "example"],
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
"name": "Administer",
|
|
@@ -89,7 +89,7 @@ def _configure_rich_click_command_groups() -> None:
|
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"name": "Validate & Plan",
|
|
92
|
-
"commands": ["testmonitor", "template", "spec", "workitem"
|
|
92
|
+
"commands": ["testmonitor", "template", "spec", "workitem"],
|
|
93
93
|
},
|
|
94
94
|
]
|
|
95
95
|
}
|
|
@@ -24,6 +24,16 @@ compatibility: >-
|
|
|
24
24
|
metadata:
|
|
25
25
|
author: ni-kismet
|
|
26
26
|
version: "2.0"
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Command style
|
|
30
|
+
|
|
31
|
+
Prefer long option names in generated commands and examples. Use `--format json`,
|
|
32
|
+
`--take 25`, `--workspace Default`, and `--output path.json` instead of `-f json`,
|
|
33
|
+
`-t 25`, `-w Default`, or `-o path.json`.
|
|
34
|
+
|
|
35
|
+
Only mention short aliases when explicitly documenting that they exist.
|
|
36
|
+
|
|
27
37
|
# --system SYSTEM_ID Assign a system (by minion/system ID). Repeatable.
|
|
28
38
|
# --fixture ASSET_ID Assign a fixture/slot (by asset ID, asset type FIXTURE). Repeatable.
|
|
29
39
|
# --dut ASSET_ID Assign a DUT (by asset ID, asset type DEVICE_UNDER_TEST). Repeatable.
|
|
@@ -36,22 +46,22 @@ slcli workitem schedule <WORK_ITEM_ID> \
|
|
|
36
46
|
[--system SYSTEM_ID]... [--fixture ASSET_ID]... [--dut ASSET_ID]...
|
|
37
47
|
|
|
38
48
|
# Work item template subgroup
|
|
39
|
-
slcli workitem template list [
|
|
40
|
-
slcli workitem template get <TEMPLATE_ID> [
|
|
41
|
-
slcli workitem template create --name TEXT --type TEXT --template-group TEXT [
|
|
49
|
+
slcli workitem template list [--workspace WORKSPACE] [--filter TEXT] [--take INT] [--format json]
|
|
50
|
+
slcli workitem template get <TEMPLATE_ID> [--format json]
|
|
51
|
+
slcli workitem template create --name TEXT --type TEXT --template-group TEXT [--workspace WORKSPACE] [OPTIONS]
|
|
42
52
|
slcli workitem template update <TEMPLATE_ID> [--name TEXT] [--description TEXT] [--summary TEXT]
|
|
43
53
|
slcli workitem template delete <TEMPLATE_ID>... [--yes]
|
|
44
54
|
|
|
45
55
|
# Workflow subgroup
|
|
46
|
-
slcli workitem workflow list [
|
|
47
|
-
slcli workitem workflow get [--id WORKFLOW_ID] [--name NAME] [
|
|
56
|
+
slcli workitem workflow list [--workspace WORKSPACE] [--take INT] [--format json]
|
|
57
|
+
slcli workitem workflow get [--id WORKFLOW_ID] [--name NAME] [--format json]
|
|
48
58
|
slcli workitem workflow init [--name TEXT] [--directory DIR] # Scaffold a local workflow file
|
|
49
|
-
slcli workitem workflow create --file PATH [
|
|
50
|
-
slcli workitem workflow import --file PATH [
|
|
51
|
-
slcli workitem workflow export [--id WORKFLOW_ID] [--name NAME] [
|
|
59
|
+
slcli workitem workflow create --file PATH [--workspace WORKSPACE] # Create from JSON file
|
|
60
|
+
slcli workitem workflow import --file PATH [--workspace WORKSPACE] # Import workflow from JSON
|
|
61
|
+
slcli workitem workflow export [--id WORKFLOW_ID] [--name NAME] [--output FILE] # Export to JSON
|
|
52
62
|
slcli workitem workflow update --id WORKFLOW_ID --file PATH # Update from JSON file
|
|
53
63
|
slcli workitem workflow delete --id WORKFLOW_ID [--yes]
|
|
54
|
-
slcli workitem workflow preview [--file PATH] [--id WORKFLOW_ID] [--html] [--no-open] [
|
|
64
|
+
slcli workitem workflow preview [--file PATH] [--id WORKFLOW_ID] [--html] [--no-open] [--output FILE]
|
|
55
65
|
```
|
|
56
66
|
|
|
57
67
|
**Create work item options:**
|
|
@@ -82,9 +92,9 @@ Scaffold, package, and publish custom web applications to SystemLink.
|
|
|
82
92
|
```bash
|
|
83
93
|
slcli webapp init <DIRECTORY> # Scaffold the Angular starter
|
|
84
94
|
slcli webapp manifest init <DIRECTORY> [OPTIONS] # Create nipkg.config.json for packaging
|
|
85
|
-
slcli webapp pack [FOLDER] [--config FILE] [
|
|
86
|
-
slcli webapp list [
|
|
87
|
-
slcli webapp get <WEBAPP_ID> [
|
|
95
|
+
slcli webapp pack [FOLDER] [--config FILE] [--output OUTPUT_FILE] # Package a webapp into a .nipkg
|
|
96
|
+
slcli webapp list [--workspace WORKSPACE] [--take INT] [--format json]
|
|
97
|
+
slcli webapp get <WEBAPP_ID> [--format json]
|
|
88
98
|
slcli webapp publish PATH [--workspace NAME] # Upload and publish a webapp
|
|
89
99
|
slcli webapp delete <WEBAPP_ID>
|
|
90
100
|
slcli webapp open <WEBAPP_ID> # Open webapp URL in browser
|
|
@@ -95,19 +105,19 @@ slcli webapp open <WEBAPP_ID> # Open webapp URL in br
|
|
|
95
105
|
Create, inspect, import, export, and revert saved software states managed by the SystemLink Systems State service.
|
|
96
106
|
|
|
97
107
|
```bash
|
|
98
|
-
slcli state list [
|
|
99
|
-
slcli state get <STATE_ID> [
|
|
108
|
+
slcli state list [--workspace WORKSPACE] [--architecture CHOICE] [--distribution CHOICE] [--take INT] [--format json]
|
|
109
|
+
slcli state get <STATE_ID> [--format json]
|
|
100
110
|
slcli state create --name TEXT --distribution CHOICE --architecture CHOICE [OPTIONS]
|
|
101
111
|
slcli state update <STATE_ID> [OPTIONS]
|
|
102
112
|
slcli state delete <STATE_ID> [--yes]
|
|
103
113
|
|
|
104
114
|
slcli state import --name TEXT --distribution CHOICE --architecture CHOICE --file PATH [OPTIONS]
|
|
105
|
-
slcli state replace-content <STATE_ID> --file PATH [--change-description TEXT] [
|
|
115
|
+
slcli state replace-content <STATE_ID> --file PATH [--change-description TEXT] [--format json]
|
|
106
116
|
slcli state export <STATE_ID> [--version VERSION] [--inline | --output FILE]
|
|
107
117
|
slcli state capture <SYSTEM_ID> [--inline | --output FILE]
|
|
108
118
|
|
|
109
|
-
slcli state history <STATE_ID> [
|
|
110
|
-
slcli state version <STATE_ID> <VERSION> [
|
|
119
|
+
slcli state history <STATE_ID> [--take INT] [--format json]
|
|
120
|
+
slcli state version <STATE_ID> <VERSION> [--format json]
|
|
111
121
|
slcli state revert <STATE_ID> <VERSION> [--yes]
|
|
112
122
|
```
|
|
113
123
|
|
|
@@ -148,7 +158,7 @@ Install pre-built demo configurations (systems, assets, DUTs, templates, etc.)
|
|
|
148
158
|
for training, testing, or evaluation.
|
|
149
159
|
|
|
150
160
|
```bash
|
|
151
|
-
slcli example list [
|
|
161
|
+
slcli example list [--format json] # List available examples
|
|
152
162
|
slcli example info <EXAMPLE_ID> # Show example details
|
|
153
163
|
slcli example install <EXAMPLE_ID> [--workspace NAME] # Provision example resources
|
|
154
164
|
slcli example delete <EXAMPLE_ID> [--workspace NAME] # Remove provisioned resources
|
|
@@ -175,7 +185,7 @@ SystemLink Enterprise (SLE) or require a specific microservice to be deployed.
|
|
|
175
185
|
|
|
176
186
|
```bash
|
|
177
187
|
slcli info # Shows platform type and service health
|
|
178
|
-
slcli info
|
|
188
|
+
slcli info --format json # Machine-readable; check .services for per-service status
|
|
179
189
|
```
|
|
180
190
|
|
|
181
191
|
| Command group | Required service | SLE | SLS | Notes |
|
|
@@ -231,7 +241,7 @@ to disable caching for debugging.
|
|
|
231
241
|
|
|
232
242
|
## Key rules
|
|
233
243
|
|
|
234
|
-
1. **Always use
|
|
244
|
+
1. **Always use `--format json`** when piping output to `jq` or doing programmatic analysis.
|
|
235
245
|
2. **Use `--summary --group-by`** for aggregation instead of fetching all records and counting.
|
|
236
246
|
3. **Use convenience filters first** (e.g., `--status FAILED`), fall back to `--filter` for complex queries.
|
|
237
247
|
4. **Parameterize `--filter` queries** — use `--substitution` instead of string interpolation.
|
|
@@ -20,6 +20,84 @@ argument-hint: 'Describe the notebook purpose and what data it should report on'
|
|
|
20
20
|
- Creating a test data analysis notebook
|
|
21
21
|
- Deploying a notebook to SystemLink via `slcli`
|
|
22
22
|
|
|
23
|
+
## Important: Python Client Quirks
|
|
24
|
+
|
|
25
|
+
The `nisystemlink-clients` Python package has a few ergonomics quirks to be aware of:
|
|
26
|
+
|
|
27
|
+
### API naming inconsistency
|
|
28
|
+
|
|
29
|
+
Client methods use Python `snake_case`, but request model fields use `camelCase`. This requires careful attention:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
# ❌ WRONG: Using Python snake_case (very intuitive but incorrect)
|
|
33
|
+
CreateResultRequest(program_name="My Test", file_ids=[file_id])
|
|
34
|
+
|
|
35
|
+
# ✅ CORRECT: Must use camelCase field names from the request model
|
|
36
|
+
CreateResultRequest(programName="My Test", fileIds=[file_id])
|
|
37
|
+
|
|
38
|
+
# Methods stay snake_case:
|
|
39
|
+
client.create_results(request) # This is correct
|
|
40
|
+
client.create_steps(...) # This is correct
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Always check the request model constructor signature, not what "feels" Pythonic.
|
|
44
|
+
|
|
45
|
+
### Partial-success responses
|
|
46
|
+
|
|
47
|
+
Operations like `create_results()` and `create_steps()` return partial-success wrapper types
|
|
48
|
+
(e.g., `CreateStepsPartialSuccess`) even when successful. These contain both success and failure data:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from nisystemlink.clients.testmonitor import TestMonitorClient
|
|
52
|
+
from nisystemlink.clients.testmonitor.models import CreateStepRequest
|
|
53
|
+
|
|
54
|
+
client = TestMonitorClient()
|
|
55
|
+
response = client.create_steps([CreateStepRequest(...)])
|
|
56
|
+
|
|
57
|
+
# Success and failures are both in the response
|
|
58
|
+
if response.failed:
|
|
59
|
+
print(f"Failed to create {len(response.failed)} steps")
|
|
60
|
+
if response.created:
|
|
61
|
+
print(f"Successfully created {len(response.created)} steps")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Limited service coverage
|
|
65
|
+
|
|
66
|
+
The Python client does **not cover all SystemLink services**. The most important gaps for notebooks (see the [client repo](https://github.com/ni/nisystemlink-clients-python) for the current full list):
|
|
67
|
+
|
|
68
|
+
- ❌ **Notebook Execution** — no Python client for execution lifecycle management
|
|
69
|
+
- ❌ **Routines v1/v2** — no Python client for scheduling/triggering
|
|
70
|
+
- ❌ **Systems State** — no Python client for system health queries
|
|
71
|
+
- ❌ **Comments** — no Python client for resource annotations
|
|
72
|
+
- ❌ **User Data** — no Python client for key-value stores
|
|
73
|
+
- ❌ **Tag Historian** — no Python client for time-series history
|
|
74
|
+
|
|
75
|
+
For these services, use REST calls directly via the `requests` library or SystemLink's OpenAPI SDKs.
|
|
76
|
+
|
|
77
|
+
### Public import paths
|
|
78
|
+
|
|
79
|
+
This skill uses two distinct Python SDK namespaces — be careful not to mix them:
|
|
80
|
+
|
|
81
|
+
- **`nisystemlink.clients.*`** — the typed Python client (`nisystemlink-clients` package). Use public top-level imports.
|
|
82
|
+
- **`systemlink.clients.nisysmgmt.*`** — a separate OpenAPI-generated SDK used only for Systems queries.
|
|
83
|
+
|
|
84
|
+
For `nisystemlink.clients`, always import from the public top-level modules, not private `_module` paths:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# ✅ CORRECT: Public paths (nisystemlink-clients)
|
|
88
|
+
from nisystemlink.clients.file import FileClient
|
|
89
|
+
from nisystemlink.clients.testmonitor import TestMonitorClient
|
|
90
|
+
from nisystemlink.clients.testmonitor.models import CreateResultRequest, CreateStepRequest
|
|
91
|
+
|
|
92
|
+
# ❌ WRONG: Private module paths (may change or be removed)
|
|
93
|
+
from nisystemlink.clients.testmonitor._test_monitor_client import TestMonitorClient
|
|
94
|
+
from nisystemlink.clients.testmonitor.models._create_result_request import CreateResultRequest
|
|
95
|
+
|
|
96
|
+
# Separate SDK — used only for Systems queries:
|
|
97
|
+
from systemlink.clients.nisysmgmt.api.systems_api import SystemsApi
|
|
98
|
+
from systemlink.clients.nisysmgmt.models.query_systems_request import QuerySystemsRequest
|
|
99
|
+
```
|
|
100
|
+
|
|
23
101
|
## Notebook Structure
|
|
24
102
|
|
|
25
103
|
Every SystemLink notebook follows this cell pattern:
|
|
@@ -199,33 +277,59 @@ import scrapbook as sb
|
|
|
199
277
|
from systemlink.clients.nisysmgmt.api.systems_api import SystemsApi
|
|
200
278
|
from systemlink.clients.nisysmgmt.models.query_systems_request import QuerySystemsRequest
|
|
201
279
|
|
|
202
|
-
# Test results
|
|
280
|
+
# Test results (remember: camelCase field names in request models)
|
|
203
281
|
from nisystemlink.clients.testmonitor import TestMonitorClient
|
|
282
|
+
from nisystemlink.clients.testmonitor.models import CreateResultRequest, CreateStepRequest
|
|
204
283
|
from nisystemlink.clients.core import HttpConfigurationManager
|
|
205
284
|
|
|
206
285
|
# Assets
|
|
207
286
|
from nisystemlink.clients.assetmanagement import AssetManagementClient
|
|
208
287
|
|
|
209
|
-
# Direct HTTP (when no typed client exists)
|
|
288
|
+
# Direct HTTP (when no typed client exists or for missing services)
|
|
210
289
|
import requests
|
|
211
290
|
config = HttpConfigurationManager.get_configuration()
|
|
212
291
|
base_url = config.server_uri.rstrip("/")
|
|
213
|
-
|
|
292
|
+
api_keys = getattr(config, "api_keys", {})
|
|
293
|
+
api_key = api_keys.get("x-ni-api-key") if isinstance(api_keys, dict) else None
|
|
294
|
+
if not api_key:
|
|
295
|
+
raise RuntimeError("Configure an x-ni-api-key before using REST fallbacks.")
|
|
296
|
+
headers = {"x-ni-api-key": api_key}
|
|
214
297
|
```
|
|
215
298
|
|
|
299
|
+
### Available Python client services
|
|
300
|
+
|
|
301
|
+
The Python client covers these **15 main services**:
|
|
302
|
+
- `alarm`, `artifact`, `assetmanagement`, `dataframe`, `feeds`, `file`, `notebook`,
|
|
303
|
+
`notification`, `product`, `spec`, `systems`, `tag`, `test_plan`, `testmonitor`, `work_item`
|
|
304
|
+
|
|
305
|
+
### Missing services (use REST directly)
|
|
306
|
+
|
|
307
|
+
If you need these services, call the REST API directly using `requests` and the OpenAPI docs:
|
|
308
|
+
- **Notebook Execution** — execution lifecycle (use OpenAPI directly)
|
|
309
|
+
- **Routines v1/v2** — scheduling/triggering (use OpenAPI directly)
|
|
310
|
+
- **Systems State** — system health/connection status (use OpenAPI directly)
|
|
311
|
+
- **Comments** — resource annotations (use OpenAPI directly)
|
|
312
|
+
- **User Data** — key-value stores (use OpenAPI directly)
|
|
313
|
+
- **Tag Historian** — time-series history (use OpenAPI directly)
|
|
314
|
+
- **Auth**, **User**, and others — see full list in service-gaps documentation
|
|
315
|
+
|
|
216
316
|
## Client and API References
|
|
217
317
|
|
|
218
|
-
-
|
|
318
|
+
- **Python client repository** — full source and examples:
|
|
219
319
|
https://github.com/ni/nisystemlink-clients-python
|
|
220
|
-
-
|
|
221
|
-
directly and use the hosted OpenAPI docs to discover endpoints and schemas:
|
|
320
|
+
- **SystemLink OpenAPI docs** — for all services, including those without Python clients:
|
|
222
321
|
https://demo-api.lifecyclesolutions.ni.com/niapis/
|
|
223
|
-
-
|
|
224
|
-
examples repository:
|
|
322
|
+
- **SystemLink Enterprise examples** — end-to-end patterns:
|
|
225
323
|
https://github.com/ni/systemlink-enterprise-examples/
|
|
226
324
|
|
|
227
|
-
When using
|
|
228
|
-
|
|
325
|
+
When using the Python client:
|
|
326
|
+
- Always check the request model constructor signature for camelCase field names (they won't match Python snake_case)
|
|
327
|
+
- Expect `create_*` operations to return partial-success wrapper types; inspect `.created` and `.failed` attributes
|
|
328
|
+
- Use public import paths from top-level modules, not private `_module` paths
|
|
329
|
+
|
|
330
|
+
When a service lacks a Python client, use OpenAPI docs to discover the endpoint path,
|
|
331
|
+
request body shape, and response schema before writing HTTP calls.
|
|
332
|
+
|
|
229
333
|
## Systems Query Pattern
|
|
230
334
|
|
|
231
335
|
The `SystemsApi` uses a projection/filter pattern for querying:
|
|
@@ -14,6 +14,20 @@ Prefer `create --interface ...` when you are creating a new notebook. Use
|
|
|
14
14
|
`update --interface ...` for in-place interface changes on an existing notebook.
|
|
15
15
|
Delete and re-create only if the server rejects the update.
|
|
16
16
|
|
|
17
|
+
## Service Availability Note
|
|
18
|
+
|
|
19
|
+
The Python client does not cover every SystemLink service. Key gaps that affect
|
|
20
|
+
automation interfaces (see the `nisystemlink-clients` repository for the current
|
|
21
|
+
service list):
|
|
22
|
+
|
|
23
|
+
- ❌ **Notebook Execution** — No Python client for checking execution status or logs
|
|
24
|
+
- ❌ **Routines v1/v2** — No Python client for scheduling; use REST directly or `slcli routine` in scheduled shells
|
|
25
|
+
- ❌ **Comments** — No Python client for adding resource annotations
|
|
26
|
+
- ❌ **User** — No Python client for querying users/workspaces (use REST directly)
|
|
27
|
+
|
|
28
|
+
For these services in notebooks, call the REST API directly via the `requests`
|
|
29
|
+
library and the service-specific SystemLink OpenAPI docs.
|
|
30
|
+
|
|
17
31
|
## Available Interfaces
|
|
18
32
|
|
|
19
33
|
| Interface | Use Case |
|
|
@@ -56,7 +70,12 @@ Parameters typically include:
|
|
|
56
70
|
### Periodic Execution
|
|
57
71
|
|
|
58
72
|
No special parameter requirements. Typically uses fixed configuration
|
|
59
|
-
or reads from tags/files. Can be scheduled via routines
|
|
73
|
+
or reads from tags/files. Can be scheduled via routines (no Python client available).
|
|
74
|
+
|
|
75
|
+
**Note:** The Python client does not have a Routines service. Use `slcli routine` to
|
|
76
|
+
schedule notebooks, or call the Routines REST API directly.
|
|
77
|
+
|
|
78
|
+
Create a scheduled routine via CLI:
|
|
60
79
|
|
|
61
80
|
```bash
|
|
62
81
|
slcli routine create --api-version v1 \
|
|
@@ -66,6 +85,31 @@ slcli routine create --api-version v1 \
|
|
|
66
85
|
--schedule '{"startTime":"2026-01-01T00:00:00Z","repeat":"DAY"}'
|
|
67
86
|
```
|
|
68
87
|
|
|
88
|
+
Or create a scheduled routine via REST using `HttpConfigurationManager` and `requests`:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import requests
|
|
92
|
+
from nisystemlink.clients.core import HttpConfigurationManager
|
|
93
|
+
|
|
94
|
+
config = HttpConfigurationManager.get_configuration()
|
|
95
|
+
base_url = config.server_uri.rstrip("/")
|
|
96
|
+
api_keys = getattr(config, "api_keys", {})
|
|
97
|
+
api_key = api_keys.get("x-ni-api-key") if isinstance(api_keys, dict) else None
|
|
98
|
+
if not api_key:
|
|
99
|
+
raise RuntimeError("Configure an x-ni-api-key before using REST fallbacks.")
|
|
100
|
+
headers = {"x-ni-api-key": api_key}
|
|
101
|
+
|
|
102
|
+
payload = {
|
|
103
|
+
"name": "Daily Report",
|
|
104
|
+
"type": "SCHEDULED",
|
|
105
|
+
"notebookId": "<NOTEBOOK_ID>",
|
|
106
|
+
"schedule": {"startTime": "<START_TIME_ISO8601>", "repeat": "DAY"}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
resp = requests.post(f"{base_url}/niroutine/v1/routines", json=payload, headers=headers)
|
|
110
|
+
resp.raise_for_status()
|
|
111
|
+
```
|
|
112
|
+
|
|
69
113
|
### Work Item Automations
|
|
70
114
|
|
|
71
115
|
Use this interface for notebooks that act on selected work items (close, update,
|
|
@@ -80,3 +124,49 @@ Parameters are injected by the work item system:
|
|
|
80
124
|
**Critical:** `work_item_ids` must be typed as `"string[]"` (not `"string"`),
|
|
81
125
|
default to `[]` in both papermill and the code cell, and `systemlink.version`
|
|
82
126
|
must be `1`. See the systemlink-notebook skill for the full metadata example.
|
|
127
|
+
|
|
128
|
+
**Service note:** The Python client has `work_item` service for querying and updating
|
|
129
|
+
work items, but does not have a `comments` service. If your automation needs to add
|
|
130
|
+
comments or notes, call the Comments REST API directly via `requests` library.
|
|
131
|
+
|
|
132
|
+
## Using REST When Python Clients Are Missing
|
|
133
|
+
|
|
134
|
+
If a notebook needs a service without a Python client, use `requests` and the OpenAPI docs:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
import requests
|
|
138
|
+
from nisystemlink.clients.core import HttpConfigurationManager
|
|
139
|
+
|
|
140
|
+
config = HttpConfigurationManager.get_configuration()
|
|
141
|
+
base_url = config.server_uri.rstrip("/")
|
|
142
|
+
api_keys = getattr(config, "api_keys", {})
|
|
143
|
+
api_key = api_keys.get("x-ni-api-key") if isinstance(api_keys, dict) else None
|
|
144
|
+
if not api_key:
|
|
145
|
+
raise RuntimeError("Configure an x-ni-api-key before using REST fallbacks.")
|
|
146
|
+
headers = {"x-ni-api-key": api_key}
|
|
147
|
+
|
|
148
|
+
# Example: Add a comment to a work item (Comments service not available in Python)
|
|
149
|
+
comment_payload = {
|
|
150
|
+
"resourceId": work_item_id,
|
|
151
|
+
"resourceType": "WorkItem",
|
|
152
|
+
"content": "Automated note from notebook"
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
resp = requests.post(
|
|
156
|
+
f"{base_url}/nicomments/v1/comments",
|
|
157
|
+
json=comment_payload,
|
|
158
|
+
headers=headers
|
|
159
|
+
)
|
|
160
|
+
resp.raise_for_status()
|
|
161
|
+
comment = resp.json()
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Common missing services you might need:
|
|
165
|
+
|
|
166
|
+
- **Comments** — `/nicomments/v1/comments`
|
|
167
|
+
- **Routines v1/v2** — `/niroutine/v1/routines` or `/niroutine/v2/routines`
|
|
168
|
+
- **User** — `/niuser/v1/users` or `/niuser/v1/users/query`
|
|
169
|
+
- **Systems State** — `/nisystemsstate/v1/states`
|
|
170
|
+
- **Tag Historian** — check the service-specific OpenAPI docs instead of assuming `/niapis/...`
|
|
171
|
+
|
|
172
|
+
Always check the OpenAPI docs to confirm the correct endpoint path and request schema before implementing REST calls.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Annotated examples of common SystemLink notebook patterns.
|
|
4
4
|
|
|
5
|
+
⚠️ **Important:** The Python client mixes Pythonic `snake_case` method names with `camelCase` request-model field names.
|
|
6
|
+
See the main skill documentation for details on this quirk and other client ergonomics issues. Always verify the
|
|
7
|
+
request model constructor signature before using — intuitive Python names will **not** work.
|
|
8
|
+
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
## Pattern 1: Systems Grid Column Report
|
|
@@ -12,15 +16,19 @@ a `data_frame` output that the Systems Grid can display as a column.
|
|
|
12
16
|
### Full annotated example (Package Version)
|
|
13
17
|
|
|
14
18
|
**Cell 1 — Imports description (markdown)**
|
|
19
|
+
|
|
15
20
|
```markdown
|
|
16
21
|
### Imports
|
|
22
|
+
|
|
17
23
|
Import Python modules for executing the notebook.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
|
|
25
|
+
- Pandas is used for building and handling dataframes.
|
|
26
|
+
- Scrapbook is used for recording data for the Notebook Execution Service.
|
|
27
|
+
- SystemsApi is an NI provided package for communicating with the SystemLink Systems service.
|
|
21
28
|
```
|
|
22
29
|
|
|
23
30
|
**Cell 2 — Imports (code)**
|
|
31
|
+
|
|
24
32
|
```python
|
|
25
33
|
import re
|
|
26
34
|
import pandas as pd
|
|
@@ -31,18 +39,21 @@ from systemlink.clients.nisysmgmt.models.query_systems_request import QuerySyste
|
|
|
31
39
|
```
|
|
32
40
|
|
|
33
41
|
**Cell 3 — Parameters description (markdown)**
|
|
42
|
+
|
|
34
43
|
```markdown
|
|
35
44
|
### Parameters
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
|
|
46
|
+
- `group_by`: The property by which data is grouped. For the data to appear
|
|
47
|
+
as a column in the Systems Grid, we must support 'System' here.
|
|
48
|
+
- `package`: The Package Name of the software to display the version of.
|
|
49
|
+
- `systems_filter`: A filter specifying which systems to query.
|
|
50
|
+
An empty filter matches all systems.
|
|
41
51
|
```
|
|
42
52
|
|
|
43
53
|
**Cell 4 — Parameters (code, with metadata)**
|
|
44
54
|
|
|
45
55
|
The code cell declares variables with defaults:
|
|
56
|
+
|
|
46
57
|
```python
|
|
47
58
|
group_by = "System"
|
|
48
59
|
package = "ni-daqmx"
|
|
@@ -50,6 +61,7 @@ systems_filter = ""
|
|
|
50
61
|
```
|
|
51
62
|
|
|
52
63
|
The cell metadata must include:
|
|
64
|
+
|
|
53
65
|
```json
|
|
54
66
|
{
|
|
55
67
|
"papermill": {
|
|
@@ -92,11 +104,13 @@ The cell metadata must include:
|
|
|
92
104
|
```
|
|
93
105
|
|
|
94
106
|
**Cell 5 — Query description (markdown)**
|
|
107
|
+
|
|
95
108
|
```markdown
|
|
96
109
|
### Query for Systems with the specified package and get the Package Version
|
|
97
110
|
```
|
|
98
111
|
|
|
99
112
|
**Cell 6 — Query (code)**
|
|
113
|
+
|
|
100
114
|
```python
|
|
101
115
|
api = SystemsApi()
|
|
102
116
|
|
|
@@ -133,11 +147,13 @@ data = await query_result
|
|
|
133
147
|
```
|
|
134
148
|
|
|
135
149
|
**Cell 7 — Dataframe description (markdown)**
|
|
150
|
+
|
|
136
151
|
```markdown
|
|
137
152
|
### Extract Package data from query results and create pandas dataframe
|
|
138
153
|
```
|
|
139
154
|
|
|
140
155
|
**Cell 8 — Dataframe (code)**
|
|
156
|
+
|
|
141
157
|
```python
|
|
142
158
|
pkg_version = { item['id'] : item['displayversion'] for item in data.data }
|
|
143
159
|
df = pd.DataFrame.from_dict(pkg_version, orient='index', columns=['Package Version'])
|
|
@@ -145,11 +161,13 @@ df
|
|
|
145
161
|
```
|
|
146
162
|
|
|
147
163
|
**Cell 9 — Output description (markdown)**
|
|
164
|
+
|
|
148
165
|
```markdown
|
|
149
166
|
### Convert dataframe to result format that the Systems Grid can interpret
|
|
150
167
|
```
|
|
151
168
|
|
|
152
169
|
**Cell 10 — Output with sb.glue (code)**
|
|
170
|
+
|
|
153
171
|
```python
|
|
154
172
|
df_dict = {
|
|
155
173
|
'columns': ['minion id', 'package version'],
|
|
@@ -167,8 +185,10 @@ sb.glue('result', result)
|
|
|
167
185
|
```
|
|
168
186
|
|
|
169
187
|
**Cell 11 — Usage instructions (markdown)**
|
|
188
|
+
|
|
170
189
|
```markdown
|
|
171
190
|
### View the output of this report in the Systems Grid
|
|
191
|
+
|
|
172
192
|
1. Upload this notebook to the reports folder in SystemLink Jupyter
|
|
173
193
|
2. From the Systems page, press the edit grid button
|
|
174
194
|
3. Press '+ ADD' and select 'Notebook' as the data source
|
|
@@ -183,7 +203,12 @@ sb.glue('result', result)
|
|
|
183
203
|
|
|
184
204
|
Query test results and return a summary. Uses `nisystemlink.clients.testmonitor`.
|
|
185
205
|
|
|
206
|
+
**⚠️ API Quirk:** Request models in the TestMonitor client use camelCase field names.
|
|
207
|
+
Constructor calls like `CreateResultRequest(programName="...", fileIds=[...])` are required.
|
|
208
|
+
Using intuitive Python `snake_case` names will fail.
|
|
209
|
+
|
|
186
210
|
**Parameters cell metadata:**
|
|
211
|
+
|
|
187
212
|
```json
|
|
188
213
|
{
|
|
189
214
|
"papermill": {
|
|
@@ -204,10 +229,22 @@ Query test results and return a summary. Uses `nisystemlink.clients.testmonitor`
|
|
|
204
229
|
}
|
|
205
230
|
],
|
|
206
231
|
"parameters": [
|
|
207
|
-
{"display_name": "Group by", "id": "group_by", "type": "string"},
|
|
208
|
-
{
|
|
209
|
-
|
|
210
|
-
|
|
232
|
+
{ "display_name": "Group by", "id": "group_by", "type": "string" },
|
|
233
|
+
{
|
|
234
|
+
"display_name": "Program Name",
|
|
235
|
+
"id": "program_name",
|
|
236
|
+
"type": "string"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"display_name": "Status Filter",
|
|
240
|
+
"id": "status_filter",
|
|
241
|
+
"type": "string"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"display_name": "Systems Filter",
|
|
245
|
+
"id": "systems_filter",
|
|
246
|
+
"type": "string"
|
|
247
|
+
}
|
|
211
248
|
],
|
|
212
249
|
"version": 2
|
|
213
250
|
},
|
|
@@ -216,6 +253,7 @@ Query test results and return a summary. Uses `nisystemlink.clients.testmonitor`
|
|
|
216
253
|
```
|
|
217
254
|
|
|
218
255
|
**Query pattern:**
|
|
256
|
+
|
|
219
257
|
```python
|
|
220
258
|
from nisystemlink.clients.testmonitor import TestMonitorClient
|
|
221
259
|
from nisystemlink.clients.core import HttpConfigurationManager
|
|
@@ -231,6 +269,7 @@ results = client.get_results(
|
|
|
231
269
|
```
|
|
232
270
|
|
|
233
271
|
**Output pattern (same as Pattern 1):**
|
|
272
|
+
|
|
234
273
|
```python
|
|
235
274
|
result = [{
|
|
236
275
|
"display_name": "Test Summary",
|
|
@@ -251,6 +290,7 @@ sb.glue('result', result)
|
|
|
251
290
|
When the notebook returns a single value instead of a table.
|
|
252
291
|
|
|
253
292
|
**Output metadata:**
|
|
293
|
+
|
|
254
294
|
```json
|
|
255
295
|
{
|
|
256
296
|
"systemlink": {
|
|
@@ -266,6 +306,7 @@ When the notebook returns a single value instead of a table.
|
|
|
266
306
|
```
|
|
267
307
|
|
|
268
308
|
**Output code:**
|
|
309
|
+
|
|
269
310
|
```python
|
|
270
311
|
result = [{
|
|
271
312
|
"display_name": "Total Count",
|