systemlink-cli 1.9.2__tar.gz → 1.9.4__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 (83) hide show
  1. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/PKG-INFO +1 -1
  2. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/pyproject.toml +38 -31
  3. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/_version.py +1 -1
  4. systemlink_cli-1.9.4/slcli/mcp_reachability.py +53 -0
  5. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skill_click.py +51 -21
  6. systemlink_cli-1.9.4/slcli/skills/nipkg-file-package/SKILL.md +541 -0
  7. systemlink_cli-1.9.4/slcli/skills/systemlink-job-debugging/SKILL.md +325 -0
  8. systemlink_cli-1.9.4/slcli/skills/systemlink-python-test/SKILL.md +547 -0
  9. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/utils.py +4 -1
  10. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/webapp_click.py +107 -38
  11. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/LICENSE +0 -0
  12. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/dff-editor/editor.js +0 -0
  13. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/dff-editor/index.html +0 -0
  14. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/__init__.py +0 -0
  15. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/__main__.py +0 -0
  16. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/asset_click.py +0 -0
  17. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/cli_formatters.py +0 -0
  18. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/cli_utils.py +0 -0
  19. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/comment_click.py +0 -0
  20. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/completion_click.py +0 -0
  21. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/config.py +0 -0
  22. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/config_click.py +0 -0
  23. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/dff_click.py +0 -0
  24. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/dff_decorators.py +0 -0
  25. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/example_click.py +0 -0
  26. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/example_loader.py +0 -0
  27. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/example_provisioner.py +0 -0
  28. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/README.md +0 -0
  29. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/_schema/schema-v1.0.json +0 -0
  30. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/demo-complete-workflow/README.md +0 -0
  31. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/demo-complete-workflow/config.yaml +0 -0
  32. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/demo-test-plans/README.md +0 -0
  33. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/demo-test-plans/config.yaml +0 -0
  34. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
  35. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
  36. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
  37. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
  38. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
  39. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
  40. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
  41. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
  42. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
  43. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
  44. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/feed_click.py +0 -0
  45. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/file_click.py +0 -0
  46. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/function_click.py +0 -0
  47. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/function_templates.py +0 -0
  48. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/main.py +0 -0
  49. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/mcp_click.py +0 -0
  50. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/mcp_server.py +0 -0
  51. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/notebook_click.py +0 -0
  52. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/platform.py +0 -0
  53. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/policy_click.py +0 -0
  54. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/policy_utils.py +0 -0
  55. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/profiles.py +0 -0
  56. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/response_handlers.py +0 -0
  57. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/rich_output.py +0 -0
  58. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/routine_click.py +0 -0
  59. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/slcli/SKILL.md +0 -0
  60. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
  61. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/slcli/references/filtering.md +0 -0
  62. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-notebook/SKILL.md +0 -0
  63. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-notebook/references/interfaces.md +0 -0
  64. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-notebook/references/notebook-patterns.md +0 -0
  65. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-webapp/SKILL.md +0 -0
  66. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-webapp/references/deployment.md +0 -0
  67. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-webapp/references/layout-patterns.md +0 -0
  68. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-webapp/references/nimble-angular.md +0 -0
  69. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/skills/systemlink-webapp/references/systemlink-services.md +0 -0
  70. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/ssl_trust.py +0 -0
  71. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/system_click.py +0 -0
  72. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/table_utils.py +0 -0
  73. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/tag_click.py +0 -0
  74. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/templates_click.py +0 -0
  75. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/testmonitor_click.py +0 -0
  76. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/universal_handlers.py +0 -0
  77. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/user_click.py +0 -0
  78. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/web_editor.py +0 -0
  79. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/workflow_preview.py +0 -0
  80. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/workflows_click.py +0 -0
  81. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/workitem_click.py +0 -0
  82. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/workspace_click.py +0 -0
  83. {systemlink_cli-1.9.2 → systemlink_cli-1.9.4}/slcli/workspace_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemlink-cli
3
- Version: 1.9.2
3
+ Version: 1.9.4
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.9.2"
3
+ version = "1.9.4"
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" }]
@@ -16,6 +16,7 @@ slcli = "slcli.__main__:cli"
16
16
  slcli-mcp = "slcli.mcp_server:main"
17
17
  build-pyinstaller = "scripts.build_pyinstaller:main"
18
18
  update-version = "scripts.update_version:main"
19
+ release-from-changes = "scripts.towncrier_release:main"
19
20
  lint = "scripts.lint:main"
20
21
 
21
22
  [tool.poetry.group.mcp]
@@ -59,8 +60,8 @@ pyinstaller = "^6.14.2"
59
60
  types-requests = "*"
60
61
  types-tabulate = "*"
61
62
 
62
- # Semantic Release
63
- python-semantic-release = "^10.0.0"
63
+ # Changelog and release management
64
+ towncrier = "^25.8.0"
64
65
  pytest-xdist = "^3.8.0"
65
66
 
66
67
  # Excel file generation
@@ -114,34 +115,40 @@ check_untyped_defs = true
114
115
  warn_redundant_casts = true
115
116
  warn_unreachable = true
116
117
 
117
- [tool.semantic_release]
118
- version_toml = ["pyproject.toml:tool.poetry.version"]
119
- version_variables = ["slcli/_version.py:__version__"]
120
- build_command = "python scripts/update_version.py"
121
- major_on_zero = false
122
- branch = "main"
123
- upload_to_pypi = true
124
- upload_to_release = true
125
- hvcs = "github"
126
- commit_message = "chore(release): {version}"
127
- tag_format = "v{version}"
128
-
129
- [tool.semantic_release.commit_parser_options]
130
- allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "style", "refactor", "test"]
131
- minor_tags = ["feat"]
132
- patch_tags = ["fix", "perf"]
133
-
134
- [tool.semantic_release.changelog]
135
- template_dir = "templates"
136
- exclude_commit_patterns = []
137
-
138
- [tool.semantic_release.changelog.default_templates]
139
- changelog_file = "CHANGELOG.md"
140
-
141
- [tool.semantic_release.branches.main]
142
- match = "(main|master)"
143
- prerelease_token = "rc"
144
- prerelease = false
118
+ [tool.towncrier]
119
+ package = "slcli"
120
+ package_dir = "."
121
+ directory = "newsfragments"
122
+ filename = "CHANGELOG.md"
123
+ template = "towncrier:default.md"
124
+ start_string = "<!-- towncrier release notes start -->\n"
125
+ title_format = "## v{version} ({project_date})"
126
+ ignore = ["README.md"]
127
+
128
+ [[tool.towncrier.type]]
129
+ directory = "major"
130
+ name = "Breaking Changes"
131
+ showcontent = true
132
+
133
+ [[tool.towncrier.type]]
134
+ directory = "minor"
135
+ name = "Features"
136
+ showcontent = true
137
+
138
+ [[tool.towncrier.type]]
139
+ directory = "patch"
140
+ name = "Bug Fixes"
141
+ showcontent = true
142
+
143
+ [[tool.towncrier.type]]
144
+ directory = "doc"
145
+ name = "Documentation"
146
+ showcontent = true
147
+
148
+ [[tool.towncrier.type]]
149
+ directory = "misc"
150
+ name = "Other Changes"
151
+ showcontent = true
145
152
 
146
153
  [build-system]
147
154
  requires = ["poetry-core>=1.0.0"]
@@ -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.9.2"
4
+ __version__ = "1.9.4"
@@ -0,0 +1,53 @@
1
+ """Helpers for classifying local MCP client connectivity failures."""
2
+
3
+ from typing import Iterator, List
4
+
5
+
6
+ def iter_exceptions(exc: BaseException) -> Iterator[BaseException]:
7
+ """Yield an exception plus any nested causes, contexts, or exception-group members."""
8
+ stack: List[BaseException] = [exc]
9
+ seen: set[int] = set()
10
+
11
+ while stack:
12
+ current = stack.pop()
13
+ marker = id(current)
14
+ if marker in seen:
15
+ continue
16
+ seen.add(marker)
17
+ yield current
18
+
19
+ cause = getattr(current, "__cause__", None)
20
+ if isinstance(cause, BaseException):
21
+ stack.append(cause)
22
+
23
+ context = getattr(current, "__context__", None)
24
+ if isinstance(context, BaseException):
25
+ stack.append(context)
26
+
27
+ if isinstance(current, BaseExceptionGroup):
28
+ stack.extend(current.exceptions)
29
+
30
+
31
+ def is_reachability_failure(exc: BaseException) -> bool:
32
+ """Return True when an exception indicates the local MCP server is unreachable."""
33
+ for candidate in iter_exceptions(exc):
34
+ if isinstance(candidate, (OSError, TimeoutError)):
35
+ return True
36
+
37
+ message = str(candidate).lower()
38
+ if any(
39
+ token in message
40
+ for token in (
41
+ "connection refused",
42
+ "connect error",
43
+ "all connection attempts failed",
44
+ "timed out",
45
+ "timeout",
46
+ "name or service not known",
47
+ "nodename nor servname provided",
48
+ "server disconnected",
49
+ )
50
+ ):
51
+ return True
52
+
53
+ return False
@@ -11,7 +11,14 @@ import questionary
11
11
  from .utils import ExitCodes
12
12
 
13
13
  SKILL_NAME = "slcli"
14
- SKILL_CHOICES = ["slcli", "systemlink-webapp", "systemlink-notebook"]
14
+ _FALLBACK_SKILL_CHOICES = [
15
+ "nipkg-file-package",
16
+ "slcli",
17
+ "systemlink-job-debugging",
18
+ "systemlink-notebook",
19
+ "systemlink-python-test",
20
+ "systemlink-webapp",
21
+ ]
15
22
 
16
23
  # Mapping of client name -> (personal skills dir, project subdir relative to repo root)
17
24
  # personal dir uses Path.home() so it's always resolved at call time via _personal_dir().
@@ -23,6 +30,45 @@ _CLIENT_TABLE: Dict[str, Tuple[str, str]] = {
23
30
  CLIENT_CHOICES = list(_CLIENT_TABLE.keys())
24
31
 
25
32
 
33
+ def _skills_dir_candidates() -> List[Path]:
34
+ """Return candidate bundled skills directories for source and frozen layouts."""
35
+ candidates: List[Path] = []
36
+
37
+ meipass = getattr(sys, "_MEIPASS", None)
38
+ if meipass:
39
+ candidates.append(Path(meipass) / "skills")
40
+
41
+ if getattr(sys, "frozen", False):
42
+ candidates.append(Path(sys.executable).resolve().parent / "skills")
43
+
44
+ candidates.append(Path(__file__).resolve().parent / "skills")
45
+ return candidates
46
+
47
+
48
+ def _skill_names_in_directory(directory: Path) -> List[str]:
49
+ """Return sorted bundled skill names for a skills directory."""
50
+ if not directory.exists():
51
+ return []
52
+
53
+ return sorted(
54
+ child.name
55
+ for child in directory.iterdir()
56
+ if child.is_dir() and (child / "SKILL.md").exists()
57
+ )
58
+
59
+
60
+ def _discover_skill_choices() -> List[str]:
61
+ """Discover bundled skills from the current installation layout."""
62
+ for candidate in _skills_dir_candidates():
63
+ names = _skill_names_in_directory(candidate)
64
+ if names:
65
+ return names
66
+ return list(_FALLBACK_SKILL_CHOICES)
67
+
68
+
69
+ SKILL_CHOICES = _discover_skill_choices()
70
+
71
+
26
72
  def _personal_dir(client: str) -> Path:
27
73
  """Return the resolved personal skills directory for a client."""
28
74
  return Path(_CLIENT_TABLE[client][0]).expanduser()
@@ -57,24 +103,8 @@ def _find_bundled_skills_dir() -> Path:
57
103
  Raises:
58
104
  FileNotFoundError: If the skills directory cannot be found.
59
105
  """
60
- candidates: List[Path] = []
61
-
62
- # PyInstaller onefile mode
63
- meipass = getattr(sys, "_MEIPASS", None)
64
- if meipass:
65
- candidates.append(Path(meipass) / "skills")
66
-
67
- # PyInstaller onedir / frozen executable
68
- if getattr(sys, "frozen", False):
69
- candidates.append(Path(sys.executable).resolve().parent / "skills")
70
-
71
- # pip install / development: skills/ bundled inside the slcli package
72
- candidates.append(Path(__file__).resolve().parent / "skills")
73
-
74
- for candidate in candidates:
75
- if candidate.exists() and any(
76
- (candidate / name / "SKILL.md").exists() for name in SKILL_CHOICES
77
- ):
106
+ for candidate in _skills_dir_candidates():
107
+ if _skill_names_in_directory(candidate):
78
108
  return candidate
79
109
 
80
110
  raise FileNotFoundError(
@@ -178,7 +208,7 @@ def register_skill_commands(cli: Any) -> None:
178
208
  "-k",
179
209
  type=click.Choice(SKILL_CHOICES + ["all"], case_sensitive=False),
180
210
  default=None,
181
- help="Skill to install (slcli, systemlink-webapp, systemlink-notebook, or all).",
211
+ help=f"Skill to install ({', '.join(SKILL_CHOICES)}, or all).",
182
212
  )
183
213
  @click.option(
184
214
  "--client",
@@ -207,7 +237,7 @@ def register_skill_commands(cli: Any) -> None:
207
237
  """Install agent skills for AI coding assistants.
208
238
 
209
239
  Copies bundled skills into the skills directory of one or more AI clients.
210
- Available skills: slcli, systemlink-webapp, systemlink-notebook.
240
+ Available skills are shown in `--help` and prompted interactively.
211
241
  Supported clients and their skill locations:
212
242
 
213
243
  \b