openc3 7.4.0 → 7.5.0

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/bin/openc3cli +4 -3
  3. data/bin/pipinstall +18 -5
  4. data/bin/pipuninstall +1 -1
  5. data/bin/uvinstall +36 -8
  6. data/data/config/default_plugins.yaml +43 -0
  7. data/data/config/interface_modifiers.yaml +22 -7
  8. data/data/config/item_modifiers.yaml +14 -4
  9. data/data/config/plugins.yaml +1 -1
  10. data/data/config/widgets.yaml +1 -1
  11. data/lib/openc3/api/cmd_api.rb +10 -13
  12. data/lib/openc3/api/interface_api.rb +1 -2
  13. data/lib/openc3/api/limits_api.rb +1 -1
  14. data/lib/openc3/api/metrics_api.rb +26 -1
  15. data/lib/openc3/api/router_api.rb +1 -2
  16. data/lib/openc3/api/tlm_api.rb +21 -21
  17. data/lib/openc3/config/config_parser.rb +3 -1
  18. data/lib/openc3/core_ext/tempfile.rb +2 -0
  19. data/lib/openc3/interfaces/file_interface.rb +6 -1
  20. data/lib/openc3/interfaces/http_client_interface.rb +14 -6
  21. data/lib/openc3/interfaces/interface.rb +27 -3
  22. data/lib/openc3/interfaces/protocols/protocol.rb +8 -0
  23. data/lib/openc3/interfaces/read_queue_interface.rb +331 -0
  24. data/lib/openc3/interfaces/stream_interface.rb +22 -3
  25. data/lib/openc3/interfaces/tcpip_server_interface.rb +13 -0
  26. data/lib/openc3/interfaces/udp_interface.rb +16 -2
  27. data/lib/openc3/interfaces.rb +1 -0
  28. data/lib/openc3/io/json_api_object.rb +24 -3
  29. data/lib/openc3/io/json_drb_object.rb +3 -2
  30. data/lib/openc3/logs/log_writer.rb +13 -4
  31. data/lib/openc3/microservices/decom_microservice.rb +7 -4
  32. data/lib/openc3/microservices/interface_microservice.rb +146 -50
  33. data/lib/openc3/microservices/log_microservice.rb +1 -3
  34. data/lib/openc3/microservices/microservice.rb +25 -1
  35. data/lib/openc3/microservices/plugin_microservice.rb +32 -0
  36. data/lib/openc3/microservices/text_log_microservice.rb +1 -3
  37. data/lib/openc3/models/interface_model.rb +1 -1
  38. data/lib/openc3/models/interface_status_model.rb +6 -0
  39. data/lib/openc3/models/metric_model.rb +52 -4
  40. data/lib/openc3/models/microservice_model.rb +7 -3
  41. data/lib/openc3/models/plugin_model.rb +12 -12
  42. data/lib/openc3/models/python_package_model.rb +3 -13
  43. data/lib/openc3/models/reaction_model.rb +6 -3
  44. data/lib/openc3/models/setting_model.rb +5 -3
  45. data/lib/openc3/models/target_model.rb +83 -9
  46. data/lib/openc3/operators/microservice_operator.rb +5 -0
  47. data/lib/openc3/operators/operator.rb +69 -0
  48. data/lib/openc3/packets/packet.rb +10 -4
  49. data/lib/openc3/packets/packet_config.rb +48 -2
  50. data/lib/openc3/packets/packet_item.rb +27 -14
  51. data/lib/openc3/packets/parsers/state_parser.rb +1 -1
  52. data/lib/openc3/packets/parsers/xtce_parser.rb +8 -1
  53. data/lib/openc3/packets/structure_item.rb +3 -2
  54. data/lib/openc3/script/api_shared.rb +58 -84
  55. data/lib/openc3/script/extract.rb +215 -19
  56. data/lib/openc3/script/plugins.rb +4 -11
  57. data/lib/openc3/script/storage.rb +81 -10
  58. data/lib/openc3/script/tables.rb +5 -1
  59. data/lib/openc3/system/system.rb +9 -6
  60. data/lib/openc3/topics/command_decom_topic.rb +1 -1
  61. data/lib/openc3/topics/command_topic.rb +2 -1
  62. data/lib/openc3/topics/router_topic.rb +2 -1
  63. data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
  64. data/lib/openc3/topics/telemetry_topic.rb +3 -2
  65. data/lib/openc3/topics/topic.rb +154 -2
  66. data/lib/openc3/utilities/cli_generator.rb +67 -15
  67. data/lib/openc3/utilities/config_overlay.rb +35 -17
  68. data/lib/openc3/utilities/default_plugins.rb +33 -0
  69. data/lib/openc3/utilities/local_mode.rb +82 -46
  70. data/lib/openc3/utilities/metric.rb +16 -0
  71. data/lib/openc3/utilities/process_stats.rb +160 -0
  72. data/lib/openc3/utilities/pypi_url.rb +65 -0
  73. data/lib/openc3/utilities/questdb_client.rb +43 -46
  74. data/lib/openc3/utilities/running_script.rb +22 -18
  75. data/lib/openc3/utilities/store_autoload.rb +20 -3
  76. data/lib/openc3/utilities/store_queued.rb +37 -9
  77. data/lib/openc3/utilities/target_file.rb +57 -12
  78. data/lib/openc3/utilities/topic_lag_monitor.rb +193 -0
  79. data/lib/openc3/version.rb +5 -5
  80. data/templates/conversion/conversion.py +6 -2
  81. data/templates/conversion/conversion.rb +5 -0
  82. data/templates/plugin/.github/workflows/playwright.yml +62 -0
  83. data/templates/plugin/.github/workflows/release.yml +45 -0
  84. data/templates/plugin/.github/workflows/unit-tests.yml +35 -0
  85. data/templates/plugin/.gitignore +6 -0
  86. data/templates/plugin/README.md +114 -2
  87. data/templates/plugin/lib/PACKAGE/__init__.py +4 -0
  88. data/templates/plugin/plugin.gemspec +10 -1
  89. data/templates/plugin/pyproject.toml +119 -0
  90. data/templates/tool_angular/package.json +2 -2
  91. data/templates/tool_angular/pnpm-workspace.yaml +16 -0
  92. data/templates/tool_react/package.json +1 -1
  93. data/templates/tool_react/pnpm-workspace.yaml +16 -0
  94. data/templates/tool_svelte/package.json +2 -1
  95. data/templates/tool_svelte/pnpm-workspace.yaml +20 -0
  96. data/templates/tool_vue/package.json +3 -3
  97. data/templates/tool_vue/pnpm-workspace.yaml +16 -0
  98. data/templates/widget/package.json +2 -2
  99. data/templates/widget/pnpm-workspace.yaml +16 -0
  100. metadata +36 -1
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '7.4.0'
3
+ OPENC3_VERSION = '7.5.0'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '7'
7
- MINOR = '4'
7
+ MINOR = '5'
8
8
  PATCH = '0'
9
9
  OTHER = ''
10
- BUILD = 'ed0cb44ca3c661eaf2babb77664d0063c955c68c'
10
+ BUILD = 'f77108e1b9d90505ae1ba0a893150c837f879288'
11
11
  end
12
- VERSION = '7.4.0'
13
- GEM_VERSION = '7.4.0'
12
+ VERSION = '7.5.0'
13
+ GEM_VERSION = '7.5.0'
14
14
  end
@@ -1,6 +1,6 @@
1
1
  from openc3.conversions.conversion import Conversion
2
- # Using tlm() requires the following:
3
- # from openc3.api.tlm_api import tlm
2
+ # Using System.telemetry.packet() requires the following:
3
+ # from openc3.system.system import System
4
4
 
5
5
  # Custom conversion class
6
6
  # See https://docs.openc3.com/docs/configuration/conversions
@@ -20,4 +20,8 @@ class <%= conversion_class %>(Conversion):
20
20
  # Used when conversion is applied to a regular (not DERIVED) item
21
21
  # NOTE: You can also use packet.read("ITEM") to get additional values
22
22
  # return value / 2 * packet.read("OTHER_ITEM")
23
+ #
24
+ # In a READ_CONVERSION, read the latest value from a different packet in the same target
25
+ # other = System.telemetry.packet(packet.target_name, "OTHER_PACKET")
26
+ # return value * other.read("OTHER_ITEM")
23
27
  return value
@@ -20,6 +20,11 @@ module OpenC3
20
20
  # Used when conversion is applied to a regular (not DERIVED) item
21
21
  # NOTE: You can also use packet.read("ITEM") to get additional values
22
22
  # return value / 2 * packet.read("OTHER_ITEM")
23
+ #
24
+ # In a READ_CONVERSION, read the latest value from a different packet in the same target
25
+ # other = System.telemetry.packet(packet.target_name, "OTHER_PACKET")
26
+ # return value * other.read("OTHER_ITEM")
27
+ return value
23
28
  end
24
29
  end
25
30
  end
@@ -0,0 +1,62 @@
1
+ # Builds this plugin and installs it into a real COSMOS with Playwright.
2
+ #
3
+ # Runs the most recent COSMOS Core release in Docker, builds the plugin gem, and
4
+ # drives the Admin tool the way an operator would: Install From File, submit the
5
+ # variables dialog, and wait for the install to report Complete. That catches
6
+ # what unit tests can't - a plugin.txt that doesn't parse, a target that doesn't
7
+ # build, a microservice that won't start.
8
+ #
9
+ # Nothing here needs configuring as the plugin grows. Tool pages are discovered
10
+ # from the COSMOS API after install and checked for browser console errors, and
11
+ # a frontend is built with pnpm whenever the plugin has a package.json, so
12
+ # `cli generate tool` and `cli generate widget` are covered with no edit here.
13
+ #
14
+ # Runs on every commit and once a week. The weekly run is what catches a new
15
+ # COSMOS release breaking this plugin. Note that GitHub disables scheduled
16
+ # workflows in a repo with no activity for 60 days.
17
+
18
+ name: Playwright
19
+
20
+ on:
21
+ push:
22
+ branches: [main]
23
+ pull_request:
24
+ branches: ["**"]
25
+ # Off the hour because scheduled runs at :00 get queued behind everyone else's
26
+ schedule:
27
+ - cron: '27 7 * * 1'
28
+ workflow_dispatch:
29
+ inputs:
30
+ cosmos_version:
31
+ description: 'COSMOS version to run, or latest'
32
+ required: false
33
+ type: string
34
+ default: 'latest'
35
+
36
+ permissions:
37
+ contents: read
38
+
39
+ concurrency:
40
+ group: ${{ github.workflow }}-${{ github.ref }}
41
+ # Superseding a pull request run is fine, but a scheduled run and a push to
42
+ # main share a ref, so cancelling on those would have them kill each other
43
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
44
+
45
+ jobs:
46
+ playwright:
47
+ uses: OpenC3/.github/.github/workflows/plugin-playwright-reusable.yml@main
48
+ with:
49
+ plugin_directory: .
50
+ cosmos_version: ${{ inputs.cosmos_version || 'latest' }}
51
+ # Once you have added targets with `cli generate target`, list them here
52
+ # and the install is checked for them:
53
+ # expected_targets: MY_TARGET ANOTHER_TARGET
54
+ #
55
+ # install_demo: true # Uncomment if this plugin references INST/INST2
56
+ # is_tool: true # Uncomment to require that this plugin registers a tool
57
+ #
58
+ # Tool pages are checked for browser console errors automatically. Add
59
+ # regexes here for errors to allow:
60
+ # console_ignore: |
61
+ # some third party gripe
62
+ # another known message
@@ -0,0 +1,45 @@
1
+ # Builds the gem, tags the commit, and creates a GitHub release. Run it by hand
2
+ # from the Actions tab and give it a version number.
3
+ #
4
+ # Both publish steps are off by default so a first release works with no setup
5
+ # at all. Tick the box in the run dialog when you are ready to publish, after
6
+ # adding the matching secret to the repo:
7
+ #
8
+ # Deploy to OpenC3 App Store -> OPENC3_API_TOKEN (your store account token)
9
+ # Publish the gem to RubyGems -> RUBYGEMS_API_KEY (your RubyGems API key)
10
+ #
11
+ # A tool or widget frontend needs nothing set here: once the plugin has a
12
+ # package.json it is built with pnpm before the gem is packaged.
13
+
14
+ name: Release
15
+
16
+ on:
17
+ workflow_dispatch:
18
+ inputs:
19
+ version:
20
+ description: 'Version number'
21
+ required: true
22
+ type: string
23
+ deploy_to_store:
24
+ description: 'Deploy to OpenC3 App Store'
25
+ required: false
26
+ type: boolean
27
+ default: false
28
+ deploy_to_rubygems:
29
+ description: 'Publish the gem to RubyGems'
30
+ required: false
31
+ type: boolean
32
+ default: false
33
+
34
+ jobs:
35
+ release:
36
+ uses: OpenC3/.github/.github/workflows/release-cosmos-plugin-reusable.yml@main
37
+ with:
38
+ version: ${{ inputs.version }}
39
+ deploy_to_store: ${{ inputs.deploy_to_store }}
40
+ deploy_to_rubygems: ${{ inputs.deploy_to_rubygems }}
41
+ plugin_directory: .
42
+ # is_tool: true # Uncomment to fail the release if package.json is missing
43
+ secrets:
44
+ OPENC3_API_TOKEN: ${{ secrets.OPENC3_API_TOKEN }}
45
+ RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
@@ -0,0 +1,35 @@
1
+ # Runs this plugin's unit tests on every push and pull request.
2
+ #
3
+ # Python tests are discovered in tests/ or test/, Ruby specs in spec/ or specs/.
4
+ # Whichever this plugin doesn't have is skipped, so there is nothing to set up:
5
+ # add a test file and it starts running. A plugin with no tests at all passes
6
+ # with a warning until you set require_tests below.
7
+ #
8
+ # Dependencies are picked up automatically - requirements.txt for the code under
9
+ # test, <test dir>/requirements.txt for test only ones, and a Gemfile for Ruby
10
+ # when there is one.
11
+
12
+ name: Unit Tests
13
+
14
+ on:
15
+ push:
16
+ branches: [main]
17
+ pull_request:
18
+ branches: ["**"]
19
+
20
+ permissions:
21
+ contents: read
22
+
23
+ concurrency:
24
+ group: ${{ github.workflow }}-${{ github.ref }}
25
+ cancel-in-progress: true
26
+
27
+ jobs:
28
+ unit-tests:
29
+ uses: OpenC3/.github/.github/workflows/plugin-unit-tests-reusable.yml@main
30
+ with:
31
+ plugin_directory: .
32
+ # python_version: '3.12' # Uncomment to pin a different Python
33
+ # ruby_version: '3.4' # Uncomment to pin a different Ruby
34
+ # require_tests: true # Uncomment to fail the build when there are no tests
35
+ # gemfile: Gemfile.dev # Uncomment if the specs need a different Gemfile than the plugin's own
@@ -1 +1,7 @@
1
1
  node_modules
2
+ <% if @@language == 'py' -%>
3
+ .venv/
4
+ __pycache__/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ <% end -%>
@@ -8,6 +8,96 @@ Update this comment with your own description.
8
8
 
9
9
  1. Edit the .gemspec file fields: name, summary, description, authors, email, and homepage
10
10
  1. Update the LICENSE.md file with your company name
11
+ <% if @@language == 'py' -%>
12
+ 1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) to manage the plugin's Python dependencies
13
+
14
+ ## Python dependencies with uv
15
+
16
+ The plugin's Python dependencies are declared in `pyproject.toml` and locked in `uv.lock`.
17
+ Both files are packaged into the gem automatically, and COSMOS reads them when the plugin is installed.
18
+
19
+ ### Adding dependencies
20
+
21
+ ```sh
22
+ uv add requests # runtime dependency, installed into COSMOS with the plugin
23
+ uv add --group dev pytest-mock # development only, never installed into COSMOS
24
+ ```
25
+
26
+ `uv add` updates both `pyproject.toml` and `uv.lock`. Commit both files.
27
+
28
+ `uv lock` resolves `pyproject.toml` and writes `uv.lock` without installing anything. `uv sync` does the
29
+ same when the lock is stale, then installs into `.venv`. Either works after editing `pyproject.toml` by hand;
30
+ commit the updated `uv.lock`.
31
+
32
+ COSMOS installs a locked plugin with `uv sync --frozen`, which installs exactly what `uv.lock` records and never
33
+ relocks, so a stale lock ships stale dependencies. `uv lock --check` fails if the lock is out of date.
34
+
35
+ ### How COSMOS installs them
36
+
37
+ - **With `uv.lock`** (recommended): COSMOS runs `uv sync --frozen --no-dev`. Every install gets the same
38
+ versions, downloaded from the URLs recorded in the lock.
39
+ - **Without `uv.lock`**: COSMOS resolves the dependencies at install time against the PyPI URL set in
40
+ Admin Console -> Settings, so versions can change from one install to the next.
41
+
42
+ The `dev` dependency group is never installed into COSMOS.
43
+
44
+ ### Developing locally
45
+
46
+ ```sh
47
+ uv sync --group dev # create .venv with runtime and dev dependencies
48
+ uv run --group dev pytest # run tests; lib/ is on the import path
49
+ uv run --group dev ruff check # lint
50
+ uv run --group dev ruff format
51
+ uv run --group dev ty check # type check
52
+ ```
53
+
54
+ A plain `uv sync` installs only the runtime dependencies, matching what COSMOS installs.
55
+
56
+ The plugin itself is not installed into `.venv`: COSMOS puts `lib/` on the Python path instead, and pytest and ty
57
+ are configured to do the same. Anything else needs `lib/` on the path to import `<%= package_name %>`:
58
+
59
+ ```
60
+ PYTHONPATH=lib uv run python my_script.py
61
+ ```
62
+
63
+ `cli generate` writes a `.python-version` file pinning the Python version of the COSMOS image it ran in, so
64
+ uv develops against the same Python COSMOS runs. If you upgrade to a COSMOS release with a newer Python, update
65
+ it with `uv python pin <version>`. Without that file uv picks any installed Python that satisfies
66
+ `requires-python`.
67
+
68
+ The `openc3` dev dependency provides the COSMOS Python API for your editor, tests and `ty`. Pin it to the
69
+ COSMOS version you deploy to so they see the same API, e.g. `uv add --group dev "openc3==X.Y.Z"`.
70
+
71
+ ### Where to put Python code
72
+
73
+ Put Python code shared across the plugin in `lib/<%= package_name %>/`, never directly in `lib/`.
74
+
75
+ COSMOS adds the `lib/` directory of every installed plugin to the Python path. If two plugins both ship
76
+ `lib/helpers.py`, `import helpers` loads whichever one Python finds first, and the other can't be imported
77
+ at all. A module directly in `lib/` can also hide an installed package of the same name, such as `requests`.
78
+ The `<%= package_name %>` package is named after this plugin, so its modules can't collide.
79
+
80
+ Import from the package:
81
+
82
+ ```python
83
+ from <%= package_name %>.helpers import Helper
84
+ ```
85
+
86
+ Reference its files by path in plugin configuration, e.g. `INTERFACE MY_INT <%= package_name %>/my_interface.py`.
87
+
88
+ ### Updating dependencies
89
+
90
+ ```
91
+ uv lock --upgrade-package requests # upgrade one package
92
+ uv lock --upgrade # upgrade everything
93
+ ```
94
+
95
+ ### Private package indexes
96
+
97
+ See the comments in the `[tool.uv]` section of `pyproject.toml`. If the COSMOS PyPI URL setting points at
98
+ anything other than public PyPI, COSMOS ignores the plugin's own index settings when it resolves, so a
99
+ package published only to your private index must also be served by that index, or be locked in `uv.lock`.
100
+ <% end -%>
11
101
 
12
102
  ## Building non-tool / widget plugins
13
103
 
@@ -26,19 +116,41 @@ If you don’t have a local node environment, you can use our openc3-node contai
26
116
 
27
117
  Mac / Linux:
28
118
 
29
- ```
119
+ ```sh
30
120
  docker run -it -v `pwd`:/openc3/local:z -w /openc3/local docker.io/openc3inc/openc3-node sh
31
121
  ```
32
122
 
33
123
  Windows:
34
124
 
35
- ```
125
+ ```sh
36
126
  docker run -it -v %cd%:/openc3/local -w /openc3/local docker.io/openc3inc/openc3-node sh
37
127
  ```
38
128
 
39
129
  1. pnpm install --frozen-lockfile --ignore-scripts
40
130
  1. rake build VERSION=1.0.0
41
131
 
132
+ ## Continuous integration
133
+
134
+ `.github/workflows/` ships three GitHub Actions workflows that work as soon as
135
+ you push this plugin to GitHub. They call shared workflows from `OpenC3/.github`,
136
+ so the steps stay current without you updating anything here.
137
+
138
+ - **Unit Tests** - on every push and pull request. Runs Python tests in `tests/`
139
+ or `test/` and Ruby specs in `spec/` or `specs/`. Whichever you don't have is
140
+ skipped, so just add a test file.
141
+ - **Playwright** - on every push and pull request, plus weekly. Builds the gem,
142
+ starts the latest COSMOS release in Docker, and installs the plugin through the
143
+ Admin tool, which catches a `plugin.txt` that doesn't parse, a target that
144
+ doesn't build, or a microservice that won't start. The weekly run is what tells
145
+ you a new COSMOS release broke this plugin. Once you add targets, list them in
146
+ `expected_targets` so the install is verified against them.
147
+ - **Release** - manual, from the Actions tab. Builds the gem, tags the commit and
148
+ creates a GitHub release. Publishing to the OpenC3 App Store and to RubyGems is
149
+ off until you add the matching secret and tick the box.
150
+
151
+ Adding a tool or a widget needs no change to any of these. All three build a
152
+ frontend with pnpm as soon as the plugin has a `package.json`.
153
+
42
154
  ## Installing into OpenC3 COSMOS
43
155
 
44
156
  1. Go to the OpenC3 Admin Tool, Plugins Tab
@@ -0,0 +1,4 @@
1
+ # Python code shared across this plugin lives in this package. COSMOS puts
2
+ # every installed plugin's lib/ on sys.path, so a module placed directly in
3
+ # lib/ can collide with another plugin's module of the same name. Keeping it
4
+ # under this uniquely named package avoids that. See README.md.
@@ -20,7 +20,16 @@ Gem::Specification.new do |s|
20
20
  time = Time.now.strftime("%Y%m%d%H%M%S")
21
21
  s.version = '0.0.0' + ".#{time}"
22
22
  end
23
- s.files = Dir.glob("{targets,lib,public,tools,microservices}/**/*") + %w(Rakefile README.md LICENSE.md plugin.txt)
23
+ <% if @@language == 'py' -%>
24
+ # pyproject.toml and uv.lock must be in the gem for COSMOS to install the
25
+ # plugin's python dependencies: install only sees files the gem contains.
26
+ # Globbed rather than listed so the gem still builds before `uv lock` is run.
27
+ <% end -%>
28
+ s.files = Dir.glob("{targets,lib,public,tools,microservices}/**/*") + %w(Rakefile README.md LICENSE.md plugin.txt)<% if @@language == 'py' %> + Dir.glob("{pyproject.toml,uv.lock}")<% end %>
29
+ <% if @@language == 'py' -%>
30
+ # Running tests or scripts locally writes bytecode next to the source; keep it out of the gem.
31
+ s.files = s.files.reject { |file| file.include?('__pycache__') }
32
+ <% end -%>
24
33
 
25
34
  s.metadata = {
26
35
  # These fields are used when you submit your plugin to the OpenC3 Store at store.openc3.com
@@ -0,0 +1,119 @@
1
+ [project]
2
+ name = "<%= plugin_name %>"
3
+ version = "0.0.0"
4
+ description = "OpenC3 <%= plugin_name %> plugin Python dependencies"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ # Add your plugin's Python dependencies here, then run `uv lock` and commit the
8
+ # resulting uv.lock so COSMOS installs the same versions every time.
9
+ dependencies = []
10
+
11
+ [dependency-groups]
12
+ # Development and test only. COSMOS installs plugin dependencies with --no-dev,
13
+ # so nothing here reaches a deployed plugin. Left unpinned on purpose: a bound
14
+ # written into this template would still be here whenever you generated this
15
+ # plugin, holding you on stale tooling. Commit the uv.lock for reproducible
16
+ # versions, and add a pin here only if you need a specific one.
17
+ dev = [
18
+ "openc3",
19
+ "pytest",
20
+ "ruff",
21
+ "ty",
22
+ ]
23
+
24
+ [tool.uv]
25
+ # This file declares dependencies only — it is not a buildable package. COSMOS
26
+ # loads plugin code from lib/ at runtime and installs with `uv sync --frozen`,
27
+ # so nothing here is ever built and no [build-system] is needed.
28
+ package = false
29
+
30
+ # Keep the dev group out of a plain `uv sync` so a local install matches what
31
+ # COSMOS installs (it passes --no-dev). Use `uv sync --group dev` while
32
+ # developing, or `uv run --group dev pytest`.
33
+ default-groups = []
34
+
35
+ # Uncomment to install dependencies from a private PyPI repository.
36
+ # See: https://docs.astral.sh/uv/configuration/indexes/
37
+ #
38
+ # These settings are used whenever uv resolves: when you run `uv lock` yourself,
39
+ # and at install time when no uv.lock is committed alongside this file.
40
+ #
41
+ # They do not always survive installation into COSMOS. When the PyPI URL in
42
+ # Admin Console -> Settings names anything other than public PyPI, the operator
43
+ # has designated an index and COSMOS makes it authoritative: the install passes
44
+ # uv `--no-config --no-sources`, so everything below is ignored and every
45
+ # package is resolved from the operator's index. A dependency published only to
46
+ # your private index then fails to install there, rather than being fetched
47
+ # from it — coordinate with the operator so their index serves it too.
48
+ #
49
+ # A committed uv.lock sidesteps this entirely: COSMOS installs with
50
+ # `uv sync --frozen`, which fetches the exact registry and wheel URLs recorded
51
+ # in the lock and consults no index at all.
52
+ #
53
+ # Indexes are searched in the order listed, before the default index. Mark one
54
+ # `default = true` to replace public PyPI entirely, or list your private repo
55
+ # first and leave PyPI as the default to fall back to it.
56
+ #
57
+ # index = [
58
+ # { name = "private", url = "https://private-pypi.example.com/simple" },
59
+ # { name = "pypi", url = "https://pypi.org/simple", default = true },
60
+ # ]
61
+ #
62
+ # Pin internal packages to a specific index. A pin keeps a same-named package on
63
+ # public PyPI from being substituted. Add `explicit = true` to an index to keep
64
+ # it from serving anything other than packages pinned to it.
65
+ #
66
+ # sources = { my-internal-pkg = { index = "private" } }
67
+ #
68
+ # Uncomment for self-signed certificates.
69
+ #
70
+ # allow-insecure-host = ["private-pypi.example.com"]
71
+
72
+ [tool.ty.environment]
73
+ # COSMOS puts the plugin's lib/ on sys.path at runtime rather than installing it,
74
+ # so ty needs it here to resolve imports between the plugin's own modules.
75
+ extra-paths = ["lib"]
76
+
77
+ [tool.pytest.ini_options]
78
+ # Same reason as ty's extra-paths: lib/ is on sys.path at runtime, not installed,
79
+ # so tests need it on the path to import the plugin's own modules.
80
+ pythonpath = ["lib"]
81
+
82
+ [tool.ty.rules]
83
+ # These are artifacts of how COSMOS ships its Python API, not mistakes in your
84
+ # plugin, so they are off rather than "warn": ty exits non-zero on a warning, so
85
+ # "warn" would fail the check just as an error does. Delete a line to opt back
86
+ # in, or silence a single case with `# ty: ignore[rule-name]`.
87
+ #
88
+ # openc3.script re-exports its API through star imports (from .telemetry import *,
89
+ # etc.) with no __all__, so ty cannot see tlm, cmd, send_raw and friends even
90
+ # though they resolve at runtime. unresolved-reference covers using such a name,
91
+ # unresolved-import covers importing one by name. Ruff's F405 flags the same
92
+ # thing if you want it reported.
93
+ unresolved-reference = "ignore"
94
+ unresolved-import = "ignore"
95
+ # Script Runner replaces openc3.script.start() at runtime with its own
96
+ # implementation, which accepts bind_variables. The pip package only ships the
97
+ # stub signature start(procedure_name).
98
+ unknown-argument = "ignore"
99
+
100
+ [tool.ruff]
101
+ line-length = 120
102
+ # target-version is intentionally absent: ruff infers it from the project's
103
+ # requires-python above, so there is one place to bump the minimum. ty does the
104
+ # same, which is why [tool.ty.environment] sets no python-version either.
105
+
106
+ [tool.ruff.lint]
107
+ select = ["E", "F", "I", "N", "UP", "B", "W", "C4", "SIM"]
108
+ ignore = [
109
+ "E402", # Module level import not at top of file
110
+ "E501", # Line too long (handled by the formatter)
111
+ "F402", # Import shadowed by loop var
112
+ "F403", # Star imports used - the documented way to import the COSMOS API
113
+ "F405", # Name may be undefined due to star import
114
+ "N815", # Mixed case variable in class scope
115
+ ]
116
+
117
+ [tool.ruff.lint.isort]
118
+ known-first-party = ["openc3"]
119
+ lines-after-imports = 2
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "scripts": {
5
5
  "ng": "ng",
6
6
  "start": "ng serve",
@@ -23,7 +23,7 @@
23
23
  "@angular/platform-browser-dynamic": "^18.2.6",
24
24
  "@angular/router": "^18.2.6",
25
25
  "@astrouxds/astro-web-components": "^7.24.0",
26
- "@openc3/js-common": "7.4.0",
26
+ "@openc3/js-common": "7.5.0",
27
27
  "rxjs": "~7.8.0",
28
28
  "single-spa": "^5.9.5",
29
29
  "single-spa-angular": "^9.2.0",
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 OpenC3, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # This program is distributed in the hope that it will be useful,
5
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
6
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
+ # See LICENSE.md for more details.
8
+ #
9
+ # This file may also be used under the terms of a commercial license
10
+ # if purchased from OpenC3, Inc.
11
+
12
+ minimumReleaseAge: 1440 # 1 day
13
+ minimumReleaseAgeExclude:
14
+ # we control these packages, so we don't need to wait to consume them
15
+ - '@openc3/js-common'
16
+ - '@openc3/vue-common'
@@ -16,7 +16,7 @@
16
16
  "@emotion/react": "^11.13.3",
17
17
  "@emotion/styled": "^11.11.0",
18
18
  "@mui/material": "^6.1.1",
19
- "@openc3/js-common": "7.4.0",
19
+ "@openc3/js-common": "7.5.0",
20
20
  "react": "^18.2.0",
21
21
  "react-dom": "^18.2.0",
22
22
  "single-spa-react": "^5.1.4"
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 OpenC3, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # This program is distributed in the hope that it will be useful,
5
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
6
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
+ # See LICENSE.md for more details.
8
+ #
9
+ # This file may also be used under the terms of a commercial license
10
+ # if purchased from OpenC3, Inc.
11
+
12
+ minimumReleaseAge: 1440 # 1 day
13
+ minimumReleaseAgeExclude:
14
+ # we control these packages, so we don't need to wait to consume them
15
+ - '@openc3/js-common'
16
+ - '@openc3/vue-common'
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@astrouxds/astro-web-components": "^7.24.0",
15
- "@openc3/js-common": "7.4.0",
15
+ "@openc3/js-common": "7.5.0",
16
16
  "@smui/button": "^7.0.0",
17
17
  "@smui/common": "^7.0.0",
18
18
  "@smui/card": "^7.0.0",
@@ -26,6 +26,7 @@
26
26
  "devDependencies": {
27
27
  "@babel/core": "^7.25.2",
28
28
  "@babel/preset-env": "^7.25.4",
29
+ "@material/theme": "^14.0.0",
29
30
  "@rollup/plugin-commonjs": "^28.0.0",
30
31
  "@rollup/plugin-node-resolve": "^15.3.0",
31
32
  "@testing-library/jest-dom": "^6.5.0",
@@ -0,0 +1,20 @@
1
+ # Copyright 2026 OpenC3, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # This program is distributed in the hope that it will be useful,
5
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
6
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
+ # See LICENSE.md for more details.
8
+ #
9
+ # This file may also be used under the terms of a commercial license
10
+ # if purchased from OpenC3, Inc.
11
+
12
+ # smui-theme builds its sass load path from require.resolve('@material/dom'),
13
+ # which only finds the sibling @material/* packages in a flat node_modules.
14
+ nodeLinker: hoisted
15
+
16
+ minimumReleaseAge: 1440 # 1 day
17
+ minimumReleaseAgeExclude:
18
+ # we control these packages, so we don't need to wait to consume them
19
+ - '@openc3/js-common'
20
+ - '@openc3/vue-common'
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -11,8 +11,8 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@astrouxds/astro-web-components": "^7.24.0",
14
- "@openc3/js-common": "7.4.0",
15
- "@openc3/vue-common": "7.4.0",
14
+ "@openc3/js-common": "7.5.0",
15
+ "@openc3/vue-common": "7.5.0",
16
16
  "axios": "^1.7.7",
17
17
  "date-fns": "^4.1.0",
18
18
  "lodash": "^4.17.21",
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 OpenC3, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # This program is distributed in the hope that it will be useful,
5
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
6
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
+ # See LICENSE.md for more details.
8
+ #
9
+ # This file may also be used under the terms of a commercial license
10
+ # if purchased from OpenC3, Inc.
11
+
12
+ minimumReleaseAge: 1440 # 1 day
13
+ minimumReleaseAgeExclude:
14
+ # we control these packages, so we don't need to wait to consume them
15
+ - '@openc3/js-common'
16
+ - '@openc3/vue-common'
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= widget_name %>",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@astrouxds/astro-web-components": "^7.24.0",
11
- "@openc3/vue-common": "7.4.0",
11
+ "@openc3/vue-common": "7.5.0",
12
12
  "vuetify": "^3.7.1"
13
13
  },
14
14
  "devDependencies": {
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 OpenC3, Inc.
2
+ # All Rights Reserved.
3
+ #
4
+ # This program is distributed in the hope that it will be useful,
5
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
6
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
+ # See LICENSE.md for more details.
8
+ #
9
+ # This file may also be used under the terms of a commercial license
10
+ # if purchased from OpenC3, Inc.
11
+
12
+ minimumReleaseAge: 1440 # 1 day
13
+ minimumReleaseAgeExclude:
14
+ # we control these packages, so we don't need to wait to consume them
15
+ - '@openc3/js-common'
16
+ - '@openc3/vue-common'