systemlink-cli 1.13.7__tar.gz → 1.13.9__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.
Files changed (93) hide show
  1. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/PKG-INFO +1 -1
  2. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/pyproject.toml +1 -1
  3. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/_version.py +1 -1
  4. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/SKILL.md +47 -0
  5. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/references/commands.md +55 -39
  6. systemlink_cli-1.13.9/slcli/skills/slcli/references/routine-examples.md +186 -0
  7. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/SKILL.md +55 -2
  8. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/deployment.md +22 -5
  9. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/nimble-angular.md +26 -0
  10. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/troubleshooting.md +10 -0
  11. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/LICENSE +0 -0
  12. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/dff-editor/editor.js +0 -0
  13. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/dff-editor/index.html +0 -0
  14. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/__init__.py +0 -0
  15. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/__main__.py +0 -0
  16. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/asset_click.py +0 -0
  17. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/cli_formatters.py +0 -0
  18. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/cli_utils.py +0 -0
  19. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/comment_click.py +0 -0
  20. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/completion_click.py +0 -0
  21. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/config.py +0 -0
  22. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/config_click.py +0 -0
  23. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/dataframe_click.py +0 -0
  24. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/dff_click.py +0 -0
  25. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/dff_decorators.py +0 -0
  26. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/example_click.py +0 -0
  27. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/example_loader.py +0 -0
  28. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/example_provisioner.py +0 -0
  29. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/README.md +0 -0
  30. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/_schema/schema-v1.0.json +0 -0
  31. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/demo-complete-workflow/README.md +0 -0
  32. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/demo-complete-workflow/config.yaml +0 -0
  33. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/demo-test-plans/README.md +0 -0
  34. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/demo-test-plans/config.yaml +0 -0
  35. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
  36. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
  37. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
  38. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
  39. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
  40. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
  41. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
  42. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
  43. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
  44. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
  45. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/feed_click.py +0 -0
  46. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/file_click.py +0 -0
  47. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/function_click.py +0 -0
  48. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/function_templates.py +0 -0
  49. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/main.py +0 -0
  50. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/mcp_click.py +0 -0
  51. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/mcp_reachability.py +0 -0
  52. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/mcp_server.py +0 -0
  53. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/notebook_click.py +0 -0
  54. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/platform.py +0 -0
  55. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/policy_click.py +0 -0
  56. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/policy_utils.py +0 -0
  57. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/profiles.py +0 -0
  58. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/response_handlers.py +0 -0
  59. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/rich_output.py +0 -0
  60. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/routine_click.py +0 -0
  61. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skill_click.py +0 -0
  62. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/nipkg-file-package/SKILL.md +0 -0
  63. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
  64. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
  65. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/references/filtering.md +0 -0
  66. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/slcli/references/troubleshooting.md +0 -0
  67. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-job-debugging/SKILL.md +0 -0
  68. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-notebook/SKILL.md +0 -0
  69. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-notebook/references/interfaces.md +0 -0
  70. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-notebook/references/notebook-patterns.md +0 -0
  71. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-python-test/SKILL.md +0 -0
  72. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/angular-ui-packages.md +0 -0
  73. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/layout-patterns.md +0 -0
  74. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/skills/systemlink-webapp/references/systemlink-services.md +0 -0
  75. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/spec_click.py +0 -0
  76. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/ssl_trust.py +0 -0
  77. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/state_click.py +0 -0
  78. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/system_click.py +0 -0
  79. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/system_query_utils.py +0 -0
  80. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/table_utils.py +0 -0
  81. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/tag_click.py +0 -0
  82. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/templates_click.py +0 -0
  83. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/testmonitor_click.py +0 -0
  84. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/universal_handlers.py +0 -0
  85. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/user_click.py +0 -0
  86. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/utils.py +0 -0
  87. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/web_editor.py +0 -0
  88. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/webapp_click.py +0 -0
  89. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/workflow_preview.py +0 -0
  90. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/workflows_click.py +0 -0
  91. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/workitem_click.py +0 -0
  92. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/workspace_click.py +0 -0
  93. {systemlink_cli-1.13.7 → systemlink_cli-1.13.9}/slcli/workspace_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemlink-cli
3
- Version: 1.13.7
3
+ Version: 1.13.9
4
4
  Summary: SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates.
5
5
  License-File: LICENSE
6
6
  Author: Fred Visser
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "systemlink-cli"
3
- version = "1.13.7"
3
+ version = "1.13.9"
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" }]
@@ -1,4 +1,4 @@
1
1
  """Version information for slcli."""
2
2
 
3
3
  # This file is auto-generated. Do not edit manually.
4
- __version__ = "1.13.7"
4
+ __version__ = "1.13.9"
@@ -164,6 +164,52 @@ slcli example install <EXAMPLE_ID> [--workspace NAME] # Provision example res
164
164
  slcli example delete <EXAMPLE_ID> [--workspace NAME] # Remove provisioned resources
165
165
  ```
166
166
 
167
+ ### routine — Routine management
168
+
169
+ `slcli routine` spans two different services with different trigger payload shapes.
170
+ Document the API version and trigger schema explicitly when generating commands.
171
+
172
+ #### v1 notebook routines
173
+
174
+ Use `--api-version v1` for notebook-execution routines. These map to the
175
+ Routine Manager API and use `--type`, `--notebook-id`, plus either `--trigger`
176
+ or `--schedule`.
177
+
178
+ Notes for v1 triggers:
179
+
180
+ - `trigger.filter` is required by the v1 API schema for triggered routines.
181
+ - The only trigger `source` documented by the swagger is `FILES`.
182
+ - The documented `events` values are `CREATED` and `UPDATED`.
183
+ - The simplest documented filter is `extension=".xml"`, but observed live examples also combine `workspace = ...` and `name.Contains(...)` checks.
184
+ - Treat the filter string as service-owned syntax, not LINQ or OData. Do not rewrite it as `--filter` CLI syntax.
185
+ - When working with an existing v1 routine, prefer `slcli routine get --api-version v1 <ID>` because the default API version is v2.
186
+
187
+ #### v2 event-action routines
188
+
189
+ Use the default `v2` API for event-action routines. These map to the newer
190
+ Routine Service and use `--event` plus `--actions`.
191
+
192
+ For v2 routines, there is no top-level `filter` field in the create/update
193
+ request. Filtering is event-type-specific and lives inside
194
+ `event.triggers[].configuration`.
195
+
196
+ Notes for v2 triggers:
197
+
198
+ - `event.type` selects the event provider/plugin.
199
+ - `event.triggers[]` contains one or more named conditions.
200
+ - Each trigger's `configuration` object is provider-specific; the v2 swagger does not enumerate a universal set of filter keys.
201
+ - Some v2 providers do use a `configuration.filter` field, but it is part of the provider-specific trigger configuration, not a top-level routine field.
202
+ - Other v2 providers use structured condition fields such as `path`, `type`, `comparator`, `thresholds`, and `deadband` instead of a `filter` string.
203
+ - Do not assume the v1 file-trigger filter string syntax applies to v2 routines.
204
+ - When documenting v2 routines, show the exact JSON shape and note that valid configuration keys depend on the event type.
205
+ - Live survey on the demo environment found these v2 event types in use: `TAG`, `TESTRESULTCHANGED`, and `WORKITEMCHANGED`.
206
+ - Live survey on the demo environment found these v2 action types in use: `ALARM` and `NOTEBOOK`.
207
+ - Observed TAG routines also use comparator-driven configurations such as `IN_RANGE`, `NOT_EQUAL`, and `GREATER_THAN_OR_EQUAL`.
208
+ - Observed `TESTRESULTCHANGED` and `WORKITEMCHANGED` filters use provider-specific expression syntax such as nested field comparisons, `after.properties["key"]`, `DateTime.parse(...)`, `.Any(...)`, and `!Contains(...)`.
209
+ - Common NOTEBOOK action fields in v2 are `notebookId`, `parameters`, `resourceProfile`, `priority`, and `serviceAccount`.
210
+ - ALARM-producing routines need the clear/reset action that uses trigger `nisystemlink_no_triggers_breached`.
211
+ - Load [routine-examples.md](./references/routine-examples.md) for sanitized live examples of compound v1 FILES filters and advanced v2 configurations.
212
+
167
213
  ## Reference docs
168
214
 
169
215
  Consult these for detailed guidance. Load only what you need for the current task.
@@ -171,6 +217,7 @@ Consult these for detailed guidance. Load only what you need for the current tas
171
217
  | Topic | File | When to load |
172
218
  | --------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------- |
173
219
  | CLI command reference | [commands.md](./references/commands.md) | Looking up command syntax, options, or examples |
220
+ | Routine examples | [routine-examples.md](./references/routine-examples.md) | Provider-specific v1/v2 payload shapes and sanitized live examples |
174
221
  | Datasheet-to-specs workflow | [datasheet-workflow.md](./references/datasheet-workflow.md) | Importing specs from PDF, CSV, or structured text |
175
222
  | Filtering guide | [filtering.md](./references/filtering.md) | Advanced LINQ expressions, parameterized queries |
176
223
  | Analysis recipes | [analysis-recipes.md](./references/analysis-recipes.md) | Multi-step analysis: yield, calibration, operator performance |
@@ -358,6 +358,11 @@ Two API versions are supported:
358
358
  - **v2** (default): General event-action routines — monitor tags, work-item changes, and more; trigger alarms, emails, or notebook executions.
359
359
  - **v1**: Notebook-execution routines with SCHEDULED or TRIGGERED types.
360
360
 
361
+ Observed on the demo environment:
362
+
363
+ - v2 event types: `TAG`, `TESTRESULTCHANGED`, `WORKITEMCHANGED`
364
+ - v2 action types: `ALARM`, `NOTEBOOK`
365
+
361
366
  ```bash
362
367
  # List routines
363
368
  slcli routine list [OPTIONS]
@@ -375,6 +380,9 @@ slcli routine list [OPTIONS]
375
380
  # Get a single routine by ID
376
381
  slcli routine get <ROUTINE_ID> [--api-version v1|v2] [-f json]
377
382
 
383
+ # Note: the default API version is v2. Use --api-version v1 when reading or
384
+ # updating notebook routines created through the older Routine Manager service.
385
+
378
386
  # Create a v2 event-action routine
379
387
  # --event: JSON object with `type` and `triggers` array
380
388
  # --actions: JSON array of action objects
@@ -401,7 +409,10 @@ slcli routine create --api-version v1 \
401
409
  --name "On Upload" \
402
410
  --type TRIGGERED \
403
411
  --notebook-id <NOTEBOOK_ID> \
404
- --trigger '{"source":"FILES","events":["CREATED"],"filter":"extension=\".csv\""}'
412
+ --trigger '{"source":"FILES","events":["CREATED"],"filter":"extension=\".xml\""}'
413
+
414
+ # For compound FILES filters and provider-specific live examples, load
415
+ # routine-examples.md in this folder.
405
416
 
406
417
  # Update a routine (only supplied fields are changed)
407
418
  slcli routine update <ROUTINE_ID> [--api-version v1|v2] \
@@ -420,6 +431,10 @@ slcli routine delete <ROUTINE_ID> [--api-version v1|v2] [-y]
420
431
 
421
432
  ### v2 event JSON structure
422
433
 
434
+ For v2 routines, there is no top-level routine `filter` field. Filtering is
435
+ provider-specific and belongs inside `event.triggers[].configuration` when the
436
+ provider supports it.
437
+
423
438
  ```json
424
439
  {
425
440
  "type": "TAG",
@@ -437,9 +452,41 @@ slcli routine delete <ROUTINE_ID> [--api-version v1|v2] [-y]
437
452
  }
438
453
  ```
439
454
 
440
- Supported TAG comparators: `GREATER_THAN`, `LESS_THAN`, `EQUAL`, `NOT_EQUAL`.
455
+ Observed TAG comparators include `GREATER_THAN`, `GREATER_THAN_OR_EQUAL`, `LESS_THAN`, `EQUAL`, `NOT_EQUAL`, and `IN_RANGE`.
441
456
  Tag data types: `DOUBLE`, `INT32`, `U_INT64`, `STRING`, `BOOLEAN`.
442
457
 
458
+ Some v2 providers use a string filter inside trigger configuration instead of
459
+ structured comparator/path fields. Example from a `WORKITEMCHANGED` routine:
460
+
461
+ ```json
462
+ {
463
+ "type": "WORKITEMCHANGED",
464
+ "triggers": [
465
+ {
466
+ "name": "8f4db567-9686-4e4b-ac2c-31345cb01691",
467
+ "configuration": {
468
+ "filter": "(before.assignedTo != after.assignedTo) && (after.assignedTo = \"a69caa22-7e24-445f-8e9f-084ed98ff6e3\")"
469
+ }
470
+ }
471
+ ]
472
+ }
473
+ ```
474
+
475
+ Another observed string-filter provider is `TESTRESULTCHANGED`:
476
+
477
+ ```json
478
+ {
479
+ "type": "TESTRESULTCHANGED",
480
+ "triggers": [
481
+ {
482
+ "configuration": {
483
+ "filter": "(before.status != after.status) && (after.programName = \"...\")"
484
+ }
485
+ }
486
+ ]
487
+ }
488
+ ```
489
+
443
490
  ### v2 actions JSON structure
444
491
 
445
492
  ```json
@@ -465,44 +512,13 @@ Tag data types: `DOUBLE`, `INT32`, `U_INT64`, `STRING`, `BOOLEAN`.
465
512
 
466
513
  The second ALARM entry with trigger `nisystemlink_no_triggers_breached` is required by the API — it handles the alarm clear/reset state. Email notifications are delivered via `dynamicRecipientList` inside the ALARM action configuration. Severity levels: 1 (low) – 4 (critical).
467
514
 
468
- ### Full example: tag threshold monitor with alarm + email
515
+ Load [routine-examples.md](./routine-examples.md) for sanitized live examples covering:
469
516
 
470
- ```bash
471
- slcli routine create \
472
- --name "Fred Tag Monitor" \
473
- --description "Alert when fred.test.* exceeds 10.2" \
474
- --enabled \
475
- --event '{
476
- "type": "TAG",
477
- "triggers": [{
478
- "name": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
479
- "configuration": {
480
- "comparator": "GREATER_THAN",
481
- "path": "fred.test.*",
482
- "thresholds": ["10.2"],
483
- "type": "DOUBLE"
484
- }
485
- }]
486
- }' \
487
- --actions '[
488
- {
489
- "type": "ALARM",
490
- "triggers": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
491
- "configuration": {
492
- "displayName": "Fred Test Tag Alarm",
493
- "description": "Tag fred.test.* exceeded 10.2",
494
- "severity": 4,
495
- "condition": "Greater than: 10.2",
496
- "dynamicRecipientList": ["fred.visser@emerson.com"]
497
- }
498
- },
499
- {
500
- "type": "ALARM",
501
- "triggers": ["nisystemlink_no_triggers_breached"],
502
- "configuration": null
503
- }
504
- ]'
505
- ```
517
+ - v1 FILES filters that combine workspace checks, `name.Contains(...)`, and extension matching
518
+ - v2 TAG routines using `IN_RANGE`, `NOT_EQUAL`, and `GREATER_THAN_OR_EQUAL`
519
+ - v2 `TESTRESULTCHANGED` filters with nested field checks, indexed property access, and `DateTime.parse(...)`
520
+ - v2 `WORKITEMCHANGED` filters with `.Any(...)` and `!Contains(...)`
521
+ - Representative NOTEBOOK and ALARM action payloads
506
522
 
507
523
  ## comment — Resource comments
508
524
 
@@ -0,0 +1,186 @@
1
+ # Routine Configuration Examples
2
+
3
+ Load this file when you need sanitized live examples for provider-specific
4
+ routine payloads beyond the minimal syntax in `commands.md`.
5
+
6
+ ## v1 notebook routines
7
+
8
+ ### Scheduled notebook execution
9
+
10
+ ```bash
11
+ slcli routine create --api-version v1 \
12
+ --name "Daily Notebook" \
13
+ --type SCHEDULED \
14
+ --notebook-id <NOTEBOOK_ID> \
15
+ --schedule '{"startTime":"2026-01-01T00:00:00Z","repeat":"DAY"}'
16
+ ```
17
+
18
+ ### FILES trigger with compound filter
19
+
20
+ Observed v1 routines use the service-owned `trigger.filter` string directly.
21
+ This can be more expressive than the simple `extension=".xml"` example.
22
+
23
+ ```json
24
+ {
25
+ "trigger": {
26
+ "source": "FILES",
27
+ "events": ["CREATED"],
28
+ "filter": "workspace = \"<WORKSPACE_ID>\" && (name.Contains(\"Specs\") && extension = \"xlsx\")"
29
+ },
30
+ "execution": {
31
+ "type": "NOTEBOOK",
32
+ "definition": {
33
+ "notebookId": "<NOTEBOOK_ID>"
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ Notes:
40
+
41
+ - Keep the v1 filter string in the service's own syntax.
42
+ - Observed FILES filters can combine workspace checks, `name.Contains(...)`, and extension checks.
43
+
44
+ ## v2 event-action routines
45
+
46
+ ### TAG alarm with structured trigger fields
47
+
48
+ Observed TAG routines can use comparator-driven configuration instead of a
49
+ string `filter`.
50
+
51
+ ```json
52
+ {
53
+ "event": {
54
+ "type": "TAG",
55
+ "triggers": [
56
+ {
57
+ "configuration": {
58
+ "comparator": "IN_RANGE",
59
+ "deadband": 2,
60
+ "path": "*.path.to.tag",
61
+ "thresholds": ["1", "12"],
62
+ "type": "INT"
63
+ }
64
+ },
65
+ {
66
+ "configuration": {
67
+ "comparator": "NOT_EQUAL",
68
+ "path": "*.path.to.tag",
69
+ "thresholds": ["3"],
70
+ "type": "INT"
71
+ }
72
+ }
73
+ ]
74
+ },
75
+ "actions": [
76
+ {
77
+ "type": "ALARM",
78
+ "configuration": {
79
+ "displayName": "Alarm Name",
80
+ "severity": 4,
81
+ "condition": "In range: [1, 12]",
82
+ "dynamicRecipientList": ["user@example.com"]
83
+ }
84
+ }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ ### TAG health monitor with threshold alarm
90
+
91
+ ```json
92
+ {
93
+ "event": {
94
+ "type": "TAG",
95
+ "triggers": [
96
+ {
97
+ "configuration": {
98
+ "comparator": "GREATER_THAN_OR_EQUAL",
99
+ "deadband": 5,
100
+ "path": "*.Health.Memory.UsePercentage",
101
+ "thresholds": ["80"],
102
+ "type": "DOUBLE"
103
+ }
104
+ }
105
+ ]
106
+ },
107
+ "actions": [
108
+ {
109
+ "type": "ALARM",
110
+ "configuration": {
111
+ "displayName": "High memory usage on <system>",
112
+ "severity": 3,
113
+ "condition": "Greater than or equal: 80"
114
+ }
115
+ }
116
+ ]
117
+ }
118
+ ```
119
+
120
+ Notes:
121
+
122
+ - Observed TAG comparators include `GREATER_THAN`, `GREATER_THAN_OR_EQUAL`, `NOT_EQUAL`, and `IN_RANGE`.
123
+ - Alarm-producing TAG routines still need the clear/reset action that uses trigger `nisystemlink_no_triggers_breached`.
124
+
125
+ ### TESTRESULTCHANGED filter with nested fields and time parsing
126
+
127
+ ```json
128
+ {
129
+ "event": {
130
+ "type": "TESTRESULTCHANGED",
131
+ "triggers": [
132
+ {
133
+ "configuration": {
134
+ "filter": "(before.partNumber != after.partNumber) && ((after.status.statusType = \"Done\" && after.hostName = \"<HOST_NAME>\" && after.operator = \"<OPERATOR>\" && after.properties[\"key\"] = \"value\" || after.programName = \"Test Name\" && DateTime(after.updatedAt) > DateTime.parse(\"2026-05-14T19:23:15.275Z\")))"
135
+ }
136
+ }
137
+ ]
138
+ },
139
+ "actions": [
140
+ {
141
+ "type": "NOTEBOOK",
142
+ "configuration": {
143
+ "notebookId": "<NOTEBOOK_ID>",
144
+ "resourceProfile": "LOW",
145
+ "priority": "MEDIUM",
146
+ "serviceAccount": "<SERVICE_ACCOUNT_ID>"
147
+ }
148
+ }
149
+ ]
150
+ }
151
+ ```
152
+
153
+ Notes:
154
+
155
+ - Observed filters can combine before/after comparisons, nested status fields, indexed property lookups, and `DateTime.parse(...)`.
156
+
157
+ ### WORKITEMCHANGED filter with collection predicates
158
+
159
+ ```json
160
+ {
161
+ "event": {
162
+ "type": "WORKITEMCHANGED",
163
+ "triggers": [
164
+ {
165
+ "configuration": {
166
+ "filter": "(before.assignedTo != after.assignedTo) && (after.resources.assets.selections.Any(s => s.id == \"<ASSET_ID>\") && !after.description.Contains(\"description\") && after.templateId = \"123\")"
167
+ }
168
+ }
169
+ ]
170
+ },
171
+ "actions": [
172
+ {
173
+ "type": "NOTEBOOK",
174
+ "configuration": {
175
+ "resourceProfile": "HIGH",
176
+ "priority": "HIGH"
177
+ }
178
+ }
179
+ ]
180
+ }
181
+ ```
182
+
183
+ Notes:
184
+
185
+ - Observed `WORKITEMCHANGED` filters can use `.Any(...)`, negated string checks, and exact template matching.
186
+ - Common NOTEBOOK action fields across v2 examples are `notebookId`, `parameters`, `resourceProfile`, `priority`, and `serviceAccount`.
@@ -38,7 +38,7 @@ Before generating code, clarify only the details that change the implementation:
38
38
  4. Auth context: same-origin hosted app versus remote/dev API-key flow.
39
39
  5. Deployment target: ordinary hosted webapp only, or Plugin Manager package as well.
40
40
 
41
- Do not ask about Angular or Nimble versions unless the user is constrained by an existing project. Default to Angular 20 and the latest compatible `@ni/nimble-angular`.
41
+ Do not ask about Angular or Nimble versions unless the user is constrained by an existing project. Default to Angular 20 and the latest compatible `@ni/nimble-angular`, but verify the installed versions immediately after scaffold instead of assuming the generator produced the expected combination.
42
42
 
43
43
  For new SystemLink apps, recommend installing the NI Angular UI packages together unless the user is intentionally minimizing dependencies. `@ni/nimble-angular` remains the default foundation, `@ni/spright-angular` adds Spright chat and icon components, and `@ni/ok-angular` adds OK-specific controls such as accordion items and search input.
44
44
 
@@ -56,11 +56,31 @@ Then generate Angular in that starter directory so the SystemLink scaffolding st
56
56
 
57
57
  ```bash
58
58
  npx -y @angular/cli@20 new <app-name> --directory . --routing --style=scss --skip-git --no-standalone --defaults --force
59
- npm install @ni/nimble-angular @ni/spright-angular @ni/ok-angular @ni/systemlink-clients-ts
59
+ npm install @ni/nimble-angular @ni/nimble-components @ni/unit-format @ni/spright-angular @ni/ok-angular @ni/systemlink-clients-ts @angular/localize
60
+ npm install --save-dev @angular-devkit/build-angular
60
61
  ```
61
62
 
62
63
  Prefer NgModule-based apps for this workflow. The Nimble Angular wrapper modules fit naturally into a centralized `AppModule`, which reduces template surprises and keeps imports explicit.
63
64
 
65
+ Immediately after scaffold, inspect `package.json` and `angular.json` before building features. The generator or migrations may leave the workspace on the wrong Angular major or on a builder configuration that does not bundle `@ni/nimble-angular` cleanly.
66
+
67
+ For the currently supported path, standardize on:
68
+
69
+ - Angular 20.x
70
+ - `@ni/nimble-angular` 33.2.x
71
+ - `@ni/nimble-components` 35.8.x
72
+ - `@ni/unit-format` 1.0.4+
73
+ - `@angular/localize` installed and added to build and test polyfills
74
+
75
+ If the workspace ends up on `@angular/build:application` and Nimble fails to bundle with `Could not resolve '@ni/nimble-components/dist/esm/...'`, switch `angular.json` back to the legacy Angular builders:
76
+
77
+ - `@angular-devkit/build-angular:browser`
78
+ - `@angular-devkit/build-angular:dev-server`
79
+ - `@angular-devkit/build-angular:extract-i18n`
80
+ - `@angular-devkit/build-angular:karma`
81
+
82
+ This fallback is not optional when the Nimble packages fail under the application builder. Fix the builder mismatch before implementing more UI.
83
+
64
84
  Recommend installing `@ni/spright-angular` and `@ni/ok-angular` early even if the first slice only uses Nimble. That avoids dependency churn later when the UI needs chat surfaces, product-specific icons, accordion items, or the OK search input.
65
85
 
66
86
  If the user has not run `slcli webapp init` and explicitly wants a SystemLink-hosted webapp, recommend it first unless they want a manual setup.
@@ -76,6 +96,8 @@ These decisions prevent the most common hosted-webapp failures:
76
96
  - Do not add `CUSTOM_ELEMENTS_SCHEMA` just to silence missing Nimble module imports.
77
97
  - Put theme-aware color and shadow aliases on `nimble-theme-provider`, not on `:root`.
78
98
  - Import `@angular/localize/init` in Angular polyfills for both build and test paths.
99
+ - Import Nimble fonts once in the root `src/styles.scss` with `@use '@ni/nimble-angular/styles/fonts' as *;`. Without this, Nimble components render with fallback system fonts instead of the required Source Sans Pro typeface.
100
+ - Run a production build immediately after setup changes. Do not postpone the first `npm run build` until after the UI is implemented.
79
101
 
80
102
  If you need the exact module patterns or template wiring, load [references/nimble-angular.md](./references/nimble-angular.md).
81
103
  If you need a concise package-level inventory before choosing components, load [references/angular-ui-packages.md](./references/angular-ui-packages.md).
@@ -90,6 +112,16 @@ Use SystemLink-appropriate layout defaults instead of inventing page structure f
90
112
  - Use accordions for grouped fields and advanced configuration.
91
113
  - Use cards sparingly for summaries, not as the default editing or data layout.
92
114
 
115
+ Treat Nimble alignment as a requirement, not a style preference:
116
+
117
+ - Use Nimble controls for primary actions, selection, inputs, status, and data display.
118
+ - Use raw HTML elements mostly for semantic grouping, layout wrappers, and text structure.
119
+ - Do not build custom-styled buttons, inputs, dropdowns, tabs, or pseudo-cards when Nimble already provides the interaction primitive.
120
+ - Prefer Nimble spacing, borders, focus states, and theme tokens over bespoke visual treatments.
121
+ - If a page starts to look like a generic marketing dashboard instead of a SystemLink tool, pull it back toward table/list-detail, drawers, banners, tabs, and structured metadata panels.
122
+
123
+ The goal is a webapp that feels native to the SystemLink shell, not an arbitrary Angular site hosted inside it.
124
+
93
125
  Load [references/layout-patterns.md](./references/layout-patterns.md) when the task turns into page composition, spacing, or shell layout work.
94
126
 
95
127
  ### 4. Integrate SystemLink APIs the low-risk way
@@ -117,6 +149,14 @@ When the user asks for implementation, prefer one working slice over a full app
117
149
  - one error banner
118
150
  - one settings/control path only if required
119
151
 
152
+ For a new app, the first vertical slice should also prove the setup:
153
+
154
+ - scaffold completes
155
+ - Angular and NI package versions are compatible
156
+ - the app builds successfully
157
+ - one Nimble-based route renders
158
+ - one real SystemLink query works in the hosted shell
159
+
120
160
  This keeps context narrow and usually reveals the real integration blockers faster than broad scaffolding.
121
161
 
122
162
  ### 6. Publish or package only after the hosted constraints are covered
@@ -137,6 +177,7 @@ Always verify:
137
177
  - the browser console is clear of blocking errors
138
178
  - the correct SystemLink data loads
139
179
  - light/dark theme switching updates the app in real time
180
+ - the page still reads as a Nimble/SystemLink experience rather than a custom HTML dashboard
140
181
 
141
182
  Load [references/troubleshooting.md](./references/troubleshooting.md) for the hosted validation flow and symptom-based fixes.
142
183
 
@@ -145,14 +186,20 @@ Load [references/troubleshooting.md](./references/troubleshooting.md) for the ho
145
186
  Before you consider a SystemLink webapp slice correct, confirm all of the following:
146
187
 
147
188
  - Angular 20 workspace created in the intended starter directory.
189
+ - Angular and NI package versions verified after scaffold, not assumed.
190
+ - `@ni/nimble-components`, `@ni/unit-format`, `@angular/localize`, and `@angular-devkit/build-angular` installed when using `@ni/nimble-angular`.
191
+ - `angular.json` uses builders that are known to bundle Nimble successfully.
148
192
  - `AppModule` provides `APP_BASE_HREF`.
149
193
  - `index.html` does not contain a `<base>` element.
150
194
  - Router uses `useHash: true`.
151
195
  - Production build disables `inlineCritical`.
196
+ - Root `src/styles.scss` imports `@use '@ni/nimble-angular/styles/fonts' as *;`.
152
197
  - Nimble Angular modules are imported explicitly.
198
+ - Primary interaction controls use Nimble wrappers rather than custom HTML surrogates.
153
199
  - No hardcoded colors in component SCSS.
154
200
  - Theme-aware aliases live on `nimble-theme-provider`.
155
201
  - API client uses the correct SystemLink service base URL.
202
+ - `npm run build` passes before publish.
156
203
  - Hosted deployment is validated after publish.
157
204
 
158
205
  ## Default implementation stance
@@ -162,20 +209,26 @@ Use these defaults unless the user asks for a different tradeoff:
162
209
  - Angular 20
163
210
  - NgModule-based app
164
211
  - `@ni/nimble-angular`
212
+ - `@ni/nimble-components`
213
+ - `@ni/unit-format`
165
214
  - `@ni/spright-angular`
166
215
  - `@ni/ok-angular`
167
216
  - `@ni/systemlink-clients-ts`
168
217
  - table-first data presentation
169
218
  - same-origin cookie auth
170
219
  - long-form CLI flags in examples and commands
220
+ - Nimble-first interaction design with minimal bespoke chrome
171
221
 
172
222
  ## Common mistakes to prevent up front
173
223
 
174
224
  - Treating the app like a normal root-hosted Angular SPA instead of an iframe/sub-path app.
225
+ - Assuming the scaffolded Angular major or builder is already correct for Nimble.
226
+ - Waiting until the end of implementation to run the first production build.
175
227
  - Checking only the `theme` attribute instead of verifying resolved Nimble tokens.
176
228
  - Putting theme-aware aliases on `:root`.
177
229
  - Overriding SDK base URLs with incomplete service prefixes.
178
230
  - Using raw HTML controls where Nimble primitives should define the interaction model.
231
+ - Letting the page drift into a custom dashboard aesthetic that ignores Nimble interaction and spacing patterns.
179
232
  - Loading too much reference material before the task requires it.
180
233
 
181
234
  ## When to escalate into the references
@@ -3,7 +3,10 @@
3
3
  ## Prerequisites
4
4
 
5
5
  - `slcli` installed and authenticated (`slcli login` or config file present)
6
- - Angular app built to `dist/<app-name>/browser/`
6
+ - Angular app built successfully
7
+ - Publish path confirmed for the active builder:
8
+ - `dist/<app-name>/browser/` for the application builder
9
+ - `dist/<app-name>/` for the legacy browser builder
7
10
 
8
11
  ---
9
12
 
@@ -11,12 +14,19 @@
11
14
 
12
15
  ```bash
13
16
  # Run from project root
14
- node_modules/.bin/ng build --configuration production --output-path dist/<app-name>
17
+ node_modules/.bin/ng build --configuration production
15
18
  ```
16
19
 
17
20
  **Do NOT pass `--base-href`.** This would reintroduce a `<base>` element that violates SystemLink's CSP.
18
21
 
19
- Angular 19 places the browser output at `dist/<app-name>/browser/` — publish that subdirectory, not the parent.
22
+ Angular may emit different publish roots depending on the active builder.
23
+
24
+ - `@angular/build:application` emits browser assets under `dist/<app-name>/browser/`
25
+ - `@angular-devkit/build-angular:browser` emits browser assets directly under `dist/<app-name>/`
26
+
27
+ Always inspect the actual build output before publishing. Do not hardcode `/browser/` if the workspace is on the legacy builder.
28
+
29
+ If `npm run build` fails with `Could not resolve '@ni/nimble-components/dist/esm/...'` while using `@ni/nimble-angular`, switch the workspace to the legacy Angular browser builder before continuing. Do not publish from a half-fixed setup.
20
30
 
21
31
  ### Background build (if terminal has heredoc/interrupt issues)
22
32
 
@@ -33,7 +43,7 @@ tail -f /tmp/ng-build.log
33
43
  ## First deploy (no existing webapp)
34
44
 
35
45
  ```bash
36
- slcli webapp publish dist/<app-name>/browser/ --workspace <workspace-name>
46
+ slcli webapp publish <ACTUAL_BUILD_OUTPUT_DIR> --workspace <workspace-name>
37
47
  ```
38
48
 
39
49
  The command prints the new webapp ID. **Save it** — you need it for every future redeploy and for `slcli webapp open`.
@@ -49,7 +59,7 @@ Created webapp: 3727d9ac-86e1-4d6e-820e-d2630c1b28e9
49
59
  ## Redeploy (update existing webapp)
50
60
 
51
61
  ```bash
52
- slcli webapp publish dist/<app-name>/browser/ --workspace <workspace-name> --id <webapp-id>
62
+ slcli webapp publish <ACTUAL_BUILD_OUTPUT_DIR> --workspace <workspace-name> --id <webapp-id>
53
63
  ```
54
64
 
55
65
  ---
@@ -86,9 +96,11 @@ Before publishing, verify:
86
96
  - [ ] `app.module.ts` provides `{ provide: APP_BASE_HREF, useValue: '/' }`
87
97
  - [ ] `app-routing.module.ts` uses `useHash: true`
88
98
  - [ ] `angular.json` has `inlineCritical: false` in production optimization
99
+ - [ ] `angular.json` uses a builder that bundles `@ni/nimble-angular` successfully
89
100
  - [ ] `basePath` is `window.location.origin + '/<service-prefix>'` (not just origin)
90
101
  - [ ] `credentials: 'include'` (or equivalent) set on API client
91
102
  - [ ] Build succeeded with no errors (warnings about bundle size are OK if within 2MB error limit)
103
+ - [ ] Publish path matches the active builder output
92
104
 
93
105
  ---
94
106
 
@@ -114,6 +126,11 @@ Before publishing, verify:
114
126
  - Beasties CSS inliner is injecting `onload` handlers
115
127
  - Fix: set `inlineCritical: false` in angular.json
116
128
 
129
+ ### Nimble packages fail to resolve during build
130
+
131
+ - You may be on `@angular/build:application` with a Nimble package layout that esbuild does not resolve cleanly
132
+ - Fix: install `@angular-devkit/build-angular` and switch to the legacy browser/dev-server builders in `angular.json`
133
+
117
134
  ### "Budget exceeded" build error
118
135
 
119
136
  Increase error limits in `angular.json`:
@@ -10,6 +10,32 @@ When building Angular apps with Nimble, use `@ni/nimble-angular` wrapper modules
10
10
  - Do not add `CUSTOM_ELEMENTS_SCHEMA` just to silence unknown Nimble elements in templates. That usually hides a missing module import and weakens Angular's template validation.
11
11
  - If a Nimble icon or control is unknown, first look for the matching module in `@ni/nimble-angular` and import it.
12
12
 
13
+ ## Fonts
14
+
15
+ Nimble requires the Source Sans Pro font family. Without this import, all Nimble components render with fallback system fonts (Arial) and the UI will not match the SystemLink design system.
16
+
17
+ Import the fonts **once** in the root `src/styles.scss`:
18
+
19
+ ```scss
20
+ @use '@ni/nimble-angular/styles/fonts' as *;
21
+ ```
22
+
23
+ This registers `@font-face` declarations for Source Sans Pro (Regular, Light, SemiBold) and Source Code Pro, loading `.woff2` files bundled in `@ni/nimble-tokens`.
24
+
25
+ To use Nimble design tokens (colors, font sizes, spacing) in component SCSS files, also import:
26
+
27
+ ```scss
28
+ @use '@ni/nimble-angular/styles/tokens' as *;
29
+
30
+ .my-element {
31
+ font-family: $ni-nimble-body-font-family;
32
+ font-size: $ni-nimble-body-font-size;
33
+ color: $ni-nimble-body-font-color;
34
+ }
35
+ ```
36
+
37
+ Do not duplicate the fonts import in component SCSS — it belongs only in the global `styles.scss`.
38
+
13
39
  ## nimble-theme-provider
14
40
 
15
41
  Wrap your entire app. Always place at the root component level.
@@ -46,6 +46,7 @@ If the `theme` attribute changes but the colors do not:
46
46
  | Error or symptom | Likely cause | Fix |
47
47
  | ----------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------- |
48
48
  | `$localize is not defined` | Angular localize polyfill missing | Add `@angular/localize/init` to Angular polyfills |
49
+ | `Could not resolve '@ni/nimble-components/dist/esm/...'` during build | Nimble package layout not bundling under Angular application builder | Install `@angular-devkit/build-angular` and switch `angular.json` back to the legacy browser/dev-server builders |
49
50
  | NG04002 or blank screen | Path routing under SystemLink sub-path | Use hash routing |
50
51
  | CSP `base-uri` error | `<base>` tag present | Remove `<base>` and provide `APP_BASE_HREF` via DI |
51
52
  | CSP `unsafe-inline` error from styles | Critical CSS inlining injected handlers | Set `inlineCritical: false` |
@@ -63,6 +64,7 @@ If the `theme` attribute changes but the colors do not:
63
64
  - confirm `nimble-theme-provider` is present
64
65
  - confirm the required Nimble Angular modules are imported
65
66
  - confirm the app uses Nimble components instead of native HTML controls for primary interactions
67
+ - confirm the page is not relying on custom-styled HTML buttons, inputs, or cards where Nimble controls should own the interaction
66
68
 
67
69
  ### App follows the shell theme attribute but colors still look wrong
68
70
 
@@ -76,6 +78,13 @@ If the `theme` attribute changes but the colors do not:
76
78
  - verify cookie auth versus API-key mode
77
79
  - verify the generated request body shape matches the real API
78
80
 
81
+ ### Build fails before the app ever runs
82
+
83
+ - verify the Angular major matches the installed `@ni/nimble-angular` peer dependency
84
+ - verify `@ni/nimble-components`, `@ni/unit-format`, and `@angular/localize` are installed
85
+ - if the workspace uses `@angular/build:application` and Nimble imports fail to resolve, move back to `@angular-devkit/build-angular:browser`
86
+ - rerun `npm run build` before changing more application code
87
+
79
88
  ### Dialogs or advanced overlays do not open
80
89
 
81
90
  - do not gate `nimble-dialog` with `*ngIf`
@@ -87,6 +96,7 @@ Before publishing or redeploying, verify:
87
96
 
88
97
  - no hardcoded colors remain in component styles
89
98
  - Nimble primitives are used for the main controls and data views
99
+ - the page reads as a Nimble/SystemLink tool rather than a bespoke HTML dashboard
90
100
  - `APP_BASE_HREF` is provided and no `<base>` tag exists
91
101
  - routing uses `useHash: true`
92
102
  - production build disables `inlineCritical`
File without changes