stock-analysis-plugin 0.2.2__tar.gz → 0.2.5__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.
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.github/workflows/autofix.yml +2 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.github/workflows/ci.yml +87 -32
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.github/workflows/publish.yml +19 -6
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/AGENTS.md +6 -6
- stock_analysis_plugin-0.2.5/LICENSE +21 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/PKG-INFO +84 -17
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/README.md +79 -15
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/docs/hermes-integration.en.md +3 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/docs/hermes-integration.md +4 -4
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/docs/openclaw-integration.md +4 -4
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/docs/pi-integration.en.md +3 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/docs/pi-integration.md +3 -3
- stock_analysis_plugin-0.2.5/docs/research/issue-44-coverage-sources.md +122 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/dsh/README.md +2 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/dsh/index.ts +223 -16
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/dsh/package.json +3 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/hermes/plugin.yaml +16 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/hermes/schemas.py +157 -6
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/hermes/tools.py +93 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/openclaw/README.md +2 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/openclaw/index.ts +184 -26
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/openclaw/openclaw.plugin.json +10 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/openclaw/package.json +1 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/package-lock.json +261 -143
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/package.json +5 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/pi/index.ts +265 -11
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/pyproject.toml +4 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/requirements-dev.txt +1 -1
- stock_analysis_plugin-0.2.5/ruff.toml +8 -0
- stock_analysis_plugin-0.2.5/scripts/ci-resolve-llm-host.mjs +29 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/scripts/setup-python.mjs +7 -9
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/event-driven/SKILL.md +6 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/growth-quality/SKILL.md +6 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/hot-theme/SKILL.md +3 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/SKILL.md +22 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/stock-screener/SKILL.md +19 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/strategy-backtest/SKILL.md +11 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/bottom_volume.yaml +5 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/box_oscillation.yaml +5 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/bull_trend.yaml +11 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/dragon_head.yaml +4 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/emotion_cycle.yaml +5 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/ma_crossover.yaml +10 -3
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/rsi_oversold.yaml +5 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/shrink_pullback.yaml +7 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/strategies/examples/volume_breakout.yaml +7 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/conftest.py +25 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/host_smoke.mjs +52 -55
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_hermes_llm.py +12 -13
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_openclaw_e2e.ts +5 -2
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_pi_llm.ts +8 -9
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_provider_network.py +12 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_alert_rules.py +43 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_anomaly_detect.py +25 -0
- stock_analysis_plugin-0.2.5/tests/test_backtest.py +727 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_backtest_advanced.py +15 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_capabilities.py +1 -1
- stock_analysis_plugin-0.2.5/tests/test_data_cache.py +47 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_diagnostics.py +25 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_dsh_integration.ts +86 -5
- stock_analysis_plugin-0.2.5/tests/test_dsh_sdk_compat.ts +22 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_gather.py +75 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_hermes_integration.py +79 -0
- stock_analysis_plugin-0.2.5/tests/test_kline_adjustment.py +194 -0
- stock_analysis_plugin-0.2.5/tests/test_market_regime.py +148 -0
- stock_analysis_plugin-0.2.5/tests/test_market_review.py +229 -0
- stock_analysis_plugin-0.2.5/tests/test_name_resolver.py +135 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_openclaw_integration.ts +110 -14
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_pi_integration.ts +49 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_report_renderer.py +66 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_risk_screening.py +32 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_screener.py +161 -0
- stock_analysis_plugin-0.2.5/tests/test_setup_python.mjs +21 -0
- stock_analysis_plugin-0.2.5/tests/test_stock_data.py +307 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_stock_data_failover.py +498 -68
- stock_analysis_plugin-0.2.5/tests/test_stock_data_margin.py +375 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_stock_data_short_term.py +14 -30
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_technical.py +166 -0
- stock_analysis_plugin-0.2.5/tests/test_trading_calendar.py +300 -0
- stock_analysis_plugin-0.2.5/tests/test_value_data.py +974 -0
- stock_analysis_plugin-0.2.5/tests/test_volume_analysis.py +147 -0
- stock_analysis_plugin-0.2.5/tools/_cache.py +61 -0
- stock_analysis_plugin-0.2.5/tools/_subproc.py +95 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/alert_rules.py +19 -9
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/anomaly_detect.py +24 -35
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/backtest.py +180 -100
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/capabilities.py +13 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/diagnostics.py +12 -6
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/gather.py +13 -9
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/import_parser.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/market_regime.py +27 -35
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/market_review.py +56 -9
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/name_resolver.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/pattern.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/position_context.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/report_renderer.py +10 -6
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/requirements.txt +2 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/risk_screening.py +29 -23
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/screener.py +80 -18
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/search_intel.py +5 -13
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/signal_tracker.py +2 -6
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/stock_data.py +520 -169
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/technical.py +136 -40
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/trading_calendar.py +78 -18
- stock_analysis_plugin-0.2.5/tools/value_data.py +1368 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/volume_analysis.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/watchlist.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/watchlist_context.py +2 -5
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tsconfig.json +8 -1
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/typings/openclaw/index.d.ts +1 -0
- stock_analysis_plugin-0.2.2/ruff.toml +0 -6
- stock_analysis_plugin-0.2.2/tests/test_backtest.py +0 -211
- stock_analysis_plugin-0.2.2/tests/test_market_regime.py +0 -90
- stock_analysis_plugin-0.2.2/tests/test_market_review.py +0 -115
- stock_analysis_plugin-0.2.2/tests/test_stock_data.py +0 -95
- stock_analysis_plugin-0.2.2/tests/test_trading_calendar.py +0 -161
- stock_analysis_plugin-0.2.2/tools/_subproc.py +0 -46
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.github/release.yml +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.gitignore +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/.npmignore +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/CLAUDE.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/dsh/cordis.patch.yml +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/hermes/__init__.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/openclaw/.npmignore +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/schemas/market_review_schema.json +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/schemas/report_schema.json +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/scripts/sync-version.sh +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/scripts/venv-python.mjs +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/bottom-volume/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/bottom-volume/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/box-oscillation/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/box-oscillation/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/bull-trend/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/bull-trend/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/chan-theory/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/chan-theory/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/dragon-head/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/dragon-head/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/emotion-cycle/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/emotion-cycle/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/event-driven/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/expectation-repricing/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/expectation-repricing/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/growth-quality/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/hot-theme/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/ma-crossover/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/ma-crossover/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/market-review/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/market-review/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/one-yang-three-yin/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/one-yang-three-yin/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/shrink-pullback/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/shrink-pullback/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/references/short-term-trading.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/stock-analysis/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/stock-screener/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/strategy-backtest/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/volume-breakout/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/volume-breakout/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/wave-theory/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/wave-theory/scripts/gather.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/skills/wisburg-research/SKILL.md +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/templates/_macros.j2 +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/templates/market_review/full.md.j2 +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/templates/stock_analysis/brief.md.j2 +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/templates/stock_analysis/full.md.j2 +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/__init__.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/_stubs/dsh-tools.ts +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/_stubs/openclaw-sdk.ts +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/_stubs/typebox.ts +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/dsh_tool_spy.mjs +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_dsh_e2e.ts +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_host_to_python.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/e2e/test_pi_e2e.ts +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_import_parser.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_pattern.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_position_context.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_search_intel.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_sentiment.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_signal_tracker.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_skill_workflows.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_subproc.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_watchlist.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tests/test_watchlist_context.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/tools/__init__.py +0 -0
- {stock_analysis_plugin-0.2.2 → stock_analysis_plugin-0.2.5}/typings/pi-agent/index.d.ts +0 -0
|
@@ -18,7 +18,8 @@ jobs:
|
|
|
18
18
|
cache: pip
|
|
19
19
|
|
|
20
20
|
- name: Install ruff
|
|
21
|
-
|
|
21
|
+
# Pinned — must match ci.yml and requirements-dev.txt.
|
|
22
|
+
run: pip install "ruff==0.15.20"
|
|
22
23
|
|
|
23
24
|
- name: Ruff auto-fix (lint)
|
|
24
25
|
run: ruff check --fix tools/ skills/ tests/ hermes/
|
|
@@ -7,9 +7,15 @@ on:
|
|
|
7
7
|
branches: [main]
|
|
8
8
|
workflow_call:
|
|
9
9
|
|
|
10
|
+
# One active run per branch/PR — new pushes cancel stale runs.
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
10
15
|
jobs:
|
|
11
16
|
lint:
|
|
12
17
|
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 10
|
|
13
19
|
steps:
|
|
14
20
|
- uses: actions/checkout@v4
|
|
15
21
|
|
|
@@ -18,7 +24,8 @@ jobs:
|
|
|
18
24
|
python-version: "3.11"
|
|
19
25
|
|
|
20
26
|
- name: Install Python lint tools
|
|
21
|
-
|
|
27
|
+
# Pinned — must match requirements-dev.txt and autofix.yml.
|
|
28
|
+
run: pip install ruff==0.15.20
|
|
22
29
|
|
|
23
30
|
- name: Ruff check
|
|
24
31
|
run: ruff check tools/ skills/ tests/ hermes/
|
|
@@ -29,21 +36,30 @@ jobs:
|
|
|
29
36
|
- uses: actions/setup-node@v4
|
|
30
37
|
with:
|
|
31
38
|
node-version: "20"
|
|
39
|
+
cache: "npm"
|
|
32
40
|
|
|
41
|
+
# --ignore-scripts: tsc doesn't need the postinstall-built Python venv.
|
|
33
42
|
- name: Install Node dependencies
|
|
34
|
-
run: npm
|
|
43
|
+
run: npm ci --ignore-scripts
|
|
35
44
|
|
|
36
45
|
- name: TypeScript type check
|
|
37
46
|
run: npx tsc --noEmit
|
|
38
47
|
|
|
39
48
|
test:
|
|
40
49
|
runs-on: ubuntu-latest
|
|
50
|
+
timeout-minutes: 15
|
|
51
|
+
strategy:
|
|
52
|
+
fail-fast: false
|
|
53
|
+
matrix:
|
|
54
|
+
# 3.10 leg guards the declared floor — verified: full dep set installs
|
|
55
|
+
# and the suite passes on cpython 3.10.19.
|
|
56
|
+
python-version: ["3.11", "3.10"]
|
|
41
57
|
steps:
|
|
42
58
|
- uses: actions/checkout@v4
|
|
43
59
|
|
|
44
60
|
- uses: actions/setup-python@v5
|
|
45
61
|
with:
|
|
46
|
-
python-version:
|
|
62
|
+
python-version: ${{ matrix.python-version }}
|
|
47
63
|
cache: pip
|
|
48
64
|
|
|
49
65
|
- name: Install dependencies
|
|
@@ -57,7 +73,11 @@ jobs:
|
|
|
57
73
|
network:
|
|
58
74
|
# Real provider calls (akshare/yfinance) — flaky upstreams by nature, so
|
|
59
75
|
# gated to same-repo PRs and pushes (forks skip it, like e2e-llm).
|
|
76
|
+
# continue-on-error: see publish.yml — a flaky upstream must not block the
|
|
77
|
+
# release path; failures still surface as annotations on the run.
|
|
78
|
+
continue-on-error: true
|
|
60
79
|
runs-on: ubuntu-latest
|
|
80
|
+
timeout-minutes: 20
|
|
61
81
|
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
|
62
82
|
steps:
|
|
63
83
|
- uses: actions/checkout@v4
|
|
@@ -82,6 +102,7 @@ jobs:
|
|
|
82
102
|
# structurally cannot see. Deterministic by design: no LLM, no secrets, and
|
|
83
103
|
# the 4 round-trip tools are the non-network set (see tests/e2e/*.ts).
|
|
84
104
|
runs-on: ${{ matrix.os }}
|
|
105
|
+
timeout-minutes: 15
|
|
85
106
|
strategy:
|
|
86
107
|
fail-fast: false
|
|
87
108
|
matrix:
|
|
@@ -96,16 +117,20 @@ jobs:
|
|
|
96
117
|
- uses: actions/setup-node@v4
|
|
97
118
|
with:
|
|
98
119
|
node-version: "20"
|
|
120
|
+
cache: "npm"
|
|
121
|
+
|
|
122
|
+
- name: Python setup failure check
|
|
123
|
+
run: node tests/test_setup_python.mjs
|
|
99
124
|
|
|
100
125
|
# tests/conftest.py imports numpy/pandas at module load, so any pytest run
|
|
101
|
-
# needs the tools' runtime deps in system python. npm
|
|
126
|
+
# needs the tools' runtime deps in system python. npm ci's postinstall
|
|
102
127
|
# separately builds .venv (full requirements) — that's the python the
|
|
103
128
|
# host↔python round-trips spawn.
|
|
104
129
|
- name: Install dependencies
|
|
105
130
|
run: |
|
|
106
131
|
pip install -r tools/requirements.txt
|
|
107
132
|
pip install -r requirements-dev.txt
|
|
108
|
-
npm
|
|
133
|
+
npm ci
|
|
109
134
|
|
|
110
135
|
- name: TypeScript type check
|
|
111
136
|
run: npx tsc --noEmit
|
|
@@ -119,6 +144,9 @@ jobs:
|
|
|
119
144
|
- name: dsh plugin registration
|
|
120
145
|
run: npx tsx tests/test_dsh_integration.ts
|
|
121
146
|
|
|
147
|
+
- name: dsh current SDK compatibility
|
|
148
|
+
run: npx tsx tests/test_dsh_sdk_compat.ts
|
|
149
|
+
|
|
122
150
|
- name: Hermes plugin registration
|
|
123
151
|
run: pytest tests/test_hermes_integration.py -v
|
|
124
152
|
|
|
@@ -135,9 +163,13 @@ jobs:
|
|
|
135
163
|
run: npx tsx tests/e2e/test_dsh_e2e.ts
|
|
136
164
|
|
|
137
165
|
e2e-llm:
|
|
138
|
-
# Real
|
|
166
|
+
# Real OpenAI-compatible call. API key is a secret; URL/model can also be variables.
|
|
139
167
|
# (skipped on forks to prevent secret exposure).
|
|
168
|
+
# continue-on-error: like `network` — non-deterministic output must not
|
|
169
|
+
# block the release path (see publish.yml).
|
|
170
|
+
continue-on-error: true
|
|
140
171
|
runs-on: ubuntu-latest
|
|
172
|
+
timeout-minutes: 20
|
|
141
173
|
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
|
142
174
|
steps:
|
|
143
175
|
- uses: actions/checkout@v4
|
|
@@ -150,33 +182,43 @@ jobs:
|
|
|
150
182
|
- uses: actions/setup-node@v4
|
|
151
183
|
with:
|
|
152
184
|
node-version: "20"
|
|
185
|
+
cache: "npm"
|
|
186
|
+
|
|
187
|
+
- name: Resolve model endpoint on runner
|
|
188
|
+
env:
|
|
189
|
+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL || vars.OPENAI_BASE_URL }}
|
|
190
|
+
run: node scripts/ci-resolve-llm-host.mjs
|
|
153
191
|
|
|
154
192
|
- name: Install Python dependencies
|
|
155
193
|
run: |
|
|
156
194
|
pip install -r tools/requirements.txt
|
|
157
195
|
pip install -r requirements-dev.txt
|
|
158
196
|
|
|
197
|
+
# Full npm ci (postinstall builds .venv) — the Pi LLM flow spawns tools
|
|
198
|
+
# through it.
|
|
159
199
|
- name: Install Node dependencies
|
|
160
|
-
run: npm
|
|
200
|
+
run: npm ci
|
|
161
201
|
|
|
162
202
|
- name: E2E — Hermes LLM flow
|
|
163
203
|
env:
|
|
164
|
-
|
|
165
|
-
|
|
204
|
+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL || vars.OPENAI_BASE_URL }}
|
|
205
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
206
|
+
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL || vars.OPENAI_MODEL }}
|
|
166
207
|
run: |
|
|
167
|
-
if [ -z "$
|
|
168
|
-
echo "
|
|
208
|
+
if [ -z "$OPENAI_BASE_URL" ] || [ -z "$OPENAI_API_KEY" ] || [ -z "$OPENAI_MODEL" ]; then
|
|
209
|
+
echo "OPENAI_BASE_URL, OPENAI_API_KEY, and OPENAI_MODEL are required — skipping LLM e2e"
|
|
169
210
|
exit 0
|
|
170
211
|
fi
|
|
171
212
|
pytest tests/e2e/test_hermes_llm.py -m integration_llm -v
|
|
172
213
|
|
|
173
214
|
- name: E2E — Pi LLM flow
|
|
174
215
|
env:
|
|
175
|
-
|
|
176
|
-
|
|
216
|
+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL || vars.OPENAI_BASE_URL }}
|
|
217
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
218
|
+
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL || vars.OPENAI_MODEL }}
|
|
177
219
|
run: |
|
|
178
|
-
if [ -z "$
|
|
179
|
-
echo "
|
|
220
|
+
if [ -z "$OPENAI_BASE_URL" ] || [ -z "$OPENAI_API_KEY" ] || [ -z "$OPENAI_MODEL" ]; then
|
|
221
|
+
echo "OPENAI_BASE_URL, OPENAI_API_KEY, and OPENAI_MODEL are required — skipping LLM e2e"
|
|
180
222
|
exit 0
|
|
181
223
|
fi
|
|
182
224
|
npx tsx tests/e2e/test_pi_llm.ts
|
|
@@ -201,39 +243,42 @@ jobs:
|
|
|
201
243
|
python-version: "3.11"
|
|
202
244
|
|
|
203
245
|
- uses: actions/setup-node@v4
|
|
204
|
-
#
|
|
205
|
-
# (dsh also requires ^22.19 || >=24)
|
|
246
|
+
# OpenClaw 2026.9.6 requires Node >=24.16.
|
|
206
247
|
with:
|
|
207
|
-
node-version: "24"
|
|
248
|
+
node-version: "24.16.0"
|
|
249
|
+
cache: "npm"
|
|
250
|
+
|
|
251
|
+
- name: Resolve model endpoint on runner
|
|
252
|
+
env:
|
|
253
|
+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL || vars.OPENAI_BASE_URL }}
|
|
254
|
+
run: node scripts/ci-resolve-llm-host.mjs
|
|
208
255
|
|
|
209
256
|
- name: Install Node dependencies (also builds repo .venv via postinstall)
|
|
210
|
-
run: npm
|
|
257
|
+
run: npm ci
|
|
211
258
|
|
|
212
259
|
- name: Install host CLIs
|
|
213
|
-
#
|
|
214
|
-
# validated CLIs — openclaw@latest installed no working bin, and pi's
|
|
215
|
-
# `list` flags changed between releases. dsh is a developer preview
|
|
216
|
-
# (rc line), so pin it too. `dsh plugin` forwards to pnpm.
|
|
260
|
+
# Pin the current host releases so failures are reproducible.
|
|
217
261
|
run: |
|
|
218
|
-
npm i -g @earendil-works/pi-coding-agent@0.
|
|
219
|
-
npm i -g openclaw@2026.6
|
|
220
|
-
npm i -g @deepseek-ai/dsh@0.
|
|
262
|
+
npm i -g @earendil-works/pi-coding-agent@0.99.0
|
|
263
|
+
npm i -g openclaw@2026.9.6
|
|
264
|
+
npm i -g @deepseek-ai/dsh@0.2.0-rc.2
|
|
221
265
|
npm i -g pnpm@10
|
|
222
266
|
|
|
223
267
|
- name: Real-host smoke QA (${{ matrix.host }})
|
|
224
268
|
env:
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
269
|
+
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL || vars.OPENAI_BASE_URL }}
|
|
270
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
271
|
+
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL || vars.OPENAI_MODEL }}
|
|
228
272
|
run: |
|
|
229
|
-
if [ -z "$
|
|
230
|
-
echo "
|
|
273
|
+
if [ -z "$OPENAI_BASE_URL" ] || [ -z "$OPENAI_API_KEY" ] || [ -z "$OPENAI_MODEL" ]; then
|
|
274
|
+
echo "OPENAI_BASE_URL, OPENAI_API_KEY, and OPENAI_MODEL are required (blocking check)"
|
|
231
275
|
exit 1
|
|
232
276
|
fi
|
|
233
277
|
node tests/e2e/host_smoke.mjs ${{ matrix.host }}
|
|
234
278
|
|
|
235
279
|
build:
|
|
236
280
|
runs-on: ubuntu-latest
|
|
281
|
+
timeout-minutes: 10
|
|
237
282
|
needs: [lint, test, compat]
|
|
238
283
|
steps:
|
|
239
284
|
- uses: actions/checkout@v4
|
|
@@ -241,9 +286,19 @@ jobs:
|
|
|
241
286
|
- uses: actions/setup-node@v4
|
|
242
287
|
with:
|
|
243
288
|
node-version: "20"
|
|
289
|
+
cache: "npm"
|
|
244
290
|
|
|
291
|
+
# --ignore-scripts: packing/bundling doesn't need the Python venv
|
|
292
|
+
# (esbuild's binary arrives via optionalDependencies, not postinstall).
|
|
245
293
|
- name: Install Node dependencies
|
|
246
|
-
run: npm
|
|
294
|
+
run: npm ci --ignore-scripts
|
|
295
|
+
|
|
296
|
+
# Bundle both compiled hosts here so esbuild breakage surfaces in CI
|
|
297
|
+
# instead of at tag-publish time.
|
|
298
|
+
- name: Build host bundles
|
|
299
|
+
run: |
|
|
300
|
+
npm run build:openclaw
|
|
301
|
+
npm run build:dsh
|
|
247
302
|
|
|
248
303
|
- name: Verify pack contents
|
|
249
304
|
run: npm pack --dry-run
|
|
@@ -6,6 +6,9 @@ on:
|
|
|
6
6
|
- "v*"
|
|
7
7
|
|
|
8
8
|
jobs:
|
|
9
|
+
# ci is a whole-workflow reusable call — a caller cannot `needs` individual
|
|
10
|
+
# jobs inside it, so the flaky jobs (network, e2e-llm) carry job-level
|
|
11
|
+
# `continue-on-error: true` in ci.yml to keep them off the release path.
|
|
9
12
|
ci:
|
|
10
13
|
uses: ./.github/workflows/ci.yml
|
|
11
14
|
secrets: inherit
|
|
@@ -29,8 +32,9 @@ jobs:
|
|
|
29
32
|
- name: Sync version from tag
|
|
30
33
|
run: bash scripts/sync-version.sh
|
|
31
34
|
|
|
35
|
+
# --ignore-scripts: publishing only packs and uploads — no Python venv.
|
|
32
36
|
- name: Install dependencies
|
|
33
|
-
run: npm
|
|
37
|
+
run: npm ci --ignore-scripts
|
|
34
38
|
|
|
35
39
|
- name: Build and verify
|
|
36
40
|
run: npm pack --dry-run
|
|
@@ -95,8 +99,9 @@ jobs:
|
|
|
95
99
|
- name: Sync version from tag
|
|
96
100
|
run: bash scripts/sync-version.sh
|
|
97
101
|
|
|
102
|
+
# --ignore-scripts: publishing only packs and uploads — no Python venv.
|
|
98
103
|
- name: Install dependencies
|
|
99
|
-
run: npm
|
|
104
|
+
run: npm ci --ignore-scripts
|
|
100
105
|
|
|
101
106
|
- name: Build compiled plugin entry (dist/index.js)
|
|
102
107
|
run: npm run build:openclaw
|
|
@@ -111,6 +116,7 @@ jobs:
|
|
|
111
116
|
fi
|
|
112
117
|
done
|
|
113
118
|
rm -f openclaw/scripts/sync-version.sh
|
|
119
|
+
cp LICENSE openclaw/LICENSE
|
|
114
120
|
|
|
115
121
|
# Guard against regression of the issue behind
|
|
116
122
|
# https://github.com/Weaxs/stock-analysis-plugin/issues/3 — a TS entry
|
|
@@ -124,11 +130,14 @@ jobs:
|
|
|
124
130
|
npm pack --dry-run 2>&1 | tee pack-dry-run.txt
|
|
125
131
|
grep -q "dist/index.js" pack-dry-run.txt \
|
|
126
132
|
|| { echo "::error::dist/index.js missing from openclaw npm tarball — build ran but files whitelist excludes dist/"; exit 1; }
|
|
133
|
+
grep -q "LICENSE" pack-dry-run.txt \
|
|
134
|
+
|| { echo "::error::LICENSE missing from openclaw npm tarball"; exit 1; }
|
|
127
135
|
test -f dist/index.js \
|
|
128
136
|
|| { echo "::error::openclaw/dist/index.js missing on disk — clawhub publish would ship no compiled entry"; exit 1; }
|
|
129
137
|
|
|
130
138
|
- name: Install clawhub CLI
|
|
131
|
-
|
|
139
|
+
# Pinned — an unpinned clawhub@latest broke a release before; bump deliberately.
|
|
140
|
+
run: npm i -g clawhub@0.23.3
|
|
132
141
|
|
|
133
142
|
- name: npm publish
|
|
134
143
|
working-directory: openclaw
|
|
@@ -142,10 +151,10 @@ jobs:
|
|
|
142
151
|
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
|
|
143
152
|
|
|
144
153
|
- name: Publish to ClawHub (dry-run)
|
|
145
|
-
run: clawhub package publish ./openclaw --dry-run
|
|
154
|
+
run: clawhub package publish ./openclaw --family bundle-plugin --dry-run
|
|
146
155
|
|
|
147
156
|
- name: Publish to ClawHub
|
|
148
|
-
run: clawhub package publish ./openclaw
|
|
157
|
+
run: clawhub package publish ./openclaw --family bundle-plugin
|
|
149
158
|
|
|
150
159
|
- name: Publish unscoped variant to npm
|
|
151
160
|
# Same payload under the unscoped name. Runs after ClawHub so the
|
|
@@ -174,8 +183,9 @@ jobs:
|
|
|
174
183
|
- name: Sync version from tag
|
|
175
184
|
run: bash scripts/sync-version.sh
|
|
176
185
|
|
|
186
|
+
# --ignore-scripts: publishing only packs and uploads — no Python venv.
|
|
177
187
|
- name: Install dependencies
|
|
178
|
-
run: npm
|
|
188
|
+
run: npm ci --ignore-scripts
|
|
179
189
|
|
|
180
190
|
- name: Build compiled plugin entry (dist/index.js)
|
|
181
191
|
run: npm run build:dsh
|
|
@@ -190,6 +200,7 @@ jobs:
|
|
|
190
200
|
fi
|
|
191
201
|
done
|
|
192
202
|
rm -f dsh/scripts/sync-version.sh
|
|
203
|
+
cp LICENSE dsh/LICENSE
|
|
193
204
|
|
|
194
205
|
# Same regression guard as the OpenClaw job: the dsh profile loader
|
|
195
206
|
# imports built JS, so dist must survive the `files` whitelist, and the
|
|
@@ -202,6 +213,8 @@ jobs:
|
|
|
202
213
|
|| { echo "::error::dist/index.js missing from dsh npm tarball — build ran but files whitelist excludes dist/"; exit 1; }
|
|
203
214
|
grep -q "cordis.patch.yml" pack-dry-run.txt \
|
|
204
215
|
|| { echo "::error::cordis.patch.yml missing from dsh npm tarball — dsh bundle manifest would dangle"; exit 1; }
|
|
216
|
+
grep -q "LICENSE" pack-dry-run.txt \
|
|
217
|
+
|| { echo "::error::LICENSE missing from dsh npm tarball"; exit 1; }
|
|
205
218
|
|
|
206
219
|
- name: npm publish
|
|
207
220
|
working-directory: dsh
|
|
@@ -7,13 +7,13 @@ A multi-host agent plugin for stock analysis, screening, and strategy backtestin
|
|
|
7
7
|
The architecture is **one Python core, four thin host adapters**:
|
|
8
8
|
|
|
9
9
|
- `tools/*.py` — the shared CLI tools. **This is the single source of truth** for all behavior. Every tool prints JSON to stdout.
|
|
10
|
-
- `pi/index.ts` — Pi extension. `pi.registerTool` ×
|
|
10
|
+
- `pi/index.ts` — Pi extension. `pi.registerTool` ×57, each spawns a `tools/*.py` CLI.
|
|
11
11
|
- `hermes/` — Hermes plugin (`plugin.yaml` + `register(ctx)` in `__init__.py`; `tools.py` handlers → subprocess to the same CLIs). Discovered via the `hermes_agent.plugins` entry point.
|
|
12
|
-
- `openclaw/` — OpenClaw plugin (`openclaw.plugin.json` manifest + `index.ts` `definePluginEntry` + `registerTool` ×
|
|
13
|
-
- `dsh/` — dsh bundle (`package.json` `dsh.bundle` + `cordis.patch.yml` + `index.ts` cordis `apply(ctx)` with `defineTool` ×
|
|
12
|
+
- `openclaw/` — OpenClaw plugin (`openclaw.plugin.json` manifest + `index.ts` `definePluginEntry` + `registerTool` ×57). Bundled with esbuild.
|
|
13
|
+
- `dsh/` — dsh bundle (`package.json` `dsh.bundle` + `cordis.patch.yml` + `index.ts` cordis `apply(ctx)` with `defineTool` ×57 via `@deepseek-ai/dsh-tools`; skills via `ctx.skills.register`). Bundled with esbuild, `@deepseek-ai/*` external (peer deps).
|
|
14
14
|
- `skills/*/SKILL.md` — 20 workflow / strategy-methodology skills shared by all four hosts.
|
|
15
15
|
|
|
16
|
-
> **The invariant that matters most:** the four adapters expose the *same*
|
|
16
|
+
> **The invariant that matters most:** the four adapters expose the *same* 57 tools over the *same* Python CLIs. A change to a tool's name, parameters, or JSON output shape must be applied to **all four adapters and the relevant SKILL.md together** — never just one.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -132,7 +132,7 @@ This is the #1 regression surface (issues #2 / #7; the `compat` CI job exists sp
|
|
|
132
132
|
- **Output is JSON on stdout, always.** Host adapters parse `result.stdout`. Human-readable prose goes to stderr, never stdout.
|
|
133
133
|
- **Errors are data**: print a JSON object with an `error` key (and exit non-zero) rather than an uncaught traceback, so adapters can surface a clean message.
|
|
134
134
|
- **argparse CLI per script**, subcommands per capability (`stock_data.py kline|quote|news|...`). See the README "独立 CLI 使用" section for the established shape.
|
|
135
|
-
- **Keep `tools/` py3.
|
|
135
|
+
- **Keep `tools/` py3.10-compatible** (`ruff.toml` targets `py310`; the Python floor is 3.10 everywhere — Hermes wheel `requires-python >= 3.10`, OpenClaw hosts). PEP 604 annotations (`X | None`) and other 3.10 syntax are allowed; nothing 3.11+-only.
|
|
136
136
|
- **Line length 120**, ruff rules `E,F,W,I,UP,B,SIM` (E501 ignored).
|
|
137
137
|
- Adding a runtime dependency means adding it to `tools/requirements.txt` (the postinstall-built `.venv`) **and** considering the Hermes wheel's `dependencies` in `pyproject.toml`. Follow ponytail rung 5 — don't add a dependency for a one-call problem.
|
|
138
138
|
|
|
@@ -222,7 +222,7 @@ Versions live in **five** manifests that must stay in lockstep: `pyproject.toml`
|
|
|
222
222
|
|
|
223
223
|
## Adding a New Tool
|
|
224
224
|
|
|
225
|
-
1. Implement the CLI in the appropriate `tools/*.py` (argparse subcommand, JSON stdout, py3.
|
|
225
|
+
1. Implement the CLI in the appropriate `tools/*.py` (argparse subcommand, JSON stdout, py3.10-compatible).
|
|
226
226
|
2. Add a failing pytest first (`tests/test_<module>.py`), then make it pass (see `tdd`).
|
|
227
227
|
3. Register it in all four adapters: `pi/index.ts`, `openclaw/index.ts`, `dsh/index.ts`, `hermes/tools.py` + `hermes/schemas.py` — same name, same params.
|
|
228
228
|
4. Wire it into the relevant `skills/*/SKILL.md` workflow if an agent should call it.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Weaxs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|