thoughtleaders-cli 0.9.8__tar.gz → 0.9.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.
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.claude-plugin/plugin.json +1 -1
- thoughtleaders_cli-0.9.9/.github/workflows/ci.yml +66 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/PKG-INFO +20 -1
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/README.md +19 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/pyproject.toml +1 -1
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/__init__.py +1 -1
- thoughtleaders_cli-0.9.9/src/tl_cli/__main__.py +13 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/setup.py +71 -0
- thoughtleaders_cli-0.9.8/.github/workflows/ci.yml +0 -38
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.claude-plugin/marketplace.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.github/dependabot.yml +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.github/workflows/cli-integration.yml +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.github/workflows/python-publish.yml +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/.gitignore +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/AGENTS.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/API.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/CLAUDE.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/LICENSE +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/agents/keyword-context-classifier.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/agents/keyword-entity-resolver.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/agents/keyword-relevance-validator.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/agents/tl-analyst.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/agents/youtube-comment-classifier.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/hooks/hooks.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/hooks/scripts/load-tl-skill.mjs +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/hooks/scripts/post-usage.sh +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/hooks/scripts/pre-check.sh +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/business-glossary.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/elasticsearch-schema.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/firebolt-schema.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/postgres-schema.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/.gitignore +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/references/comment-patterns.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/references/peer-cohort.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/references/red-flags.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/references/scoring.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/_io_utf8.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/analyze_channel.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/anomaly_detector.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/comment_analyzer.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/comment_scraper.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/engagement_ratios.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/peer_cohort.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/report.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/resolve_channel.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/score.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/tl_cli.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/video_integrity.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/scripts/view_curves.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-create-workflow/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-create-workflow/references/creating-in-app.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-create-workflow/references/methodology.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-create-workflow/references/pitfalls.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-create-workflow/references/workflow-model.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/references/elasticsearch-content-search.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/references/help.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/build_report.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/expand_entities.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/fetch_context.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/probe.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/search_channels.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/search_videos.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/select_keywords.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/columns_brands.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/columns_channels.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/columns_content.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/columns_sponsorships.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/intelligence_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/intelligence_widget_schema.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/report_glossary.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/sortable_columns.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/sponsorship_filterset_schema.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/sponsorship_widget_schema.json +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/widgets.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-top-partnerships/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-top-partnerships/scripts/top_partnerships.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-views-guarantee/SKILL.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-views-guarantee/scripts/vg.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/_completions.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/_typer_utils.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/auth/__init__.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/auth/commands.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/auth/login.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/auth/pkce.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/auth/token_store.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/client/__init__.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/client/errors.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/client/http.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/__init__.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/_comments_common.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/balance.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/brands.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/bulk_import.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/changelog.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/channels.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/credits.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/db.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/deals.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/describe.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/doctor.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/matches.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/memory.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/profiles.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/proposals.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/recommender.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/reports.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/schema.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/skills.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/snapshots.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/sponsorships.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/uploads.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/whoami.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/workflows.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/config.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/filters.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/hints.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/main.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/output/__init__.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/output/formatter.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/query_history.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/self_update.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/skill_registry.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/__init__.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_auth.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_brands_winner_channels.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_build_report.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_channels_lookalike.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_db_repeat_warning.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_describe.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_error_hints.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_expand_entities.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_filters.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_http_auth.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_memory.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_output.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_probe.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_profiles.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_quota_refusal_message.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_refusal_rendering.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_reports.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_scripts_executable.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_search_channels.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_search_videos.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_select_keywords.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_setup.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_setup_marker_respect.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_skill_registry.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_skills_command.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_sponsorships.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_whoami_newsletter.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests/test_workflows.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/AGENTS.md +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/conftest.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_balance.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_db_es.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_db_fb.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_db_pg.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_schema.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/tests_cli/test_whoami.py +0 -0
- {thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/uv.lock +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Fast, hermetic checks on every push to main and every PR. These run the
|
|
4
|
+
# mocked unit suite under tests/ — no live API, no credits, fully
|
|
5
|
+
# deterministic. The live CLI tests live in cli-integration.yml.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
pull_request:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
unit-tests:
|
|
21
|
+
name: Unit tests (mocked) · py${{ matrix.python-version }}
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
# Matches `requires-python = ">=3.12"`.
|
|
27
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
- uses: astral-sh/setup-uv@v7
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
- name: Sync locked dependencies
|
|
34
|
+
run: uv sync --frozen --python ${{ matrix.python-version }}
|
|
35
|
+
- name: Run unit tests
|
|
36
|
+
# tests/ mock the HTTP client (CliRunner + fake get_client), so there
|
|
37
|
+
# is no network, no API key, and no credit spend.
|
|
38
|
+
run: uv run --python ${{ matrix.python-version }} --with pytest pytest tests/ -v
|
|
39
|
+
|
|
40
|
+
windows-launcher:
|
|
41
|
+
name: Windows launcher (tl setup windows)
|
|
42
|
+
# `tl setup windows` writes a tl.cmd that runs the CLI through the signed
|
|
43
|
+
# python.exe, so the unsigned pipx stub can't be blocked by Smart App
|
|
44
|
+
# Control. This job proves the wrapper is written and actually launches the
|
|
45
|
+
# CLI. NOTE: GitHub runners don't have SAC in enforcement, so this verifies
|
|
46
|
+
# the mechanism, not the block itself — real SAC validation needs a SAC/WDAC
|
|
47
|
+
# machine. Hermetic: a uv project install is a dev install, so the CLI's
|
|
48
|
+
# auto-updater no-ops (no network).
|
|
49
|
+
runs-on: windows-latest
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v7
|
|
52
|
+
- uses: astral-sh/setup-uv@v7
|
|
53
|
+
with:
|
|
54
|
+
enable-cache: true
|
|
55
|
+
- name: Sync locked dependencies
|
|
56
|
+
run: uv sync --frozen
|
|
57
|
+
- name: Install the launcher wrapper
|
|
58
|
+
run: uv run tl setup windows
|
|
59
|
+
- name: Wrapper exists and launches the CLI through python
|
|
60
|
+
shell: pwsh
|
|
61
|
+
run: |
|
|
62
|
+
$cmd = "$env:LOCALAPPDATA\Programs\tl-cli\tl.cmd"
|
|
63
|
+
if (-not (Test-Path $cmd)) { throw "wrapper not written at $cmd" }
|
|
64
|
+
Get-Content $cmd
|
|
65
|
+
& $cmd --version
|
|
66
|
+
if ($LASTEXITCODE -ne 0) { throw "wrapper failed to launch the CLI (exit $LASTEXITCODE)" }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: thoughtleaders-cli
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.9
|
|
4
4
|
Summary: ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence
|
|
5
5
|
Project-URL: Homepage, https://thoughtleaders.io
|
|
6
6
|
Project-URL: Repository, https://github.com/ThoughtLeaders-io/thoughtleaders-cli
|
|
@@ -92,6 +92,25 @@ uv tool install thoughtleaders-cli
|
|
|
92
92
|
pip install thoughtleaders-cli
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
#### Windows with Smart App Control / WDAC
|
|
96
|
+
|
|
97
|
+
The pipx/uv install above creates an **unsigned** launcher stub that Windows
|
|
98
|
+
Smart App Control (and enforced WDAC policies) block — `tl` fails to start with
|
|
99
|
+
a Code Integrity error. Fix it with:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
tl setup windows
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
That drops a small `tl.cmd` on your `PATH` (ahead of the blocked stub) which
|
|
106
|
+
launches the CLI through the already-signed `python.exe`, so it runs cleanly
|
|
107
|
+
under SAC. If `tl` is *already* blocked and won't start, bootstrap it through
|
|
108
|
+
the signed interpreter directly, then reopen your terminal:
|
|
109
|
+
|
|
110
|
+
```powershell
|
|
111
|
+
& "$env:USERPROFILE\pipx\venvs\thoughtleaders-cli\Scripts\python.exe" -m tl_cli setup windows
|
|
112
|
+
```
|
|
113
|
+
|
|
95
114
|
Then set up:
|
|
96
115
|
```bash
|
|
97
116
|
tl auth login # authenticate with ThoughtLeaders (OAuth2 browser flow, device code, or API key)
|
|
@@ -64,6 +64,25 @@ uv tool install thoughtleaders-cli
|
|
|
64
64
|
pip install thoughtleaders-cli
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
#### Windows with Smart App Control / WDAC
|
|
68
|
+
|
|
69
|
+
The pipx/uv install above creates an **unsigned** launcher stub that Windows
|
|
70
|
+
Smart App Control (and enforced WDAC policies) block — `tl` fails to start with
|
|
71
|
+
a Code Integrity error. Fix it with:
|
|
72
|
+
|
|
73
|
+
```powershell
|
|
74
|
+
tl setup windows
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
That drops a small `tl.cmd` on your `PATH` (ahead of the blocked stub) which
|
|
78
|
+
launches the CLI through the already-signed `python.exe`, so it runs cleanly
|
|
79
|
+
under SAC. If `tl` is *already* blocked and won't start, bootstrap it through
|
|
80
|
+
the signed interpreter directly, then reopen your terminal:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
& "$env:USERPROFILE\pipx\venvs\thoughtleaders-cli\Scripts\python.exe" -m tl_cli setup windows
|
|
84
|
+
```
|
|
85
|
+
|
|
67
86
|
Then set up:
|
|
68
87
|
```bash
|
|
69
88
|
tl auth login # authenticate with ThoughtLeaders (OAuth2 browser flow, device code, or API key)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Module entry point for the CLI.
|
|
2
|
+
|
|
3
|
+
Enables `python -m tl_cli` and serves as the single entry script for the
|
|
4
|
+
PyInstaller-frozen standalone build (see packaging/tl.spec). Invoking the CLI
|
|
5
|
+
through the signed `python.exe` / signed frozen exe is what keeps it runnable
|
|
6
|
+
under Windows Smart App Control, which blocks the unsigned launcher stub that
|
|
7
|
+
pipx/uv generate per install.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from tl_cli.main import cli
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
cli()
|
|
@@ -756,3 +756,74 @@ def setup_codex(
|
|
|
756
756
|
json_output=json_output,
|
|
757
757
|
toon_output=toon_output,
|
|
758
758
|
)
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
def _prepend_user_path(new_dir: str) -> bool:
|
|
762
|
+
"""Prepend ``new_dir`` to the persistent per-user PATH.
|
|
763
|
+
|
|
764
|
+
Writes HKCU\\Environment and broadcasts the change so new processes pick it
|
|
765
|
+
up without a sign-out. Returns True if PATH was changed, False if new_dir
|
|
766
|
+
was already present. Windows-only.
|
|
767
|
+
"""
|
|
768
|
+
import ctypes
|
|
769
|
+
import winreg
|
|
770
|
+
|
|
771
|
+
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | winreg.KEY_WRITE) as key:
|
|
772
|
+
try:
|
|
773
|
+
current, _ = winreg.QueryValueEx(key, "Path")
|
|
774
|
+
except FileNotFoundError:
|
|
775
|
+
current = ""
|
|
776
|
+
parts = [p for p in current.split(os.pathsep) if p]
|
|
777
|
+
target = os.path.normcase(os.path.normpath(new_dir))
|
|
778
|
+
if any(os.path.normcase(os.path.normpath(p)) == target for p in parts):
|
|
779
|
+
return False
|
|
780
|
+
updated = os.pathsep.join([new_dir, *parts]) if parts else new_dir
|
|
781
|
+
winreg.SetValueEx(key, "Path", 0, winreg.REG_EXPAND_SZ, updated)
|
|
782
|
+
|
|
783
|
+
# Tell running shells the environment changed (best-effort).
|
|
784
|
+
ctypes.windll.user32.SendMessageTimeoutW(0xFFFF, 0x1A, 0, "Environment", 0x2, 5000, None)
|
|
785
|
+
return True
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
@app.command("windows")
|
|
789
|
+
def setup_windows(
|
|
790
|
+
force: bool = typer.Option(False, "--force", help="Overwrite an existing tl.cmd wrapper"),
|
|
791
|
+
) -> None:
|
|
792
|
+
"""Make `tl` runnable under Windows Smart App Control (Windows only).
|
|
793
|
+
|
|
794
|
+
pipx/uv expose `tl` through an *unsigned* launcher stub that Smart App
|
|
795
|
+
Control (and enforced WDAC policies) block. This writes a small `tl.cmd`
|
|
796
|
+
that runs the CLI through the already-signed `python.exe` instead, and
|
|
797
|
+
puts it ahead of the blocked stub on your PATH.
|
|
798
|
+
|
|
799
|
+
Run once. On a machine where `tl` is already blocked, bootstrap it with
|
|
800
|
+
the venv's signed python directly:
|
|
801
|
+
|
|
802
|
+
<pipx-venv>\\Scripts\\python.exe -m tl_cli setup windows
|
|
803
|
+
|
|
804
|
+
Examples:
|
|
805
|
+
tl setup windows
|
|
806
|
+
"""
|
|
807
|
+
if sys.platform != "win32":
|
|
808
|
+
console.print("[yellow]`tl setup windows` only applies on Windows — nothing to do here.[/yellow]")
|
|
809
|
+
return
|
|
810
|
+
|
|
811
|
+
python_exe = Path(sys.executable)
|
|
812
|
+
wrapper_dir = Path(os.environ.get("LOCALAPPDATA", Path.home())) / "Programs" / "tl-cli"
|
|
813
|
+
wrapper = wrapper_dir / "tl.cmd"
|
|
814
|
+
|
|
815
|
+
if wrapper.exists() and not force:
|
|
816
|
+
console.print(f"[yellow]Wrapper already exists:[/yellow] {wrapper}\nRe-run with --force to regenerate it.")
|
|
817
|
+
return
|
|
818
|
+
|
|
819
|
+
wrapper_dir.mkdir(parents=True, exist_ok=True)
|
|
820
|
+
# Absolute path to the signed interpreter bypasses PATH so the launch can't
|
|
821
|
+
# resolve back to the blocked stub. %* forwards all arguments unchanged.
|
|
822
|
+
wrapper.write_text(f'@echo off\r\n"{python_exe}" -m tl_cli %*\r\n', encoding="ascii", newline="")
|
|
823
|
+
|
|
824
|
+
console.print(f"[green]✓[/green] Wrote signed-launcher wrapper: {wrapper}")
|
|
825
|
+
if _prepend_user_path(str(wrapper_dir)):
|
|
826
|
+
console.print(f"[green]✓[/green] Added to your user PATH (ahead of the blocked stub): {wrapper_dir}")
|
|
827
|
+
else:
|
|
828
|
+
console.print(f"[dim]Already on your user PATH: {wrapper_dir}[/dim]")
|
|
829
|
+
console.print("[dim]Open a new terminal, then run:[/dim] tl whoami")
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
# Fast, hermetic checks on every push to main and every PR. These run the
|
|
4
|
-
# mocked unit suite under tests/ — no live API, no credits, fully
|
|
5
|
-
# deterministic. The live CLI tests live in cli-integration.yml.
|
|
6
|
-
|
|
7
|
-
on:
|
|
8
|
-
push:
|
|
9
|
-
branches: [main]
|
|
10
|
-
pull_request:
|
|
11
|
-
|
|
12
|
-
permissions:
|
|
13
|
-
contents: read
|
|
14
|
-
|
|
15
|
-
concurrency:
|
|
16
|
-
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
17
|
-
cancel-in-progress: true
|
|
18
|
-
|
|
19
|
-
jobs:
|
|
20
|
-
unit-tests:
|
|
21
|
-
name: Unit tests (mocked) · py${{ matrix.python-version }}
|
|
22
|
-
runs-on: ubuntu-latest
|
|
23
|
-
strategy:
|
|
24
|
-
fail-fast: false
|
|
25
|
-
matrix:
|
|
26
|
-
# Matches `requires-python = ">=3.12"`.
|
|
27
|
-
python-version: ["3.12", "3.13", "3.14"]
|
|
28
|
-
steps:
|
|
29
|
-
- uses: actions/checkout@v7
|
|
30
|
-
- uses: astral-sh/setup-uv@v7
|
|
31
|
-
with:
|
|
32
|
-
enable-cache: true
|
|
33
|
-
- name: Sync locked dependencies
|
|
34
|
-
run: uv sync --frozen --python ${{ matrix.python-version }}
|
|
35
|
-
- name: Run unit tests
|
|
36
|
-
# tests/ mock the HTTP client (CliRunner + fake get_client), so there
|
|
37
|
-
# is no network, no API key, and no credit spend.
|
|
38
|
-
run: uv run --python ${{ matrix.python-version }} --with pytest pytest tests/ -v
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/business-glossary.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/elasticsearch-schema.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/firebolt-schema.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl/references/postgres-schema.md
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/.gitignore
RENAMED
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-channel-authenticity/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/references/help.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-keyword-research/scripts/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-save-report/references/widgets.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/skills/tl-views-guarantee/scripts/vg.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thoughtleaders_cli-0.9.8 → thoughtleaders_cli-0.9.9}/src/tl_cli/commands/_comments_common.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|