agent-wire-cli 0.2.3__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.claude-plugin/plugin.json +1 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/dependabot.yml +4 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/workflows/ci.yml +8 -8
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/workflows/codeql.yml +1 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/workflows/release.yml +4 -4
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/workflows/security.yml +7 -7
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/PKG-INFO +62 -30
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/README.md +61 -29
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/SECURITY.md +10 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/gemini_extension.json +1 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/hermes_skill.md +1 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/pyproject.toml +1 -1
- agent_wire_cli-0.2.4/src/agent_wire/__init__.py +1 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/base.py +7 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/github.py +2 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/reddit.py +2 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/web.py +2 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/hubs.py +2 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/publishing.py +2 -2
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/douyin_tiktok.py +10 -3
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/codemode/sandbox.py +32 -8
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/firewall/outbound_privacy.py +22 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_channels_new.py +16 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_codemode.py +20 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_firewall_outbound.py +20 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/uv.lock +4 -4
- agent_wire_cli-0.2.3/src/agent_wire/__init__.py +0 -1
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.claude-plugin/marketplace.json +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.github/scripts/mcp_smoke.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.gitignore +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/.mcp.json +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/LICENSE +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/agents/wire-worker.md +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-banner-light.png +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-banner-light.svg +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-banner.png +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-banner.svg +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-logo-transparent.png +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-logo-transparent.svg +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-logo.png +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/assets/agent-wire-logo.svg +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/antigravity_mcp.json +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/codex.toml +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/cursor_rule.mdc +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/peridot_local.json +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/manifests/windsurf_rules.md +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/skills/agent-wire/SKILL.md +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/__main__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/auth/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/auth/browser_paths.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/auth/cookie_vault.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/auth/rate_limiter.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/cache/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/cache/ring_buffer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/cache/sqlite_ledger.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/hackernews.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/rss.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/search.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/stackoverflow.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/wikipedia.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/x_twitter.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/youtube.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/archive_bypass.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/arxiv_papers.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/devto.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/fediverse.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/linkedin.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/markets.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/meta_social.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/news.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/polymarket.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier2_pro/stocktwits.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/bilibili.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/boss_zhipin.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/v2ex.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/wechat.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/xiaohongshu.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/xiaoyuzhou.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/xueqiu.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier3_regional/zhihu.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/cli.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/codemode/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/codemode/api.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/compression/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/compression/anchor_slicer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/compression/bm25_slicer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/compression/dam_formatter.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/compression/url_compactor.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/config.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/challenge.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/errors.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/http_pool.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/stealth_browser.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/engine/waterfall.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/firewall/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/firewall/inbound_shield.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/firewall/ssrf_guard.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/installers/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/installers/client_installer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/media/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/media/audio_transcriber.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/media/subtitle_cleaner.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/models.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/brief.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/briefing.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/cluster.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/engine.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/library.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/planner.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/scoring.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/store.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/research/watch.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/router.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/server.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/verify/__init__.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/verify/citations.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/conftest.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_auth.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_bm25_slicer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_channels_tier1.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_channels_tier2_3.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_citations.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_codemode_bench.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_compression.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_config.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_firewall_inbound.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_installer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_models.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_research.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_ring_buffer.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_server.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_ssrf_guard.py +0 -0
- {agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/tests/test_waterfall_routing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-wire",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Live web and 31-platform access for agents: token-compressed, privacy-firewalled, injection-shielded. Auto-triggers on links and live questions.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "uncoalesced"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
version: 2
|
|
2
2
|
updates:
|
|
3
3
|
# Python dependencies in uv.lock. Security fixes come as separate PRs straight away
|
|
4
|
-
# (Dependabot security updates); this keeps routine upgrades to one weekly batch.
|
|
4
|
+
# (Dependabot security updates); this keeps routine upgrades to one weekly batch. Routine
|
|
5
|
+
# upgrades wait 7 days after a release, so a hijacked version is usually pulled before we take it.
|
|
5
6
|
- package-ecosystem: uv
|
|
6
7
|
directory: /
|
|
7
8
|
target-branch: dev
|
|
@@ -13,6 +14,8 @@ updates:
|
|
|
13
14
|
patterns: ["*"]
|
|
14
15
|
update-types: [minor, patch]
|
|
15
16
|
open-pull-requests-limit: 5
|
|
17
|
+
cooldown:
|
|
18
|
+
default-days: 7
|
|
16
19
|
|
|
17
20
|
# Actions are pinned to commit SHAs; this bumps the SHA and the version comment together.
|
|
18
21
|
- package-ecosystem: github-actions
|
|
@@ -17,10 +17,10 @@ jobs:
|
|
|
17
17
|
runs-on: ubuntu-latest
|
|
18
18
|
timeout-minutes: 10
|
|
19
19
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
20
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
21
21
|
with:
|
|
22
22
|
persist-credentials: false
|
|
23
|
-
- uses: astral-sh/setup-uv@
|
|
23
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
24
24
|
- name: Lockfile matches pyproject.toml
|
|
25
25
|
run: uv lock --check
|
|
26
26
|
- name: Install
|
|
@@ -44,10 +44,10 @@ jobs:
|
|
|
44
44
|
runs-on: ${{ matrix.os }}
|
|
45
45
|
timeout-minutes: 20
|
|
46
46
|
steps:
|
|
47
|
-
- uses: actions/checkout@
|
|
47
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
48
48
|
with:
|
|
49
49
|
persist-credentials: false
|
|
50
|
-
- uses: astral-sh/setup-uv@
|
|
50
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
51
51
|
with:
|
|
52
52
|
python-version: ${{ matrix.python }}
|
|
53
53
|
- name: Install
|
|
@@ -59,10 +59,10 @@ jobs:
|
|
|
59
59
|
runs-on: ubuntu-latest
|
|
60
60
|
timeout-minutes: 10
|
|
61
61
|
steps:
|
|
62
|
-
- uses: actions/checkout@
|
|
62
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
63
63
|
with:
|
|
64
64
|
persist-credentials: false
|
|
65
|
-
- uses: astral-sh/setup-uv@
|
|
65
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
66
66
|
- name: Build sdist and wheel
|
|
67
67
|
run: uv build
|
|
68
68
|
- name: Package metadata renders on PyPI
|
|
@@ -93,10 +93,10 @@ jobs:
|
|
|
93
93
|
runs-on: ${{ matrix.os }}
|
|
94
94
|
timeout-minutes: 15
|
|
95
95
|
steps:
|
|
96
|
-
- uses: actions/checkout@
|
|
96
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
97
97
|
with:
|
|
98
98
|
persist-credentials: false
|
|
99
|
-
- uses: astral-sh/setup-uv@
|
|
99
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
100
100
|
with:
|
|
101
101
|
python-version: ${{ matrix.python }}
|
|
102
102
|
- name: Build wheel
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
contents: read
|
|
28
28
|
security-events: write # upload results to the Security tab
|
|
29
29
|
steps:
|
|
30
|
-
- uses: actions/checkout@
|
|
30
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
31
31
|
with:
|
|
32
32
|
persist-credentials: false
|
|
33
33
|
- uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
@@ -15,10 +15,10 @@ jobs:
|
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
timeout-minutes: 20
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
19
|
with:
|
|
20
20
|
persist-credentials: false
|
|
21
|
-
- uses: astral-sh/setup-uv@
|
|
21
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
22
22
|
with:
|
|
23
23
|
enable-cache: false # never build a release from a cache another run could have written
|
|
24
24
|
- name: Tag matches the package version
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
- run: uv run pytest -q
|
|
30
30
|
- run: uv build
|
|
31
31
|
- run: uvx twine check --strict dist/*
|
|
32
|
-
- uses: actions/upload-artifact@
|
|
32
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
33
33
|
with:
|
|
34
34
|
name: dist
|
|
35
35
|
path: dist/
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
permissions:
|
|
43
43
|
id-token: write # PyPI trusted publishing
|
|
44
44
|
steps:
|
|
45
|
-
- uses: actions/download-artifact@
|
|
45
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
46
46
|
with:
|
|
47
47
|
name: dist
|
|
48
48
|
path: dist/
|
|
@@ -21,10 +21,10 @@ jobs:
|
|
|
21
21
|
runs-on: ubuntu-latest
|
|
22
22
|
timeout-minutes: 10
|
|
23
23
|
steps:
|
|
24
|
-
- uses: actions/checkout@
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
25
|
with:
|
|
26
26
|
persist-credentials: false
|
|
27
|
-
- uses: astral-sh/setup-uv@
|
|
27
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
28
28
|
- name: Export the lockfile
|
|
29
29
|
run: uv export --frozen --no-hashes --all-extras --no-emit-project -o requirements-audit.txt
|
|
30
30
|
- name: pip-audit
|
|
@@ -35,10 +35,10 @@ jobs:
|
|
|
35
35
|
runs-on: ubuntu-latest
|
|
36
36
|
timeout-minutes: 10
|
|
37
37
|
steps:
|
|
38
|
-
- uses: actions/checkout@
|
|
38
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
39
39
|
with:
|
|
40
40
|
persist-credentials: false
|
|
41
|
-
- uses: astral-sh/setup-uv@
|
|
41
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
42
42
|
- name: bandit
|
|
43
43
|
run: uvx bandit==1.9.4 -r src -ll
|
|
44
44
|
|
|
@@ -47,10 +47,10 @@ jobs:
|
|
|
47
47
|
runs-on: ubuntu-latest
|
|
48
48
|
timeout-minutes: 10
|
|
49
49
|
steps:
|
|
50
|
-
- uses: actions/checkout@
|
|
50
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
51
51
|
with:
|
|
52
52
|
persist-credentials: false
|
|
53
|
-
- uses: astral-sh/setup-uv@
|
|
53
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
54
54
|
- name: zizmor
|
|
55
55
|
run: uvx zizmor==1.31.1 --format plain .github/workflows
|
|
56
56
|
env:
|
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
runs-on: ubuntu-latest
|
|
63
63
|
timeout-minutes: 10
|
|
64
64
|
steps:
|
|
65
|
-
- uses: actions/checkout@
|
|
65
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
66
66
|
with:
|
|
67
67
|
persist-credentials: false
|
|
68
68
|
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-wire-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: High-speed, privacy-first, token-compressed live web and multi-platform intelligence engine for AI agents.
|
|
5
5
|
Project-URL: Homepage, https://github.com/uncoalesced/agent-wire
|
|
6
6
|
License: MIT
|
|
@@ -43,6 +43,7 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
<a href="https://github.com/uncoalesced/agent-wire/actions/workflows/ci.yml"><img alt="CI" height="20" src="https://img.shields.io/github/actions/workflow/status/uncoalesced/agent-wire/ci.yml?branch=main&label=ci"></a>
|
|
44
44
|
<a href="LICENSE"><img alt="MIT license" height="20" src="https://img.shields.io/badge/license-MIT-f5b884"></a>
|
|
45
45
|
<a href="https://m8ven.ai/mcp/uncoalesced/agent-wire?s=readme"><img alt="M8ven Score" height="20" src="https://m8ven.ai/badge/mcp/uncoalesced/agent-wire"></a>
|
|
46
|
+
<a href="https://mcpservers.org/servers/uncoalesced/agent-wire"><img alt="Listed on mcpservers.org" height="20" src="https://mcpservers.org/badge.svg"></a>
|
|
46
47
|
</p>
|
|
47
48
|
|
|
48
49
|
<p align="center">
|
|
@@ -459,52 +460,65 @@ Tokens are the cost an agent feels first: money on an API plan, rate limits on a
|
|
|
459
460
|
|
|
460
461
|
### What a page costs
|
|
461
462
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
| Page |
|
|
465
|
-
|
|
466
|
-
| GitHub issue (uv #1495) |
|
|
467
|
-
|
|
|
468
|
-
|
|
|
469
|
-
|
|
|
470
|
-
|
|
|
471
|
-
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
463
|
+
On 2026-11-04 we read 16 pages from India, three times each, every time cold with a fresh `WIRE_HOME`, on the `dev` branch after v0.2.3 (commit `e7077af`). Tokens are counted with tiktoken (`o200k_base`), and the agent-wire count includes its header line, since that reaches the model too. "Plain fetch" is one ordinary GET with a browser user agent. [Jina Reader](https://jina.ai/reader/) is the free `r.jina.ai` endpoint with no key, which is what Agent-Reach uses first for web reads.
|
|
464
|
+
|
|
465
|
+
| Page | Plain fetch | Jina Reader | agent-wire | Saved vs plain |
|
|
466
|
+
|---|---|---|---|---|
|
|
467
|
+
| GitHub issue (uv #1495) | 184,922 | failed (403) | 2,066 | 99% |
|
|
468
|
+
| GitHub repo README (uv) | 152,386 | failed (403) | 3,003 | 98% |
|
|
469
|
+
| YouTube video page | 630,615 | failed (bot check) | 3,031 | 99.5% |
|
|
470
|
+
| Wikipedia (Model Context Protocol) | 80,494 | 8,326 | 1,868 | 98% |
|
|
471
|
+
| dev.to/t/ai | 56,834 | 12,290 | 1,017 | 98% |
|
|
472
|
+
| Cloudflare blog post | 105,755 | 2,369 | 2,051 | 98% |
|
|
473
|
+
| MDN Fetch API | 41,251 | 1,355 | 633 | 98% |
|
|
474
|
+
| Bluesky profile | 15,673 | 142 | 756 | 95% |
|
|
475
|
+
| Hacker News thread | 32,712 | 16,656 | 1,933 | 94% |
|
|
476
|
+
| docs.python.org asyncio | 6,941 | 883 | 584 | 92% |
|
|
477
|
+
| arXiv abstract (Attention Is All You Need) | 12,961 | 772 | 3,031 | 77% |
|
|
478
|
+
| Stack Overflow question | blocked (403) | 25,821 | 2,211 | |
|
|
479
|
+
| Medium post | blocked (403) | failed (403) | 2,827 | |
|
|
480
|
+
| Reddit r/Python | blocked | failed (blocked) | 2,395 | |
|
|
481
|
+
| npm package page (react) | blocked (403) | failed (CAPTCHA) | 123 | |
|
|
482
|
+
| Cloudflare challenge page (nowsecure.nl) | challenge page | 52 | 87 | |
|
|
483
|
+
|
|
484
|
+
- **Pages read:** agent-wire 16 of 16, Jina Reader 10 of 16, plain fetch 11 of 16.
|
|
485
|
+
- **Saving vs plain fetch:** median 98% on the 11 pages a plain fetch could read. The arXiv abstract was the weakest at 77%, because agent-wire opens the full paper rather than the abstract page and fills its token budget from it.
|
|
486
|
+
- **Against Jina Reader:** on the 10 pages both could read, agent-wire returned 14,171 tokens in total and Jina 68,666, so 79% fewer, and fewer on 7 of the 10. Jina was smaller on the arXiv abstract (it returns only the abstract page), the Bluesky profile (a thin cached snapshot) and the nowsecure.nl page. The comparison isn't like for like: agent-wire trims every read to a budget (3,000 tokens by default, ranked by relevance when you pass a `query`), and Jina returns the whole page. Long Hacker News and Stack Overflow threads are where that shows most.
|
|
487
|
+
- **Speed:** a cold read took 0.76 seconds at the median over 48 reads, and 3.1 seconds at the 90th percentile. The slowest was the Cloudflare challenge page, which goes through the stage 4 browser: 6 to 16 seconds. Jina's median was 0.7 seconds on the pages it could read, with a few 15 to 16 second outliers.
|
|
488
|
+
- **Search:** five searches that auto-read their top hits took 2.4 seconds at the median and returned about 2,500 tokens each.
|
|
476
489
|
|
|
477
490
|
### What it costs to have it installed
|
|
478
491
|
|
|
479
|
-
This is the part that doesn't flatter agent-wire, so here it is plainly.
|
|
492
|
+
This is the part that doesn't flatter agent-wire, so here it is plainly. We counted what each tool puts into context before it does any work, using the `o200k_base` tokenizer. Claude's tokenizer counts differently, so read these as comparable to each other and not as an exact bill. The agent-wire rows were re-counted on 2026-11-04 from the server's live tool list, taking each tool's name, description and input schema, which is what an API client sends to the model. That method counts a little more than the one we used on 2026-10-29 (1,603 for the standard profile then); the tools themselves haven't changed since v0.2.3.
|
|
480
493
|
|
|
481
494
|
| What loads | Tokens | When |
|
|
482
495
|
|---|---|---|
|
|
483
|
-
| agent-wire tool definitions, standard profile (8 tools) | 1,
|
|
484
|
-
| agent-wire tool definitions, `--profile local` (7 tools) |
|
|
485
|
-
| agent-wire tool definitions, `--code-mode` (2 tools) |
|
|
486
|
-
| agent-wire
|
|
487
|
-
|
|
|
488
|
-
| [
|
|
496
|
+
| agent-wire tool definitions, standard profile (8 tools) | 1,838, plus 150 for server instructions | every session |
|
|
497
|
+
| agent-wire tool definitions, `--profile local` (7 tools) | 961 | every session |
|
|
498
|
+
| agent-wire tool definitions, `--code-mode` (2 tools) | 500 | every session |
|
|
499
|
+
| agent-wire tool definitions, `--profile local --code-mode` (2 tools) | 155 | every session |
|
|
500
|
+
| agent-wire skill (`SKILL.md`) | 1,342 | when the skill triggers, depending on the client |
|
|
501
|
+
| [last30days](https://github.com/mvanhorn/last30days-skill) skill (`SKILL.md`, v3.31.0, counted 2026-10-29) | 7,029 | when the skill triggers |
|
|
502
|
+
| [Agent-Reach](https://github.com/Panniantong/Agent-Reach) skill (`SKILL.md`, counted 2026-10-29) | 1,933 | when the skill triggers |
|
|
489
503
|
|
|
490
|
-
An MCP server pays its tool definitions in every session, used or not. A skill costs roughly its one-paragraph description until it triggers. So on a day you never touch the web, agent-wire is the most expensive of the three to have installed. On a day you do, the order flips: its tool list
|
|
504
|
+
An MCP server pays its tool definitions in every session, used or not. A skill costs roughly its one-paragraph description until it triggers. So on a day you never touch the web, agent-wire is the most expensive of the three to have installed. On a day you do, the order flips: its tool list, instructions and skill come to about 3,300 tokens, and last30days's skill alone is about 7,000. If the 1,838 bothers you, `--profile local` and `--code-mode` cut it to 961 and 500, and both together to 155.
|
|
491
505
|
|
|
492
506
|
The comparison isn't clean. last30days's `SKILL.md` also carries a setup wizard and formatting rules, and Agent-Reach's is largely Chinese text, so its count isn't directly comparable with an English file's.
|
|
493
507
|
|
|
494
508
|
### What a task costs
|
|
495
509
|
|
|
496
|
-
Code Mode is where the biggest single saving is. The
|
|
510
|
+
Code Mode is where the biggest single saving is. The task: find the top four Hacker News threads on "rust async" and give each thread's three best comments. We count every token that enters the model's context: the tool arguments or the script, plus every tool result. The live run is from 2026-11-04 (three cold runs, same result each time); the offline one is the bundled benchmark (`pytest -s tests/test_codemode_bench.py`) on canned pages.
|
|
497
511
|
|
|
498
|
-
| Route | Context tokens | Round trips |
|
|
499
|
-
|
|
500
|
-
| Classic tools (one search, one batched read) | 3,394 | 2 |
|
|
501
|
-
| `wire_run` script | 468 | 1 |
|
|
512
|
+
| Route | Context tokens, live | Context tokens, offline | Round trips |
|
|
513
|
+
|---|---|---|---|
|
|
514
|
+
| Classic tools (one search, one batched read) | 2,864 | 3,394 | 2 |
|
|
515
|
+
| `wire_run` script | 459 | 468 | 1 |
|
|
502
516
|
|
|
503
|
-
That is 86%
|
|
517
|
+
That is 84% fewer live and 86% offline. In the live run the script's two calls pulled in 210,569 tokens of pages, and 297 tokens of answer came back to the model; the whole script took about 2.4 seconds. A second script that read r/LocalLLaMA and the Hacker News front page in parallel fetched 13,469 tokens and returned 569.
|
|
504
518
|
|
|
505
519
|
### What we didn't measure
|
|
506
520
|
|
|
507
|
-
We have not run last30days or Agent-Reach against agent-wire on the same pages,
|
|
521
|
+
We have not run last30days or Agent-Reach themselves against agent-wire on the same pages. The Jina Reader column above covers the first step of Agent-Reach's web reads, not the whole tool, and we have no per-task comparison with either. Neither project publishes per-run token figures in its README (we checked both), so there was nothing to quote either.
|
|
508
522
|
|
|
509
523
|
What their own docs say is structural. Agent-Reach tries an ordered list of tools for each action (web reads go to Jina Reader first, then Exa) and returns what they produce. Its README says some channels, such as Xueqiu, V2EX and GitHub, come back as organized content, but it describes no token budget or slicing step. last30days collects and ranks evidence across sources, and its `SKILL.md` has the host model write the brief from that evidence, so the evidence lands in your context and the model's brief is output tokens on top. Those are differences in design, not measurements, and either could be smaller than it looks.
|
|
510
524
|
|
|
@@ -636,6 +650,24 @@ Pages get the opposite treatment. Anything a person reading the page couldn't se
|
|
|
636
650
|
|
|
637
651
|
Logins you add with `wire auth login <site>` live in an AES-GCM vault whose key is protected by Windows DPAPI, or by a 0600 key file on macOS and Linux.
|
|
638
652
|
|
|
653
|
+
### Supply chain
|
|
654
|
+
|
|
655
|
+
A lot of recent malware has arrived through package registries: a hijacked npm package, or a post-install script that runs the moment you install something. Here is what agent-wire pulls in and how it gets to you, as of a scan on 2026-11-04.
|
|
656
|
+
|
|
657
|
+
- **No npm, no Node.** agent-wire is a Python package on PyPI. `uvx` or `pip` installs it, and nothing runs `npm` or `npx`.
|
|
658
|
+
- **No install scripts.** Every package in the lockfile ships prebuilt wheels, and installing a wheel unpacks files without running any of its code. Only the optional extras fetch more later, and only when you ask: `stealth` needs `playwright install chromium`, and `local-whisper` downloads a speech model on first use.
|
|
659
|
+
- **Small direct list.** 13 direct dependencies (12 on Python 3.13 and newer), all long-standing projects. The youngest is `quickjs-ng`, the Code Mode sandbox engine, first released in February 2026. With everything they pull in, that is 94 packages, or 117 with every optional extra.
|
|
660
|
+
- **Pinned and hashed.** `uv.lock` pins every package to one version with sha256 hashes, and CI installs from it. `pip install` and `uvx` resolve fresh versions within the ranges in `pyproject.toml`, so if you want our exact set, install from a checkout with `uv sync --locked`.
|
|
661
|
+
- **Scanned.** `pip-audit` over the full locked set (runtime plus every extra) found one advisory: CVE-2026-119284 in `joserfc`, pulled in through `fastmcp`. agent-wire never parses the JSON web tokens it concerns, and the lock now uses the fixed version, so there are no known vulnerabilities. Bandit found nothing at medium severity or above, and zizmor finds nothing in the workflows. CodeQL flagged seven host checks that matched by substring (so `evilnpmjs.com` counted as npm); those now match the exact host or its subdomains. Cookies were never at risk, because the vault picks them by the real request host.
|
|
662
|
+
- **Routine upgrades wait.** Dependabot holds routine dependency and Actions upgrades for 7 days after a release, so a hijacked version usually gets yanked before we take it. Security fixes still arrive straight away.
|
|
663
|
+
- **Releases you can check.** Releases are built and uploaded by GitHub Actions through PyPI Trusted Publishing, so no upload token exists to steal. Each file on PyPI carries a signed attestation that ties it to `release.yml` in this repository. Actions are pinned to commit SHAs, and every pull request runs `pip-audit`, bandit, zizmor, dependency review and CodeQL.
|
|
664
|
+
|
|
665
|
+
To check a release yourself:
|
|
666
|
+
|
|
667
|
+
```bash
|
|
668
|
+
uvx --from pypi-attestations pypi-attestations verify pypi --repository https://github.com/uncoalesced/agent-wire pypi:agent_wire_cli-0.2.3-py3-none-any.whl
|
|
669
|
+
```
|
|
670
|
+
|
|
639
671
|
## Privacy Policy
|
|
640
672
|
|
|
641
673
|
agent-wire runs on your machine. There's no agent-wire server, no account, no analytics and no telemetry.
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
<a href="https://github.com/uncoalesced/agent-wire/actions/workflows/ci.yml"><img alt="CI" height="20" src="https://img.shields.io/github/actions/workflow/status/uncoalesced/agent-wire/ci.yml?branch=main&label=ci"></a>
|
|
14
14
|
<a href="LICENSE"><img alt="MIT license" height="20" src="https://img.shields.io/badge/license-MIT-f5b884"></a>
|
|
15
15
|
<a href="https://m8ven.ai/mcp/uncoalesced/agent-wire?s=readme"><img alt="M8ven Score" height="20" src="https://m8ven.ai/badge/mcp/uncoalesced/agent-wire"></a>
|
|
16
|
+
<a href="https://mcpservers.org/servers/uncoalesced/agent-wire"><img alt="Listed on mcpservers.org" height="20" src="https://mcpservers.org/badge.svg"></a>
|
|
16
17
|
</p>
|
|
17
18
|
|
|
18
19
|
<p align="center">
|
|
@@ -429,52 +430,65 @@ Tokens are the cost an agent feels first: money on an API plan, rate limits on a
|
|
|
429
430
|
|
|
430
431
|
### What a page costs
|
|
431
432
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
| Page |
|
|
435
|
-
|
|
436
|
-
| GitHub issue (uv #1495) |
|
|
437
|
-
|
|
|
438
|
-
|
|
|
439
|
-
|
|
|
440
|
-
|
|
|
441
|
-
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
433
|
+
On 2026-11-04 we read 16 pages from India, three times each, every time cold with a fresh `WIRE_HOME`, on the `dev` branch after v0.2.3 (commit `e7077af`). Tokens are counted with tiktoken (`o200k_base`), and the agent-wire count includes its header line, since that reaches the model too. "Plain fetch" is one ordinary GET with a browser user agent. [Jina Reader](https://jina.ai/reader/) is the free `r.jina.ai` endpoint with no key, which is what Agent-Reach uses first for web reads.
|
|
434
|
+
|
|
435
|
+
| Page | Plain fetch | Jina Reader | agent-wire | Saved vs plain |
|
|
436
|
+
|---|---|---|---|---|
|
|
437
|
+
| GitHub issue (uv #1495) | 184,922 | failed (403) | 2,066 | 99% |
|
|
438
|
+
| GitHub repo README (uv) | 152,386 | failed (403) | 3,003 | 98% |
|
|
439
|
+
| YouTube video page | 630,615 | failed (bot check) | 3,031 | 99.5% |
|
|
440
|
+
| Wikipedia (Model Context Protocol) | 80,494 | 8,326 | 1,868 | 98% |
|
|
441
|
+
| dev.to/t/ai | 56,834 | 12,290 | 1,017 | 98% |
|
|
442
|
+
| Cloudflare blog post | 105,755 | 2,369 | 2,051 | 98% |
|
|
443
|
+
| MDN Fetch API | 41,251 | 1,355 | 633 | 98% |
|
|
444
|
+
| Bluesky profile | 15,673 | 142 | 756 | 95% |
|
|
445
|
+
| Hacker News thread | 32,712 | 16,656 | 1,933 | 94% |
|
|
446
|
+
| docs.python.org asyncio | 6,941 | 883 | 584 | 92% |
|
|
447
|
+
| arXiv abstract (Attention Is All You Need) | 12,961 | 772 | 3,031 | 77% |
|
|
448
|
+
| Stack Overflow question | blocked (403) | 25,821 | 2,211 | |
|
|
449
|
+
| Medium post | blocked (403) | failed (403) | 2,827 | |
|
|
450
|
+
| Reddit r/Python | blocked | failed (blocked) | 2,395 | |
|
|
451
|
+
| npm package page (react) | blocked (403) | failed (CAPTCHA) | 123 | |
|
|
452
|
+
| Cloudflare challenge page (nowsecure.nl) | challenge page | 52 | 87 | |
|
|
453
|
+
|
|
454
|
+
- **Pages read:** agent-wire 16 of 16, Jina Reader 10 of 16, plain fetch 11 of 16.
|
|
455
|
+
- **Saving vs plain fetch:** median 98% on the 11 pages a plain fetch could read. The arXiv abstract was the weakest at 77%, because agent-wire opens the full paper rather than the abstract page and fills its token budget from it.
|
|
456
|
+
- **Against Jina Reader:** on the 10 pages both could read, agent-wire returned 14,171 tokens in total and Jina 68,666, so 79% fewer, and fewer on 7 of the 10. Jina was smaller on the arXiv abstract (it returns only the abstract page), the Bluesky profile (a thin cached snapshot) and the nowsecure.nl page. The comparison isn't like for like: agent-wire trims every read to a budget (3,000 tokens by default, ranked by relevance when you pass a `query`), and Jina returns the whole page. Long Hacker News and Stack Overflow threads are where that shows most.
|
|
457
|
+
- **Speed:** a cold read took 0.76 seconds at the median over 48 reads, and 3.1 seconds at the 90th percentile. The slowest was the Cloudflare challenge page, which goes through the stage 4 browser: 6 to 16 seconds. Jina's median was 0.7 seconds on the pages it could read, with a few 15 to 16 second outliers.
|
|
458
|
+
- **Search:** five searches that auto-read their top hits took 2.4 seconds at the median and returned about 2,500 tokens each.
|
|
446
459
|
|
|
447
460
|
### What it costs to have it installed
|
|
448
461
|
|
|
449
|
-
This is the part that doesn't flatter agent-wire, so here it is plainly.
|
|
462
|
+
This is the part that doesn't flatter agent-wire, so here it is plainly. We counted what each tool puts into context before it does any work, using the `o200k_base` tokenizer. Claude's tokenizer counts differently, so read these as comparable to each other and not as an exact bill. The agent-wire rows were re-counted on 2026-11-04 from the server's live tool list, taking each tool's name, description and input schema, which is what an API client sends to the model. That method counts a little more than the one we used on 2026-10-29 (1,603 for the standard profile then); the tools themselves haven't changed since v0.2.3.
|
|
450
463
|
|
|
451
464
|
| What loads | Tokens | When |
|
|
452
465
|
|---|---|---|
|
|
453
|
-
| agent-wire tool definitions, standard profile (8 tools) | 1,
|
|
454
|
-
| agent-wire tool definitions, `--profile local` (7 tools) |
|
|
455
|
-
| agent-wire tool definitions, `--code-mode` (2 tools) |
|
|
456
|
-
| agent-wire
|
|
457
|
-
|
|
|
458
|
-
| [
|
|
466
|
+
| agent-wire tool definitions, standard profile (8 tools) | 1,838, plus 150 for server instructions | every session |
|
|
467
|
+
| agent-wire tool definitions, `--profile local` (7 tools) | 961 | every session |
|
|
468
|
+
| agent-wire tool definitions, `--code-mode` (2 tools) | 500 | every session |
|
|
469
|
+
| agent-wire tool definitions, `--profile local --code-mode` (2 tools) | 155 | every session |
|
|
470
|
+
| agent-wire skill (`SKILL.md`) | 1,342 | when the skill triggers, depending on the client |
|
|
471
|
+
| [last30days](https://github.com/mvanhorn/last30days-skill) skill (`SKILL.md`, v3.31.0, counted 2026-10-29) | 7,029 | when the skill triggers |
|
|
472
|
+
| [Agent-Reach](https://github.com/Panniantong/Agent-Reach) skill (`SKILL.md`, counted 2026-10-29) | 1,933 | when the skill triggers |
|
|
459
473
|
|
|
460
|
-
An MCP server pays its tool definitions in every session, used or not. A skill costs roughly its one-paragraph description until it triggers. So on a day you never touch the web, agent-wire is the most expensive of the three to have installed. On a day you do, the order flips: its tool list
|
|
474
|
+
An MCP server pays its tool definitions in every session, used or not. A skill costs roughly its one-paragraph description until it triggers. So on a day you never touch the web, agent-wire is the most expensive of the three to have installed. On a day you do, the order flips: its tool list, instructions and skill come to about 3,300 tokens, and last30days's skill alone is about 7,000. If the 1,838 bothers you, `--profile local` and `--code-mode` cut it to 961 and 500, and both together to 155.
|
|
461
475
|
|
|
462
476
|
The comparison isn't clean. last30days's `SKILL.md` also carries a setup wizard and formatting rules, and Agent-Reach's is largely Chinese text, so its count isn't directly comparable with an English file's.
|
|
463
477
|
|
|
464
478
|
### What a task costs
|
|
465
479
|
|
|
466
|
-
Code Mode is where the biggest single saving is. The
|
|
480
|
+
Code Mode is where the biggest single saving is. The task: find the top four Hacker News threads on "rust async" and give each thread's three best comments. We count every token that enters the model's context: the tool arguments or the script, plus every tool result. The live run is from 2026-11-04 (three cold runs, same result each time); the offline one is the bundled benchmark (`pytest -s tests/test_codemode_bench.py`) on canned pages.
|
|
467
481
|
|
|
468
|
-
| Route | Context tokens | Round trips |
|
|
469
|
-
|
|
470
|
-
| Classic tools (one search, one batched read) | 3,394 | 2 |
|
|
471
|
-
| `wire_run` script | 468 | 1 |
|
|
482
|
+
| Route | Context tokens, live | Context tokens, offline | Round trips |
|
|
483
|
+
|---|---|---|---|
|
|
484
|
+
| Classic tools (one search, one batched read) | 2,864 | 3,394 | 2 |
|
|
485
|
+
| `wire_run` script | 459 | 468 | 1 |
|
|
472
486
|
|
|
473
|
-
That is 86%
|
|
487
|
+
That is 84% fewer live and 86% offline. In the live run the script's two calls pulled in 210,569 tokens of pages, and 297 tokens of answer came back to the model; the whole script took about 2.4 seconds. A second script that read r/LocalLLaMA and the Hacker News front page in parallel fetched 13,469 tokens and returned 569.
|
|
474
488
|
|
|
475
489
|
### What we didn't measure
|
|
476
490
|
|
|
477
|
-
We have not run last30days or Agent-Reach against agent-wire on the same pages,
|
|
491
|
+
We have not run last30days or Agent-Reach themselves against agent-wire on the same pages. The Jina Reader column above covers the first step of Agent-Reach's web reads, not the whole tool, and we have no per-task comparison with either. Neither project publishes per-run token figures in its README (we checked both), so there was nothing to quote either.
|
|
478
492
|
|
|
479
493
|
What their own docs say is structural. Agent-Reach tries an ordered list of tools for each action (web reads go to Jina Reader first, then Exa) and returns what they produce. Its README says some channels, such as Xueqiu, V2EX and GitHub, come back as organized content, but it describes no token budget or slicing step. last30days collects and ranks evidence across sources, and its `SKILL.md` has the host model write the brief from that evidence, so the evidence lands in your context and the model's brief is output tokens on top. Those are differences in design, not measurements, and either could be smaller than it looks.
|
|
480
494
|
|
|
@@ -606,6 +620,24 @@ Pages get the opposite treatment. Anything a person reading the page couldn't se
|
|
|
606
620
|
|
|
607
621
|
Logins you add with `wire auth login <site>` live in an AES-GCM vault whose key is protected by Windows DPAPI, or by a 0600 key file on macOS and Linux.
|
|
608
622
|
|
|
623
|
+
### Supply chain
|
|
624
|
+
|
|
625
|
+
A lot of recent malware has arrived through package registries: a hijacked npm package, or a post-install script that runs the moment you install something. Here is what agent-wire pulls in and how it gets to you, as of a scan on 2026-11-04.
|
|
626
|
+
|
|
627
|
+
- **No npm, no Node.** agent-wire is a Python package on PyPI. `uvx` or `pip` installs it, and nothing runs `npm` or `npx`.
|
|
628
|
+
- **No install scripts.** Every package in the lockfile ships prebuilt wheels, and installing a wheel unpacks files without running any of its code. Only the optional extras fetch more later, and only when you ask: `stealth` needs `playwright install chromium`, and `local-whisper` downloads a speech model on first use.
|
|
629
|
+
- **Small direct list.** 13 direct dependencies (12 on Python 3.13 and newer), all long-standing projects. The youngest is `quickjs-ng`, the Code Mode sandbox engine, first released in February 2026. With everything they pull in, that is 94 packages, or 117 with every optional extra.
|
|
630
|
+
- **Pinned and hashed.** `uv.lock` pins every package to one version with sha256 hashes, and CI installs from it. `pip install` and `uvx` resolve fresh versions within the ranges in `pyproject.toml`, so if you want our exact set, install from a checkout with `uv sync --locked`.
|
|
631
|
+
- **Scanned.** `pip-audit` over the full locked set (runtime plus every extra) found one advisory: CVE-2026-119284 in `joserfc`, pulled in through `fastmcp`. agent-wire never parses the JSON web tokens it concerns, and the lock now uses the fixed version, so there are no known vulnerabilities. Bandit found nothing at medium severity or above, and zizmor finds nothing in the workflows. CodeQL flagged seven host checks that matched by substring (so `evilnpmjs.com` counted as npm); those now match the exact host or its subdomains. Cookies were never at risk, because the vault picks them by the real request host.
|
|
632
|
+
- **Routine upgrades wait.** Dependabot holds routine dependency and Actions upgrades for 7 days after a release, so a hijacked version usually gets yanked before we take it. Security fixes still arrive straight away.
|
|
633
|
+
- **Releases you can check.** Releases are built and uploaded by GitHub Actions through PyPI Trusted Publishing, so no upload token exists to steal. Each file on PyPI carries a signed attestation that ties it to `release.yml` in this repository. Actions are pinned to commit SHAs, and every pull request runs `pip-audit`, bandit, zizmor, dependency review and CodeQL.
|
|
634
|
+
|
|
635
|
+
To check a release yourself:
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
uvx --from pypi-attestations pypi-attestations verify pypi --repository https://github.com/uncoalesced/agent-wire pypi:agent_wire_cli-0.2.3-py3-none-any.whl
|
|
639
|
+
```
|
|
640
|
+
|
|
609
641
|
## Privacy Policy
|
|
610
642
|
|
|
611
643
|
agent-wire runs on your machine. There's no agent-wire server, no account, no analytics and no telemetry.
|
|
@@ -34,7 +34,15 @@ agent-wire sits between an AI agent and the open web, so it treats two things as
|
|
|
34
34
|
- Getting blocked, rate-limited or challenged by a site.
|
|
35
35
|
- Problems that need someone who can already edit your `WIRE_HOME`, your agent client config or your environment variables.
|
|
36
36
|
|
|
37
|
+
## Supply chain
|
|
38
|
+
|
|
39
|
+
Dependency problems are in scope too: a vulnerable or malicious package in `uv.lock`, a release file that doesn't match this repository, or a workflow that could leak a secret or publish something we didn't build.
|
|
40
|
+
|
|
41
|
+
- **Releases.** A pushed `v*` tag runs `.github/workflows/release.yml`, which builds the wheel and sdist, runs the tests and uploads to PyPI through Trusted Publishing. No PyPI token is stored anywhere. Each file gets a PEP 740 attestation naming this repository and workflow. Check one with `uvx --from pypi-attestations pypi-attestations verify pypi --repository https://github.com/uncoalesced/agent-wire pypi:<file name>`.
|
|
42
|
+
- **Dependencies.** `uv.lock` pins every package with sha256 hashes, and CI installs with `uv sync --locked`. Every locked package ships wheels, so installing runs no package code. There is no npm or Node dependency. Routine upgrades come through Dependabot, which waits 7 days after a release; security updates come straight away.
|
|
43
|
+
- **Checks on every push and pull request.** `pip-audit` over the full locked set including extras, bandit, zizmor on the workflows, CodeQL, and dependency review on pull requests. Actions are pinned to commit SHAs.
|
|
44
|
+
- **Last manual scan, 2026-11-04.** `pip-audit` found CVE-2026-119284 in `joserfc` (via `fastmcp`, in a code path agent-wire doesn't use); the lock was moved to the fixed version. No other known vulnerabilities. CodeQL's substring host-check alerts in the channel routers were fixed; the ones left in tests are assertions on test data.
|
|
45
|
+
|
|
37
46
|
## Known limitations
|
|
38
47
|
|
|
39
|
-
- **
|
|
40
|
-
- **Secret redaction.** Output scrubbing removes bearer tokens, session cookies, private IPs and your saved vault values. It does not catch every API-key format that might appear in public page text.
|
|
48
|
+
- **Secret redaction.** Output scrubbing removes bearer tokens, session cookies, private IPs, your saved vault values and well-known prefixed API keys (GitHub, OpenAI, Anthropic, AWS, Slack, Google, GitLab, Stripe, Hugging Face, npm). Keys with no recognizable prefix that appear in public page text are not caught.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-wire
|
|
3
3
|
description: Live web and platform access (Reddit, X, GitHub, YouTube, HN, StackOverflow, arXiv, markets, Bilibili, Xiaohongshu). Use whenever the user shares a URL, asks about live facts or community opinion, or about their own social account activity.
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
metadata:
|
|
6
6
|
hermes:
|
|
7
7
|
tags: [web, search, research, social]
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agent-wire-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "High-speed, privacy-first, token-compressed live web and multi-platform intelligence engine for AI agents."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.4"
|
|
@@ -6,6 +6,7 @@ import re
|
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
from datetime import UTC, datetime, timedelta
|
|
8
8
|
from typing import ClassVar
|
|
9
|
+
from urllib.parse import urlsplit
|
|
9
10
|
|
|
10
11
|
from selectolax.lexbor import LexborHTMLParser
|
|
11
12
|
|
|
@@ -79,6 +80,12 @@ class Channel:
|
|
|
79
80
|
return WireDocument(url=url, channel=self.name, **fields)
|
|
80
81
|
|
|
81
82
|
|
|
83
|
+
def on_host(url: str, domain: str) -> bool:
|
|
84
|
+
"""URL (or bare host) is `domain` or a subdomain of it; look-alikes like evil-domain.com don't match."""
|
|
85
|
+
host = (urlsplit(url if "//" in url else f"https://{url}").hostname or "").lower()
|
|
86
|
+
return host == domain or host.endswith("." + domain)
|
|
87
|
+
|
|
88
|
+
|
|
82
89
|
def ts(value) -> datetime | None:
|
|
83
90
|
"""Epoch seconds/ms or ISO-8601 -> aware datetime."""
|
|
84
91
|
if value in (None, ""):
|
{agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/github.py
RENAMED
|
@@ -9,7 +9,7 @@ from urllib.parse import quote, urlsplit
|
|
|
9
9
|
|
|
10
10
|
from selectolax.lexbor import LexborHTMLParser
|
|
11
11
|
|
|
12
|
-
from agent_wire.channels.base import Channel, WireUnsupported, compact_count, listing, ts
|
|
12
|
+
from agent_wire.channels.base import Channel, WireUnsupported, compact_count, listing, on_host, ts
|
|
13
13
|
from agent_wire.compression.anchor_slicer import parse_line_anchor, slice_lines, slice_section
|
|
14
14
|
from agent_wire.models import WireComment, WireDocument, WireSearchHit
|
|
15
15
|
|
|
@@ -85,7 +85,7 @@ class GitHubChannel(Channel):
|
|
|
85
85
|
parts = urlsplit(url)
|
|
86
86
|
host, segs = parts.hostname or "", [s for s in parts.path.split("/") if s]
|
|
87
87
|
anchor = section or parts.fragment or None
|
|
88
|
-
if host
|
|
88
|
+
if on_host(host, "githubusercontent.com"):
|
|
89
89
|
return await self._blob_raw(url, segs[0], segs[1], "/".join(segs[3:]), url)
|
|
90
90
|
if host == "gist.github.com" and len(segs) >= 2:
|
|
91
91
|
return await self._gist(url, segs[-1])
|
{agent_wire_cli-0.2.3 → agent_wire_cli-0.2.4}/src/agent_wire/channels/tier1_global/reddit.py
RENAMED
|
@@ -15,7 +15,7 @@ from urllib.parse import quote, urlencode, urlsplit
|
|
|
15
15
|
|
|
16
16
|
import defusedxml.ElementTree as ET # untrusted feeds: no entity expansion, no DTDs
|
|
17
17
|
|
|
18
|
-
from agent_wire.channels.base import Channel, WireUnsupported, html_text, listing, ts
|
|
18
|
+
from agent_wire.channels.base import Channel, WireUnsupported, html_text, listing, on_host, ts
|
|
19
19
|
from agent_wire.engine.waterfall import WireFetchError
|
|
20
20
|
from agent_wire.firewall.outbound_privacy import parse_json
|
|
21
21
|
from agent_wire.models import WireComment, WireSearchHit
|
|
@@ -95,7 +95,7 @@ def listing_items(data: dict) -> list[dict]:
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
def post_hit(d: dict, archived: bool = False) -> WireSearchHit:
|
|
98
|
-
link = None if d.get("is_self") or
|
|
98
|
+
link = None if d.get("is_self") or on_host(d.get("url") or "", "reddit.com") else d.get("url")
|
|
99
99
|
return WireSearchHit(
|
|
100
100
|
url=WWW + d.get("permalink", ""), title=d.get("title") or "",
|
|
101
101
|
snippet="" if d.get("selftext") in ("[removed]", "[deleted]") else (d.get("selftext") or "")[:300],
|
|
@@ -6,7 +6,7 @@ from urllib.parse import urlsplit
|
|
|
6
6
|
|
|
7
7
|
import trafilatura
|
|
8
8
|
|
|
9
|
-
from agent_wire.channels.base import Channel, WireUnsupported, html_to_markdown, ts
|
|
9
|
+
from agent_wire.channels.base import Channel, WireUnsupported, html_to_markdown, on_host, ts
|
|
10
10
|
from agent_wire.compression.anchor_slicer import parse_line_anchor, slice_lines, slice_section
|
|
11
11
|
from agent_wire.firewall.inbound_shield import clean_html
|
|
12
12
|
from agent_wire.models import WireDocument
|
|
@@ -87,7 +87,7 @@ class WebChannel(Channel):
|
|
|
87
87
|
if anchor:
|
|
88
88
|
body = slice_section(body, anchor) or body
|
|
89
89
|
meta = {"site": info["site"]} if info["site"] else {}
|
|
90
|
-
if f.stage == 3 and "web.archive.org"
|
|
90
|
+
if f.stage == 3 and on_host(f.url, "web.archive.org"):
|
|
91
91
|
meta["archived"] = f.url
|
|
92
92
|
return self.doc(
|
|
93
93
|
f, url, title=info["title"], author_handle=info["author"],
|
|
@@ -6,7 +6,7 @@ from urllib.parse import quote, urlsplit
|
|
|
6
6
|
from curl_cffi.requests.exceptions import RequestException
|
|
7
7
|
from selectolax.lexbor import LexborHTMLParser
|
|
8
8
|
|
|
9
|
-
from agent_wire.channels.base import Channel, WireUnsupported, html_to_markdown
|
|
9
|
+
from agent_wire.channels.base import Channel, WireUnsupported, html_to_markdown, on_host
|
|
10
10
|
from agent_wire.engine.waterfall import WireFetchError
|
|
11
11
|
from agent_wire.models import WireSearchHit
|
|
12
12
|
|
|
@@ -33,7 +33,7 @@ class HubsChannel(Channel):
|
|
|
33
33
|
host, segs = (p.hostname or "").removeprefix("www."), [s for s in p.path.split("/") if s]
|
|
34
34
|
if host == "pypi.org" and segs[:1] == ["project"] and len(segs) > 1:
|
|
35
35
|
return await self._pypi(url, segs[1], segs[2] if len(segs) > 2 else None)
|
|
36
|
-
if host
|
|
36
|
+
if on_host(host, "npmjs.com") and segs[:1] == ["package"] and len(segs) > 1:
|
|
37
37
|
name = "/".join(segs[1:3]) if segs[1].startswith("@") else segs[1]
|
|
38
38
|
return await self._npm(url, name)
|
|
39
39
|
if host == "crates.io" and segs[:1] == ["crates"] and len(segs) > 1:
|