agent-crossbar 0.2.0__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_crossbar-0.2.0/.github/allowed_signers +1 -0
- agent_crossbar-0.2.0/.github/dependabot.yml +19 -0
- agent_crossbar-0.2.0/.github/workflows/ci.yml +186 -0
- agent_crossbar-0.2.0/.github/workflows/live-gate.yml +93 -0
- agent_crossbar-0.2.0/.github/workflows/release.yml +200 -0
- agent_crossbar-0.2.0/.github/workflows/security.yml +89 -0
- agent_crossbar-0.2.0/.gitignore +12 -0
- agent_crossbar-0.2.0/.gitleaks.toml +11 -0
- agent_crossbar-0.2.0/AGENTS.md +43 -0
- agent_crossbar-0.2.0/CHANGELOG.md +40 -0
- agent_crossbar-0.2.0/CODE_OF_CONDUCT.md +50 -0
- agent_crossbar-0.2.0/CONTRIBUTING.md +50 -0
- agent_crossbar-0.2.0/LICENSE +21 -0
- agent_crossbar-0.2.0/PKG-INFO +12 -0
- agent_crossbar-0.2.0/PUBLIC-SNAPSHOT.json +374 -0
- agent_crossbar-0.2.0/README.md +223 -0
- agent_crossbar-0.2.0/SECURITY.md +39 -0
- agent_crossbar-0.2.0/bin/agent-crossbar.mjs +37 -0
- agent_crossbar-0.2.0/demo/PROMPTS.md +25 -0
- agent_crossbar-0.2.0/demo/RECORDING.md +22 -0
- agent_crossbar-0.2.0/demo/TRANSCRIPT.md +18 -0
- agent_crossbar-0.2.0/demo/fixture/crossbar_demo.py +6 -0
- agent_crossbar-0.2.0/demo/metadata.json +10 -0
- agent_crossbar-0.2.0/docs/releases/v0.2.0.md +50 -0
- agent_crossbar-0.2.0/package.json +27 -0
- agent_crossbar-0.2.0/pyproject.toml +55 -0
- agent_crossbar-0.2.0/src/agent_crossbar/__init__.py +1 -0
- agent_crossbar-0.2.0/src/agent_crossbar/acp_client.py +422 -0
- agent_crossbar-0.2.0/src/agent_crossbar/acp_lifecycle.py +240 -0
- agent_crossbar-0.2.0/src/agent_crossbar/acp_runtime.py +389 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/__init__.py +5 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/base.py +89 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/chatgpt_pro.py +20 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/claude.py +510 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/claude_model_probe.py +781 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/codex.py +145 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/opencode.py +253 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/reasonix.py +20 -0
- agent_crossbar-0.2.0/src/agent_crossbar/adapters/registry.py +21 -0
- agent_crossbar-0.2.0/src/agent_crossbar/agent_runner.py +435 -0
- agent_crossbar-0.2.0/src/agent_crossbar/cli.py +109 -0
- agent_crossbar-0.2.0/src/agent_crossbar/context.py +33 -0
- agent_crossbar-0.2.0/src/agent_crossbar/discovery.py +416 -0
- agent_crossbar-0.2.0/src/agent_crossbar/discovery_runner.py +324 -0
- agent_crossbar-0.2.0/src/agent_crossbar/env_compat.py +55 -0
- agent_crossbar-0.2.0/src/agent_crossbar/envelope.py +293 -0
- agent_crossbar-0.2.0/src/agent_crossbar/jobs.py +837 -0
- agent_crossbar-0.2.0/src/agent_crossbar/model_cache.py +204 -0
- agent_crossbar-0.2.0/src/agent_crossbar/models.py +67 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/__init__.py +88 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/chatgpt_pro.py +33 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/claude.py +41 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/codex.py +39 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/opencode.py +49 -0
- agent_crossbar-0.2.0/src/agent_crossbar/profiles/reasonix.py +35 -0
- agent_crossbar-0.2.0/src/agent_crossbar/providers.py +461 -0
- agent_crossbar-0.2.0/src/agent_crossbar/readiness.py +785 -0
- agent_crossbar-0.2.0/src/agent_crossbar/redaction.py +66 -0
- agent_crossbar-0.2.0/src/agent_crossbar/runner.py +2974 -0
- agent_crossbar-0.2.0/src/agent_crossbar/server.py +1156 -0
- agent_crossbar-0.2.0/src/agent_crossbar/shell_server.py +68 -0
- agent_crossbar-0.2.0/src/agent_crossbar/telemetry.py +266 -0
- agent_crossbar-0.2.0/src/agent_crossbar/tmux_output.py +241 -0
- agent_crossbar-0.2.0/src/agent_crossbar/validation.py +276 -0
- agent_crossbar-0.2.0/src/agent_harness_mcp/__init__.py +87 -0
- agent_crossbar-0.2.0/tests/test_acp_agent.py +933 -0
- agent_crossbar-0.2.0/tests/test_acp_client.py +842 -0
- agent_crossbar-0.2.0/tests/test_acp_runtime_direct.py +543 -0
- agent_crossbar-0.2.0/tests/test_capability_validation.py +393 -0
- agent_crossbar-0.2.0/tests/test_claude_adapter.py +364 -0
- agent_crossbar-0.2.0/tests/test_claude_agent_integration.py +1004 -0
- agent_crossbar-0.2.0/tests/test_claude_model_probe.py +1241 -0
- agent_crossbar-0.2.0/tests/test_context.py +40 -0
- agent_crossbar-0.2.0/tests/test_demo_assets.py +26 -0
- agent_crossbar-0.2.0/tests/test_discovery.py +2828 -0
- agent_crossbar-0.2.0/tests/test_envelope.py +483 -0
- agent_crossbar-0.2.0/tests/test_jobs.py +637 -0
- agent_crossbar-0.2.0/tests/test_local_e2e_dev_start.py +410 -0
- agent_crossbar-0.2.0/tests/test_minimal_public_contract.py +526 -0
- agent_crossbar-0.2.0/tests/test_npm_launcher.py +43 -0
- agent_crossbar-0.2.0/tests/test_package_metadata.py +173 -0
- agent_crossbar-0.2.0/tests/test_policy_validation.py +93 -0
- agent_crossbar-0.2.0/tests/test_provider_adapters.py +131 -0
- agent_crossbar-0.2.0/tests/test_provider_surface_gate.py +677 -0
- agent_crossbar-0.2.0/tests/test_providers.py +128 -0
- agent_crossbar-0.2.0/tests/test_readiness.py +1407 -0
- agent_crossbar-0.2.0/tests/test_redaction.py +89 -0
- agent_crossbar-0.2.0/tests/test_runner.py +4034 -0
- agent_crossbar-0.2.0/tests/test_scaffold.py +10 -0
- agent_crossbar-0.2.0/tests/test_server_tools.py +230 -0
- agent_crossbar-0.2.0/tests/test_telemetry.py +256 -0
- agent_crossbar-0.2.0/tests/test_tmux_output.py +343 -0
- agent_crossbar-0.2.0/tests/test_tool_surface_audit.py +132 -0
- agent_crossbar-0.2.0/tests/test_validation.py +313 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
zombopanda@gmail.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBiH4qgbw/sizT5SxcfqYr8BS4T77G2sR/ph85Hwpgpw
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
|
|
9
|
+
- package-ecosystem: "npm"
|
|
10
|
+
directory: "/"
|
|
11
|
+
schedule:
|
|
12
|
+
interval: "weekly"
|
|
13
|
+
open-pull-requests-limit: 3
|
|
14
|
+
|
|
15
|
+
- package-ecosystem: "github-actions"
|
|
16
|
+
directory: "/"
|
|
17
|
+
schedule:
|
|
18
|
+
interval: "weekly"
|
|
19
|
+
open-pull-requests-limit: 3
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
# ── Python test matrix (Ubuntu) ──────────────────────────────────────────
|
|
14
|
+
test-ubuntu:
|
|
15
|
+
name: "py${{ matrix.python }} on ubuntu"
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python: ["3.11", "3.12", "3.13"]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- uses: astral-sh/setup-uv@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python }}
|
|
27
|
+
|
|
28
|
+
- name: Create isolated venv
|
|
29
|
+
run: uv venv --python ${{ matrix.python }} /tmp/ci-venv
|
|
30
|
+
|
|
31
|
+
- name: Install package + test deps
|
|
32
|
+
run: |
|
|
33
|
+
uv pip install --python /tmp/ci-venv/bin/python \
|
|
34
|
+
-e ".[test]"
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: |
|
|
38
|
+
/tmp/ci-venv/bin/python -m pytest tests/ -q \
|
|
39
|
+
--ignore=tests/test_claude_agent_integration.py \
|
|
40
|
+
--ignore=tests/test_acp_agent.py \
|
|
41
|
+
--ignore=tests/test_tmux_output.py \
|
|
42
|
+
--ignore=tests/test_local_e2e_dev_start.py
|
|
43
|
+
|
|
44
|
+
# ── Python test matrix (macOS primary version) ───────────────────────────
|
|
45
|
+
test-macos:
|
|
46
|
+
name: "py${{ matrix.python }} on macos"
|
|
47
|
+
runs-on: macos-latest
|
|
48
|
+
strategy:
|
|
49
|
+
fail-fast: false
|
|
50
|
+
matrix:
|
|
51
|
+
python: ["3.13"]
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- uses: astral-sh/setup-uv@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: ${{ matrix.python }}
|
|
58
|
+
|
|
59
|
+
- name: Create isolated venv
|
|
60
|
+
run: uv venv --python ${{ matrix.python }} /tmp/ci-venv
|
|
61
|
+
|
|
62
|
+
- name: Install package + test deps
|
|
63
|
+
run: |
|
|
64
|
+
uv pip install --python /tmp/ci-venv/bin/python \
|
|
65
|
+
-e ".[test]"
|
|
66
|
+
|
|
67
|
+
- name: Run tests
|
|
68
|
+
run: |
|
|
69
|
+
/tmp/ci-venv/bin/python -m pytest tests/ -q \
|
|
70
|
+
--ignore=tests/test_claude_agent_integration.py \
|
|
71
|
+
--ignore=tests/test_acp_agent.py \
|
|
72
|
+
--ignore=tests/test_tmux_output.py \
|
|
73
|
+
--ignore=tests/test_local_e2e_dev_start.py
|
|
74
|
+
|
|
75
|
+
# ── Lint & type checks ──────────────────────────────────────────────────
|
|
76
|
+
lint:
|
|
77
|
+
name: "lint + format check"
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
|
|
82
|
+
- uses: astral-sh/setup-uv@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: "3.13"
|
|
85
|
+
|
|
86
|
+
- name: Create isolated venv
|
|
87
|
+
run: uv venv --python 3.13 /tmp/ci-venv
|
|
88
|
+
|
|
89
|
+
- name: Install package + test deps
|
|
90
|
+
run: |
|
|
91
|
+
uv pip install --python /tmp/ci-venv/bin/python \
|
|
92
|
+
-e ".[test]"
|
|
93
|
+
|
|
94
|
+
- name: Ruff lint
|
|
95
|
+
run: |
|
|
96
|
+
/tmp/ci-venv/bin/ruff check \
|
|
97
|
+
src/agent_crossbar/ \
|
|
98
|
+
scripts/provider_surface_gate.py \
|
|
99
|
+
tests/test_minimal_public_contract.py \
|
|
100
|
+
tests/test_claude_adapter.py \
|
|
101
|
+
tests/test_provider_surface_gate.py
|
|
102
|
+
|
|
103
|
+
- name: Ruff format check
|
|
104
|
+
run: |
|
|
105
|
+
/tmp/ci-venv/bin/ruff format --check \
|
|
106
|
+
src/agent_crossbar/ \
|
|
107
|
+
scripts/provider_surface_gate.py \
|
|
108
|
+
tests/test_minimal_public_contract.py \
|
|
109
|
+
tests/test_claude_adapter.py \
|
|
110
|
+
tests/test_provider_surface_gate.py
|
|
111
|
+
|
|
112
|
+
# ── Build wheel + sdist ─────────────────────────────────────────────────
|
|
113
|
+
build:
|
|
114
|
+
name: "build wheel + sdist"
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
steps:
|
|
117
|
+
- uses: actions/checkout@v4
|
|
118
|
+
|
|
119
|
+
- uses: astral-sh/setup-uv@v5
|
|
120
|
+
with:
|
|
121
|
+
python-version: "3.13"
|
|
122
|
+
|
|
123
|
+
- name: Build
|
|
124
|
+
run: uv build --out-dir dist
|
|
125
|
+
|
|
126
|
+
- name: Archive artifacts
|
|
127
|
+
uses: actions/upload-artifact@v4
|
|
128
|
+
with:
|
|
129
|
+
name: dist
|
|
130
|
+
path: dist/
|
|
131
|
+
|
|
132
|
+
# ── Install smoke ───────────────────────────────────────────────────────
|
|
133
|
+
install-smoke:
|
|
134
|
+
name: "install smoke"
|
|
135
|
+
needs: build
|
|
136
|
+
runs-on: ubuntu-latest
|
|
137
|
+
steps:
|
|
138
|
+
- uses: actions/checkout@v4
|
|
139
|
+
|
|
140
|
+
- uses: astral-sh/setup-uv@v5
|
|
141
|
+
with:
|
|
142
|
+
python-version: "3.13"
|
|
143
|
+
|
|
144
|
+
- uses: actions/download-artifact@v4
|
|
145
|
+
with:
|
|
146
|
+
name: dist
|
|
147
|
+
path: dist/
|
|
148
|
+
|
|
149
|
+
- name: Install from wheel
|
|
150
|
+
run: |
|
|
151
|
+
uv venv --python 3.13 /tmp/smoke-venv
|
|
152
|
+
uv pip install --python /tmp/smoke-venv/bin/python dist/*.whl
|
|
153
|
+
|
|
154
|
+
- name: "Smoke: CLI help"
|
|
155
|
+
run: /tmp/smoke-venv/bin/agent-crossbar doctor
|
|
156
|
+
|
|
157
|
+
- name: "Smoke: import"
|
|
158
|
+
run: |
|
|
159
|
+
/tmp/smoke-venv/bin/python -c \
|
|
160
|
+
"import agent_crossbar; print(agent_crossbar.__version__)"
|
|
161
|
+
|
|
162
|
+
# ── npm pack + launcher smoke ───────────────────────────────────────────
|
|
163
|
+
npm-smoke:
|
|
164
|
+
name: "npm pack + launcher smoke"
|
|
165
|
+
runs-on: ubuntu-latest
|
|
166
|
+
defaults:
|
|
167
|
+
run:
|
|
168
|
+
working-directory: .
|
|
169
|
+
steps:
|
|
170
|
+
- uses: actions/checkout@v4
|
|
171
|
+
|
|
172
|
+
- uses: actions/setup-node@v4
|
|
173
|
+
with:
|
|
174
|
+
node-version: "20"
|
|
175
|
+
|
|
176
|
+
- name: npm pack
|
|
177
|
+
run: npm pack
|
|
178
|
+
|
|
179
|
+
- name: Verify tarball contents
|
|
180
|
+
run: |
|
|
181
|
+
tar -tzf agent-crossbar-*.tgz | sort
|
|
182
|
+
# Must NOT contain Python source, pyproject, tests, or internal paths
|
|
183
|
+
! tar -tzf agent-crossbar-*.tgz | grep -qE '\.py|pyproject\.toml|\.reasonix|\.memsearch|results/|\.pytest_cache|__pycache__|test'
|
|
184
|
+
|
|
185
|
+
- name: Launcher syntax check
|
|
186
|
+
run: node --check bin/agent-crossbar.mjs
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
name: Live Provider Gate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
profile:
|
|
7
|
+
description: "Provider profile to test"
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
options:
|
|
11
|
+
- codex
|
|
12
|
+
- claude
|
|
13
|
+
- opencode
|
|
14
|
+
- reasonix
|
|
15
|
+
model:
|
|
16
|
+
description: "Model ID (leave empty for profile default)"
|
|
17
|
+
required: false
|
|
18
|
+
type: string
|
|
19
|
+
effort:
|
|
20
|
+
description: "Effort level (supported by any provider that accepts effort)"
|
|
21
|
+
required: false
|
|
22
|
+
type: string
|
|
23
|
+
task:
|
|
24
|
+
description: "Task to test"
|
|
25
|
+
required: true
|
|
26
|
+
type: choice
|
|
27
|
+
options:
|
|
28
|
+
- ask
|
|
29
|
+
- review
|
|
30
|
+
- dev
|
|
31
|
+
interactive:
|
|
32
|
+
description: "Test interactive mode"
|
|
33
|
+
required: false
|
|
34
|
+
type: boolean
|
|
35
|
+
default: false
|
|
36
|
+
max_runtime_sec:
|
|
37
|
+
description: "Max runtime seconds"
|
|
38
|
+
required: false
|
|
39
|
+
type: string
|
|
40
|
+
default: "600"
|
|
41
|
+
|
|
42
|
+
permissions:
|
|
43
|
+
contents: read
|
|
44
|
+
|
|
45
|
+
jobs:
|
|
46
|
+
live-gate:
|
|
47
|
+
name: "live gate: ${{ inputs.profile }} ${{ inputs.task }}"
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
environment: live-gates
|
|
50
|
+
timeout-minutes: 30
|
|
51
|
+
|
|
52
|
+
# Never run on forks — requires maintainer credentials
|
|
53
|
+
if: github.repository == 'zombopanda/agent-crossbar'
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- uses: astral-sh/setup-uv@v5
|
|
59
|
+
with:
|
|
60
|
+
python-version: "3.13"
|
|
61
|
+
|
|
62
|
+
- name: Create isolated venv
|
|
63
|
+
run: uv venv --python 3.13 /tmp/ci-venv
|
|
64
|
+
|
|
65
|
+
- name: Install package + test deps
|
|
66
|
+
run: |
|
|
67
|
+
uv pip install --python /tmp/ci-venv/bin/python \
|
|
68
|
+
-e ".[test]"
|
|
69
|
+
|
|
70
|
+
- name: Provider surface gate
|
|
71
|
+
env:
|
|
72
|
+
PROFILE: ${{ inputs.profile }}
|
|
73
|
+
TASK: ${{ inputs.task }}
|
|
74
|
+
INTERACTIVE: ${{ inputs.interactive }}
|
|
75
|
+
MODEL: ${{ inputs.model }}
|
|
76
|
+
EFFORT: ${{ inputs.effort }}
|
|
77
|
+
MAX_RUNTIME_SEC: ${{ inputs.max_runtime_sec }}
|
|
78
|
+
run: |
|
|
79
|
+
MODEL_ARG=""
|
|
80
|
+
if [ -n "${MODEL}" ]; then
|
|
81
|
+
MODEL_ARG="--model ${MODEL}"
|
|
82
|
+
fi
|
|
83
|
+
EFFORT_ARG=""
|
|
84
|
+
if [ -n "${EFFORT}" ]; then
|
|
85
|
+
EFFORT_ARG="--effort ${EFFORT}"
|
|
86
|
+
fi
|
|
87
|
+
/tmp/ci-venv/bin/python scripts/provider_surface_gate.py \
|
|
88
|
+
--profile "${PROFILE}" \
|
|
89
|
+
${MODEL_ARG} \
|
|
90
|
+
${EFFORT_ARG} \
|
|
91
|
+
--task "${TASK}" \
|
|
92
|
+
--interactive "${INTERACTIVE}" \
|
|
93
|
+
--max-runtime-sec "${MAX_RUNTIME_SEC:-600}"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
attestations: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
# ── Build & audit ───────────────────────────────────────────────────────
|
|
15
|
+
build:
|
|
16
|
+
name: "build + audit"
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
id-token: write
|
|
21
|
+
attestations: write
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
|
|
27
|
+
- name: Verify signed release tag
|
|
28
|
+
run: |
|
|
29
|
+
git fetch --force origin \
|
|
30
|
+
"refs/tags/${GITHUB_REF_NAME}:refs/tags/${GITHUB_REF_NAME}"
|
|
31
|
+
git config gpg.format ssh
|
|
32
|
+
git config gpg.ssh.allowedSignersFile \
|
|
33
|
+
"${GITHUB_WORKSPACE}/.github/allowed_signers"
|
|
34
|
+
git verify-tag "${GITHUB_REF_NAME}"
|
|
35
|
+
|
|
36
|
+
- uses: astral-sh/setup-uv@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.13"
|
|
39
|
+
|
|
40
|
+
- name: Verify tag matches package versions
|
|
41
|
+
shell: bash
|
|
42
|
+
run: |
|
|
43
|
+
release_version="${GITHUB_REF_NAME#v}"
|
|
44
|
+
python - "${release_version}" <<'PY'
|
|
45
|
+
import json
|
|
46
|
+
import sys
|
|
47
|
+
import tomllib
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
|
|
50
|
+
package_root = Path(".")
|
|
51
|
+
tag_version = sys.argv[1]
|
|
52
|
+
python_version = tomllib.loads(
|
|
53
|
+
(package_root / "pyproject.toml").read_text()
|
|
54
|
+
)["project"]["version"]
|
|
55
|
+
npm_version = json.loads(
|
|
56
|
+
(package_root / "package.json").read_text()
|
|
57
|
+
)["version"]
|
|
58
|
+
if not tag_version == python_version == npm_version:
|
|
59
|
+
raise SystemExit(
|
|
60
|
+
"tag version does not match package versions: "
|
|
61
|
+
f"tag={tag_version}, python={python_version}, npm={npm_version}"
|
|
62
|
+
)
|
|
63
|
+
PY
|
|
64
|
+
|
|
65
|
+
- name: Build
|
|
66
|
+
run: uv build --out-dir dist
|
|
67
|
+
|
|
68
|
+
- name: Audit wheel
|
|
69
|
+
run: |
|
|
70
|
+
! unzip -l dist/*.whl | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff'
|
|
71
|
+
|
|
72
|
+
- name: Audit sdist
|
|
73
|
+
run: |
|
|
74
|
+
! tar -tzf dist/*.tar.gz | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff'
|
|
75
|
+
|
|
76
|
+
- name: Install smoke
|
|
77
|
+
run: |
|
|
78
|
+
uv venv --python 3.13 /tmp/smoke-venv
|
|
79
|
+
uv pip install --python /tmp/smoke-venv/bin/python dist/*.whl
|
|
80
|
+
/tmp/smoke-venv/bin/agent-crossbar doctor
|
|
81
|
+
/tmp/smoke-venv/bin/python -c \
|
|
82
|
+
"import agent_crossbar; print(agent_crossbar.__version__)"
|
|
83
|
+
|
|
84
|
+
- name: Attest distributions
|
|
85
|
+
uses: actions/attest-build-provenance@v3
|
|
86
|
+
with:
|
|
87
|
+
subject-path: dist/*
|
|
88
|
+
|
|
89
|
+
- uses: actions/upload-artifact@v4
|
|
90
|
+
with:
|
|
91
|
+
name: dist
|
|
92
|
+
path: dist/
|
|
93
|
+
|
|
94
|
+
# ── PyPI trusted publishing ─────────────────────────────────────────────
|
|
95
|
+
pypi-publish:
|
|
96
|
+
name: "publish to PyPI"
|
|
97
|
+
needs: build
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
environment:
|
|
100
|
+
name: pypi
|
|
101
|
+
url: https://pypi.org/p/agent-crossbar
|
|
102
|
+
permissions:
|
|
103
|
+
id-token: write
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/download-artifact@v4
|
|
106
|
+
with:
|
|
107
|
+
name: dist
|
|
108
|
+
path: dist/
|
|
109
|
+
|
|
110
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
111
|
+
with:
|
|
112
|
+
attestations: true
|
|
113
|
+
|
|
114
|
+
# ── Smoke the artifact PyPI actually serves ────────────────────────────
|
|
115
|
+
pypi-smoke:
|
|
116
|
+
name: "smoke published PyPI artifact"
|
|
117
|
+
needs: pypi-publish
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
steps:
|
|
120
|
+
- uses: astral-sh/setup-uv@v5
|
|
121
|
+
|
|
122
|
+
- name: Install and start published version
|
|
123
|
+
shell: bash
|
|
124
|
+
run: |
|
|
125
|
+
version="${GITHUB_REF_NAME#v}"
|
|
126
|
+
for attempt in {1..12}; do
|
|
127
|
+
if uvx --refresh --from "agent-crossbar==${version}" agent-crossbar doctor; then
|
|
128
|
+
exit 0
|
|
129
|
+
fi
|
|
130
|
+
if [[ "${attempt}" -eq 12 ]]; then
|
|
131
|
+
echo "PyPI artifact was not installable after propagation window" >&2
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
sleep 10
|
|
135
|
+
done
|
|
136
|
+
|
|
137
|
+
# ── npm publish (post-PyPI) ─────────────────────────────────────────────
|
|
138
|
+
npm-publish:
|
|
139
|
+
name: "publish to npm"
|
|
140
|
+
needs: pypi-smoke
|
|
141
|
+
runs-on: ubuntu-latest
|
|
142
|
+
environment:
|
|
143
|
+
name: npm
|
|
144
|
+
url: https://www.npmjs.com/package/agent-crossbar
|
|
145
|
+
permissions:
|
|
146
|
+
contents: read
|
|
147
|
+
id-token: write
|
|
148
|
+
defaults:
|
|
149
|
+
run:
|
|
150
|
+
working-directory: .
|
|
151
|
+
steps:
|
|
152
|
+
- uses: actions/checkout@v4
|
|
153
|
+
|
|
154
|
+
- uses: actions/setup-node@v4
|
|
155
|
+
with:
|
|
156
|
+
node-version: "24"
|
|
157
|
+
registry-url: "https://registry.npmjs.org"
|
|
158
|
+
|
|
159
|
+
- name: Update npm for trusted publishing
|
|
160
|
+
run: npm install --global npm@latest
|
|
161
|
+
|
|
162
|
+
- name: npm pack + verify
|
|
163
|
+
run: |
|
|
164
|
+
npm pack
|
|
165
|
+
! tar -tzf agent-crossbar-*.tgz | grep -qE '\.reasonix|\.memsearch|results/|__pycache__'
|
|
166
|
+
|
|
167
|
+
- name: npm publish
|
|
168
|
+
shell: bash
|
|
169
|
+
run: |
|
|
170
|
+
version="$(node -p 'require("./package.json").version')"
|
|
171
|
+
if npm view "agent-crossbar@${version}" version >/dev/null 2>&1; then
|
|
172
|
+
echo "agent-crossbar@${version} is already published; skipping"
|
|
173
|
+
exit 0
|
|
174
|
+
fi
|
|
175
|
+
npm publish --access public
|
|
176
|
+
|
|
177
|
+
# ── GitHub release (only after both registries are healthy) ────────────
|
|
178
|
+
github-release:
|
|
179
|
+
name: "create GitHub release"
|
|
180
|
+
needs: npm-publish
|
|
181
|
+
runs-on: ubuntu-latest
|
|
182
|
+
permissions:
|
|
183
|
+
contents: write
|
|
184
|
+
steps:
|
|
185
|
+
- uses: actions/checkout@v4
|
|
186
|
+
|
|
187
|
+
- uses: actions/download-artifact@v4
|
|
188
|
+
with:
|
|
189
|
+
name: dist
|
|
190
|
+
path: dist/
|
|
191
|
+
|
|
192
|
+
- name: Create release with verified artifacts
|
|
193
|
+
env:
|
|
194
|
+
GH_TOKEN: ${{ github.token }}
|
|
195
|
+
run: |
|
|
196
|
+
gh release create "${GITHUB_REF_NAME}" \
|
|
197
|
+
--verify-tag \
|
|
198
|
+
--title "Agent Crossbar ${GITHUB_REF_NAME}" \
|
|
199
|
+
--notes-file "docs/releases/v0.2.0.md" \
|
|
200
|
+
dist/*
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 8 * * 1" # every Monday
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
security-events: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
# ── Secret scanning ─────────────────────────────────────────────────────
|
|
17
|
+
secret-scan:
|
|
18
|
+
name: "secret scan"
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: gitleaks/gitleaks-action@v2
|
|
23
|
+
|
|
24
|
+
# ── Dependency audit ────────────────────────────────────────────────────
|
|
25
|
+
dependency-audit:
|
|
26
|
+
name: "dependency audit"
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
- uses: astral-sh/setup-uv@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.13"
|
|
33
|
+
|
|
34
|
+
- name: Create isolated venv
|
|
35
|
+
run: uv venv --python 3.13 /tmp/ci-venv
|
|
36
|
+
|
|
37
|
+
- name: Install package + test deps
|
|
38
|
+
run: |
|
|
39
|
+
uv pip install --python /tmp/ci-venv/bin/python \
|
|
40
|
+
-e ".[test]"
|
|
41
|
+
|
|
42
|
+
- name: pip-audit
|
|
43
|
+
run: /tmp/ci-venv/bin/pip-audit
|
|
44
|
+
|
|
45
|
+
# ── CodeQL ──────────────────────────────────────────────────────────────
|
|
46
|
+
codeql:
|
|
47
|
+
name: "CodeQL"
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
permissions:
|
|
50
|
+
contents: read
|
|
51
|
+
security-events: write
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- uses: github/codeql-action/init@v3
|
|
56
|
+
with:
|
|
57
|
+
languages: python, javascript
|
|
58
|
+
|
|
59
|
+
- uses: github/codeql-action/analyze@v3
|
|
60
|
+
|
|
61
|
+
# ── Artifact allowlist check ────────────────────────────────────────────
|
|
62
|
+
artifact-audit:
|
|
63
|
+
name: "artifact audit"
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
|
|
68
|
+
- uses: astral-sh/setup-uv@v5
|
|
69
|
+
with:
|
|
70
|
+
python-version: "3.13"
|
|
71
|
+
|
|
72
|
+
- name: Build artifacts
|
|
73
|
+
run: uv build --out-dir dist
|
|
74
|
+
|
|
75
|
+
- name: Audit wheel contents
|
|
76
|
+
run: |
|
|
77
|
+
echo "=== Wheel contents ==="
|
|
78
|
+
unzip -l dist/*.whl | grep -vE '\.pyc$|__pycache__'
|
|
79
|
+
echo ""
|
|
80
|
+
echo "=== Checking for prohibited paths ==="
|
|
81
|
+
! unzip -l dist/*.whl | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff|\.pytest_cache|\.DS_Store'
|
|
82
|
+
|
|
83
|
+
- name: Audit sdist contents
|
|
84
|
+
run: |
|
|
85
|
+
echo "=== Sdist contents ==="
|
|
86
|
+
tar -tzf dist/*.tar.gz | grep -vE '\.pyc$|__pycache__'
|
|
87
|
+
echo ""
|
|
88
|
+
echo "=== Checking for prohibited paths ==="
|
|
89
|
+
! tar -tzf dist/*.tar.gz | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff|\.pytest_cache|\.DS_Store'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Gitleaks configuration for Agent Crossbar
|
|
2
|
+
# Excludes known non-secret patterns and false positives from the codebase.
|
|
3
|
+
|
|
4
|
+
title = "Agent Crossbar gitleaks config"
|
|
5
|
+
|
|
6
|
+
[allowlist]
|
|
7
|
+
description = "Global allowlist"
|
|
8
|
+
paths = [
|
|
9
|
+
'''uv\.lock''',
|
|
10
|
+
'''\.gitleaks\.toml''',
|
|
11
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Agent Crossbar — Contributor Code Rules
|
|
2
|
+
|
|
3
|
+
These rules apply to code contributions. They are intentionally concise and focused on the public contract.
|
|
4
|
+
|
|
5
|
+
## Public Contract (Provider-Neutral)
|
|
6
|
+
|
|
7
|
+
1. **No top-level provider-specific fields.** The public API (`agent_start`, `job_result`, tool schemas) MUST NOT expose fields that only apply to a single provider. Provider-specific metadata lives in per-profile capability entries.
|
|
8
|
+
|
|
9
|
+
2. **The 8-tool MCP surface is locked.** Adding or removing a tool requires a design discussion and version bump. No hidden tools. No deprecated aliases.
|
|
10
|
+
|
|
11
|
+
3. **Stable error codes.** Error codes documented in the README troubleshooting table MUST NOT change semantics in a patch version. New codes may be added in minor versions.
|
|
12
|
+
|
|
13
|
+
4. **`agent_start` schema is provider-neutral and minimal.** The only public fields are: `profile`, `prompt`, `task`, `interactive`, `model`, `effort`, `cwd`, `scope`, `max_runtime_sec`, plus standard client metadata (`client`, `client_name`, `client_version`, `client_session_id`). No transport enum, no provider-specific routing hints.
|
|
14
|
+
|
|
15
|
+
5. **`interactive` is a boolean.** The public schema exposes `interactive` as a single boolean. No transport enum, no public transport field. Transport selection is an internal adapter concern.
|
|
16
|
+
|
|
17
|
+
6. **Forbidden (dead) public fields.** The following fields MUST NOT appear in the `agent_start` signature or any shipped schema: `external_context`, `budget_usd`, `text_subtype`, `review_target`, `context_target`, `full_local`. No compatibility shims, no deprecated aliases for these.
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
7. **Per-profile adapter modules.** Each provider gets one bounded module under `agent_crossbar/adapters/` implementing `ProviderAdapter` from `base.py`. Adapter modules MUST NOT import from each other.
|
|
22
|
+
|
|
23
|
+
8. **Core modules are provider-agnostic.** `server.py`, `jobs.py`, `validation.py`, `envelope.py`, `readiness.py` MUST NOT contain provider-specific branching. Provider behavior is injected through adapter lookups.
|
|
24
|
+
|
|
25
|
+
9. **Per-profile capabilities/models live in separate profile modules.** Each profile under `agent_crossbar/profiles/` owns its capabilities, models, and default configuration. Model lists MUST come from CLI discovery (`discovery.py`), not hardcoded. Profile modules MUST NOT import from each other.
|
|
26
|
+
|
|
27
|
+
10. **No compatibility aliases for removed fields.** Removed fields (`transport`, `autonomy`, `sensitivity`, `sanitized_context_only`, `timeout_sec`, etc.) MUST NOT have runtime compatibility shims, aliases, or warning-based remapping. They are simply absent.
|
|
28
|
+
|
|
29
|
+
11. **Readiness probes are non-mutating and cached.** Probes inspect state, never change it. Results cache for 60 seconds. Registration alone never produces `ready`.
|
|
30
|
+
|
|
31
|
+
## Testing
|
|
32
|
+
|
|
33
|
+
12. **TDD for provider changes.** Any new provider adapter, capability, or transport MUST include:
|
|
34
|
+
- Unit tests proving validation, schema conformance, and error paths (no live provider).
|
|
35
|
+
- A passing live provider gate (maintainer-only workflow) on every claimed operation/transport combination.
|
|
36
|
+
|
|
37
|
+
13. **No fake capabilities or models.** Model lists and capability declarations MUST come from live provider discovery or documentation references. Do not invent capabilities.
|
|
38
|
+
|
|
39
|
+
14. **Deterministic CI.** All tests in public PR CI MUST pass without provider credentials. Provider-dependent tests use `pytest.skip` when credentials are absent.
|
|
40
|
+
|
|
41
|
+
## Package Hygiene
|
|
42
|
+
|
|
43
|
+
15. **Public artifacts exclude internal content.** Benchmark results, `.reasonix/`, `.memsearch/`, personal paths, private URLs, and handoff files MUST NOT appear in wheel/sdist/npm tarball.
|