beadhub 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. beadhub/__init__.py +12 -0
  2. beadhub/api.py +260 -0
  3. beadhub/auth.py +101 -0
  4. beadhub/aweb_context.py +65 -0
  5. beadhub/aweb_introspection.py +70 -0
  6. beadhub/beads_sync.py +514 -0
  7. beadhub/cli.py +330 -0
  8. beadhub/config.py +65 -0
  9. beadhub/db.py +129 -0
  10. beadhub/defaults/invariants/01-tracking-bdh-only.md +11 -0
  11. beadhub/defaults/invariants/02-communication-mail-first.md +36 -0
  12. beadhub/defaults/invariants/03-communication-chat.md +60 -0
  13. beadhub/defaults/invariants/04-identity-no-impersonation.md +17 -0
  14. beadhub/defaults/invariants/05-collaborate.md +12 -0
  15. beadhub/defaults/roles/backend.md +55 -0
  16. beadhub/defaults/roles/coordinator.md +44 -0
  17. beadhub/defaults/roles/frontend.md +77 -0
  18. beadhub/defaults/roles/implementer.md +73 -0
  19. beadhub/defaults/roles/reviewer.md +56 -0
  20. beadhub/defaults/roles/startup-expert.md +93 -0
  21. beadhub/defaults.py +262 -0
  22. beadhub/events.py +704 -0
  23. beadhub/internal_auth.py +121 -0
  24. beadhub/jsonl.py +68 -0
  25. beadhub/logging.py +62 -0
  26. beadhub/migrations/beads/001_initial.sql +70 -0
  27. beadhub/migrations/beads/002_search_indexes.sql +20 -0
  28. beadhub/migrations/server/001_initial.sql +279 -0
  29. beadhub/names.py +33 -0
  30. beadhub/notifications.py +275 -0
  31. beadhub/pagination.py +125 -0
  32. beadhub/presence.py +495 -0
  33. beadhub/rate_limit.py +152 -0
  34. beadhub/redis_client.py +11 -0
  35. beadhub/roles.py +35 -0
  36. beadhub/routes/__init__.py +1 -0
  37. beadhub/routes/agents.py +303 -0
  38. beadhub/routes/bdh.py +655 -0
  39. beadhub/routes/beads.py +778 -0
  40. beadhub/routes/claims.py +141 -0
  41. beadhub/routes/escalations.py +471 -0
  42. beadhub/routes/init.py +348 -0
  43. beadhub/routes/mcp.py +338 -0
  44. beadhub/routes/policies.py +833 -0
  45. beadhub/routes/repos.py +538 -0
  46. beadhub/routes/status.py +568 -0
  47. beadhub/routes/subscriptions.py +362 -0
  48. beadhub/routes/workspaces.py +1642 -0
  49. beadhub/workspace_config.py +202 -0
  50. beadhub-0.1.0.dist-info/METADATA +254 -0
  51. beadhub-0.1.0.dist-info/RECORD +54 -0
  52. beadhub-0.1.0.dist-info/WHEEL +4 -0
  53. beadhub-0.1.0.dist-info/entry_points.txt +2 -0
  54. beadhub-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,202 @@
1
+ """Workspace configuration reading from .beadhub files."""
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+ MAX_CONFIG_SIZE = 4096 # 4KB max for .beadhub file
7
+
8
+
9
+ @dataclass
10
+ class WorkspaceConfig:
11
+ """Configuration loaded from a .beadhub file."""
12
+
13
+ workspace_id: str | None = None
14
+ beadhub_url: str | None = None
15
+ alias: str | None = None
16
+ human_name: str | None = None
17
+ project_slug: str | None = None
18
+ repo_origin: str | None = None
19
+
20
+
21
+ def _strip_quotes(value: str) -> str:
22
+ """Strip matching quotes from a value string.
23
+
24
+ Only removes quotes if they match (both single or both double).
25
+ """
26
+ value = value.strip()
27
+ if len(value) >= 2:
28
+ if (value.startswith('"') and value.endswith('"')) or (
29
+ value.startswith("'") and value.endswith("'")
30
+ ):
31
+ return value[1:-1]
32
+ return value
33
+
34
+
35
+ def _parse_beadhub_file(content: str) -> dict[str, str]:
36
+ """Parse simple YAML-like .beadhub config file.
37
+
38
+ Format:
39
+ # comments are ignored
40
+ key: "value" # quoted values
41
+ key: value # unquoted values
42
+
43
+ Note: This is NOT a full YAML parser. It only supports simple key: value lines.
44
+ """
45
+ config: dict[str, str] = {}
46
+ for line in content.splitlines():
47
+ line = line.strip()
48
+ if not line or line.startswith("#"):
49
+ continue
50
+ if ":" in line:
51
+ key, value = line.split(":", 1)
52
+ key = key.strip()
53
+ if not key:
54
+ continue
55
+ value = _strip_quotes(value)
56
+ if value:
57
+ config[key] = value
58
+ return config
59
+
60
+
61
+ def load_workspace_config(path: Path | None = None) -> WorkspaceConfig | None:
62
+ """Load workspace configuration from .beadhub file.
63
+
64
+ Args:
65
+ path: Directory containing .beadhub file. Defaults to current directory.
66
+ Security note: Caller must ensure this path is trusted.
67
+
68
+ Returns:
69
+ WorkspaceConfig if file exists, None if file doesn't exist.
70
+
71
+ Raises:
72
+ ValueError: If file is too large or unreadable.
73
+ """
74
+ if path is None:
75
+ path = Path.cwd()
76
+
77
+ config_file = path / ".beadhub"
78
+ if not config_file.exists():
79
+ return None
80
+
81
+ try:
82
+ file_size = config_file.stat().st_size
83
+ if file_size > MAX_CONFIG_SIZE:
84
+ raise ValueError(f".beadhub file too large ({file_size} bytes, max {MAX_CONFIG_SIZE})")
85
+ content = config_file.read_text(encoding="utf-8")
86
+ except PermissionError:
87
+ raise ValueError(f"Cannot read {config_file}: Permission denied")
88
+ except UnicodeDecodeError:
89
+ raise ValueError(f"{config_file} is not valid UTF-8 text")
90
+ except OSError as e:
91
+ raise ValueError(f"Error reading {config_file}: {e}")
92
+
93
+ parsed = _parse_beadhub_file(content)
94
+
95
+ return WorkspaceConfig(
96
+ workspace_id=parsed.get("workspace_id"),
97
+ beadhub_url=parsed.get("beadhub_url"),
98
+ alias=parsed.get("alias"),
99
+ human_name=parsed.get("human_name"),
100
+ project_slug=parsed.get("project_slug"),
101
+ repo_origin=parsed.get("repo_origin"),
102
+ )
103
+
104
+
105
+ def get_workspace_id(override: str | None = None, path: Path | None = None) -> str | None:
106
+ """Get workspace_id, preferring explicit override over file.
107
+
108
+ Args:
109
+ override: Explicit workspace_id (takes precedence).
110
+ path: Directory containing .beadhub file.
111
+
112
+ Returns:
113
+ workspace_id or None if not available.
114
+ """
115
+ if override:
116
+ return override
117
+
118
+ config = load_workspace_config(path)
119
+ if config:
120
+ return config.workspace_id
121
+
122
+ return None
123
+
124
+
125
+ def get_project_slug(override: str | None = None, path: Path | None = None) -> str | None:
126
+ """Get project_slug, preferring explicit override over file.
127
+
128
+ Args:
129
+ override: Explicit project_slug (takes precedence).
130
+ path: Directory containing .beadhub file.
131
+
132
+ Returns:
133
+ project_slug or None if not available.
134
+ """
135
+ if override:
136
+ return override
137
+
138
+ config = load_workspace_config(path)
139
+ if config:
140
+ return config.project_slug
141
+
142
+ return None
143
+
144
+
145
+ def get_human_name(override: str | None = None, path: Path | None = None) -> str | None:
146
+ """Get human_name, preferring explicit override over file.
147
+
148
+ Args:
149
+ override: Explicit human_name (takes precedence).
150
+ path: Directory containing .beadhub file.
151
+
152
+ Returns:
153
+ human_name or None if not available.
154
+ """
155
+ if override:
156
+ return override
157
+
158
+ config = load_workspace_config(path)
159
+ if config:
160
+ return config.human_name
161
+
162
+ return None
163
+
164
+
165
+ def get_alias(override: str | None = None, path: Path | None = None) -> str | None:
166
+ """Get alias, preferring explicit override over file.
167
+
168
+ Args:
169
+ override: Explicit alias (takes precedence).
170
+ path: Directory containing .beadhub file.
171
+
172
+ Returns:
173
+ alias or None if not available.
174
+ """
175
+ if override:
176
+ return override
177
+
178
+ config = load_workspace_config(path)
179
+ if config:
180
+ return config.alias
181
+
182
+ return None
183
+
184
+
185
+ def get_repo_origin(override: str | None = None, path: Path | None = None) -> str | None:
186
+ """Get repo_origin, preferring explicit override over file.
187
+
188
+ Args:
189
+ override: Explicit repo_origin (takes precedence).
190
+ path: Directory containing .beadhub file.
191
+
192
+ Returns:
193
+ repo_origin or None if not available.
194
+ """
195
+ if override:
196
+ return override
197
+
198
+ config = load_workspace_config(path)
199
+ if config:
200
+ return config.repo_origin
201
+
202
+ return None
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: beadhub
3
+ Version: 0.1.0
4
+ Summary: Real-time coordination layer for AI agent teams. File locking, messaging, escalations, and Beads integration.
5
+ Project-URL: Homepage, https://github.com/beadhub/beadhub
6
+ Project-URL: Documentation, https://github.com/beadhub/beadhub#readme
7
+ Project-URL: Repository, https://github.com/beadhub/beadhub.git
8
+ Project-URL: Issues, https://github.com/beadhub/beadhub/issues
9
+ Author-email: Juan Reyero <juan@juanreyero.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,beads,coordination,file-locking,mcp
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Framework :: FastAPI
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: aiofiles>=25.1.0
23
+ Requires-Dist: aweb>=0.1.0
24
+ Requires-Dist: bcrypt>=5.0.0
25
+ Requires-Dist: email-validator>=2.3.0
26
+ Requires-Dist: fastapi>=0.93.0
27
+ Requires-Dist: httpx>=0.23.0
28
+ Requires-Dist: pgdbm>=0.4.0
29
+ Requires-Dist: pyyaml>=6.0.3
30
+ Requires-Dist: redis>=4.2.0
31
+ Requires-Dist: typer>=0.6.0
32
+ Requires-Dist: uvicorn>=0.20.0
33
+ Description-Content-Type: text/markdown
34
+
35
+ # BeadHub
36
+
37
+ Real-time coordination for AI agent teams.
38
+
39
+ ## The Problem
40
+
41
+ When multiple AI agents work on a shared codebase, they collide. Two agents claim the same issue. Both edit the same file. Merge conflicts pile up. And you become the dispatcher—relaying messages between agents via Slack.
42
+
43
+ BeadHub lets agents coordinate themselves. They claim work, reserve files, and message each other directly—escalating to humans only when they're genuinely stuck.
44
+
45
+ **BeadHub is to [Beads](https://github.com/steveyegge/beads) what GitHub is to Git**: collaboration infrastructure for a powerful local-first tool.
46
+
47
+ ## Quick Start
48
+
49
+ Prerequisites:
50
+ - Docker
51
+ - [Beads](https://github.com/steveyegge/beads) (`bd` CLI) for issue tracking
52
+ - A git repository with a remote origin configured
53
+
54
+ ```bash
55
+ # Start the BeadHub server
56
+ git clone https://github.com/beadhub/beadhub.git
57
+ cd beadhub
58
+ make start # or: POSTGRES_PASSWORD=demo docker compose up -d
59
+
60
+ # Install the bdh CLI
61
+ curl -fsSL https://raw.githubusercontent.com/beadhub/bdh/main/install.sh | bash
62
+
63
+ # Initialize a workspace (must be a git repo with remote origin)
64
+ cd /path/to/your-repo
65
+ bdh :init --project demo
66
+
67
+ # Open the dashboard (auto-authenticates using your project API key)
68
+ bdh :dashboard
69
+ ```
70
+
71
+ Dashboard:
72
+ - Open and auto-authenticate: `bdh :dashboard`
73
+ - If you need to paste a key manually, use the `api_key` from `~/.config/aw/config.yaml` (the account selected by `.aw/context`)
74
+
75
+ ## See It In Action
76
+
77
+ Here's what multi-agent coordination looks like. You have three agents: a coordinator and two implementers.
78
+
79
+ > **Note**: The examples below use `bdh update` and `bdh close` which require [Beads](https://github.com/steveyegge/beads) for issue tracking. Install beads first, then run `bd init` in your repo.
80
+
81
+ ### 1. Agents come online
82
+
83
+ **coord-main** runs `bdh :aweb who` to see who's online:
84
+
85
+ ```
86
+ Project: <project_id>
87
+
88
+ ONLINE
89
+ bob-backend (agent) — active
90
+ alice-frontend (agent) — active
91
+ ```
92
+
93
+ ### 2. Coordinator assigns work via chat
94
+
95
+ **coord-main** runs `bdh :aweb chat send bob "Can you handle the API endpoints?" --wait 300`:
96
+
97
+ ```
98
+ Sent chat to bob (session_id=...)
99
+ ```
100
+
101
+ Bob is idle. **You** tell bob to check chat.
102
+
103
+ **bob-backend** runs `bdh :aweb chat pending`:
104
+
105
+ ```
106
+ CHATS: 1 unread conversation(s)
107
+
108
+ - coord-main (unread: 1)
109
+ ```
110
+
111
+ **bob-backend** runs `bdh :aweb chat send coord-main "Got it, I'll take the API work"`:
112
+
113
+ ```
114
+ coord-main: Can you handle the API endpoints?
115
+ ```
116
+
117
+ The coordinator sees the response and does the same with alice for UI work.
118
+
119
+ ### 3. Agents claim and complete work
120
+
121
+ **bob-backend** runs `bdh update bd-12 --status in_progress` to claim his issue.
122
+
123
+ If bob tries to claim something alice already has:
124
+
125
+ **bob-backend** runs `bdh update bd-15 --status in_progress`:
126
+
127
+ ```
128
+ REJECTED: bd-15 is being worked on by alice-frontend (juan)
129
+
130
+ Options:
131
+ - Pick different work: bdh ready
132
+ - Message them: bdh :aweb mail send alice-frontend "message"
133
+ - Escalate: bdh :escalate "subject" "situation"
134
+ ```
135
+
136
+ No collision. No confusion. Agents resolve conflicts directly.
137
+
138
+ ## Adding More Agents
139
+
140
+ Each agent needs its own worktree with its own identity:
141
+
142
+ ```bash
143
+ bdh :add-worktree backend
144
+ ```
145
+
146
+ Or do it manually:
147
+
148
+ ```bash
149
+ git worktree add ../myproject-bob-backend -b bob-backend
150
+ cd ../myproject-bob-backend
151
+ bdh :init --project demo --alias bob-backend --human "$USER"
152
+ ```
153
+
154
+ ## Commands
155
+
156
+ ### Status and visibility
157
+
158
+ ```bash
159
+ bdh :aweb whoami # Your aweb identity (project/agent)
160
+ bdh :aweb who # Who's online?
161
+ bdh ready # Find available work
162
+ bdh :aweb locks # See active locks
163
+ ```
164
+
165
+ ### Issue workflow
166
+
167
+ ```bash
168
+ bdh ready # Find available work
169
+ bdh update bd-42 --status in_progress # Claim an issue
170
+ bdh close bd-42 # Complete work
171
+ ```
172
+
173
+ ### Chat (synchronous)
174
+
175
+ Use chat when you need an answer to proceed. The sender waits.
176
+
177
+ ```bash
178
+ bdh :aweb chat send alice "Quick question..." --wait 300 # Send, wait up to 5 min
179
+ bdh :aweb chat pending # Check pending chats
180
+ bdh :aweb chat send alice "Here's the answer" # Reply
181
+ ```
182
+
183
+ ### Mail (async)
184
+
185
+ Use mail for status updates, handoffs, FYIs—anything that doesn't need an immediate response.
186
+
187
+ ```bash
188
+ bdh :aweb mail send alice "Login bug fixed. Changed session handling."
189
+ bdh :aweb mail list # Check messages
190
+ bdh :aweb mail open alice # Read + acknowledge from specific sender
191
+ ```
192
+
193
+ ### Escalation
194
+
195
+ When agents can't resolve something themselves:
196
+
197
+ ```bash
198
+ bdh :escalate "Need human decision" "Alice and I both need to modify auth.py..."
199
+ ```
200
+
201
+ ## File Reservations
202
+
203
+ bdh automatically reserves files you modify—no commands needed. Reservations are advisory (warn but don't block) and short-lived (5 minutes, auto-renewed while you work).
204
+
205
+ When an agent runs `bdh :aweb locks`:
206
+
207
+ ```
208
+ ## Other Agents' Reservations
209
+ Do not edit these files:
210
+ - `src/auth.py` — bob-backend (expires in 4m30s) "auto-reserve"
211
+ - `src/api.py` — alice-frontend (expires in 3m15s) "auto-reserve"
212
+ ```
213
+
214
+ ## Architecture
215
+
216
+ ```
217
+ ┌─────────────────────────────────────────────────────────────┐
218
+ │ BeadHub Server │
219
+ │ Claims · Reservations · Presence · Messages · Beads Sync │
220
+ ├─────────────────────────────────────────────────────────────┤
221
+ │ PostgreSQL Redis │
222
+ │ (claims, issues) (presence, messages) │
223
+ └─────────────────────────────────────────────────────────────┘
224
+ ▲ ▲ ▲
225
+ │ │ │
226
+ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
227
+ │ Agent │ │ Agent │ │ Human │
228
+ │ Repo A │ │ Repo B │ │ (dash) │
229
+ └─────────┘ └─────────┘ └─────────┘
230
+ ```
231
+
232
+ Multiple agents across different repos coordinate through the same BeadHub server.
233
+
234
+ ## Requirements
235
+
236
+ - Docker and Docker Compose
237
+ - [Beads](https://github.com/steveyegge/beads) for issue tracking
238
+
239
+ ## Documentation
240
+
241
+ - [bdh Command Reference](docs/bdh.md)
242
+ - [Deployment Guide](docs/deployment.md)
243
+ - [Development Guide](docs/development.md)
244
+ - [Changelog](CHANGELOG.md)
245
+
246
+ ## Cleanup
247
+
248
+ ```bash
249
+ docker compose down -v
250
+ ```
251
+
252
+ ## License
253
+
254
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,54 @@
1
+ beadhub/__init__.py,sha256=xV4F4KIcDjzjBAubgbfnqXQGykDSVbCZ3h8gBsKLJPI,257
2
+ beadhub/api.py,sha256=SdNS8wyoTSpB2Reo7mdiwZEIMyfWllAwzBM3U_V3-yQ,9696
3
+ beadhub/auth.py,sha256=re60LYsPzrB7WU8WB9vYoo7QNMSPbQlUI1gfxuYGL9U,3202
4
+ beadhub/aweb_context.py,sha256=XbeJd_F1YGgJyCnqoHgBuALwSZnjeT-8CTfHjPOIFR0,1905
5
+ beadhub/aweb_introspection.py,sha256=VuJxtGoru6llD9fEziNXnHuv_Mk8EdSrVc37K16aSBc,2562
6
+ beadhub/beads_sync.py,sha256=bRpsJuBTozfj-Yqjjc0Au4mQtHcjTl-BiZPb7oXaDQQ,18086
7
+ beadhub/cli.py,sha256=GsL4DK5nNSouwv4zvAqThz8o9wK3FBGGbCe9CSuKBrU,10670
8
+ beadhub/config.py,sha256=ceuQrP_kZDmTH_bBjcYHH2y5xDqbXl_P8rjgRnB1Gzg,2077
9
+ beadhub/db.py,sha256=an_Sgg3E8BA7ZvC5ruSXlYn1tQnDwqyffoqbQiQJIVk,4628
10
+ beadhub/defaults.py,sha256=aeppczKQCsnFYH9hBR4gEOMQiUZEWyzajAsD-hhH4ec,7978
11
+ beadhub/events.py,sha256=jTxkS4wOXzmiNhO-THlMN3icpI1xm60HF2mq_TQGLqY,23609
12
+ beadhub/internal_auth.py,sha256=0gMnQZTGSKum6RG_aegPAYA9Y0Su-POD3w5hsBXPv6Q,4089
13
+ beadhub/jsonl.py,sha256=rihr6dZtpetCmjI-NAcwC3Nwo59ze7hiW08iBjv7GtA,2164
14
+ beadhub/logging.py,sha256=coreUgbK0imFhuh0wqXG_08ndrP9vt8oSoXr0be3-ZA,1928
15
+ beadhub/names.py,sha256=xKgQgWbS7rvK3Eac_S9Q1y7tq4qI_CNGZbUBsRsifOk,512
16
+ beadhub/notifications.py,sha256=wqRkXBxqIGq6eKACRlj6f14fPsTrJd-65ucxZoynZHw,8487
17
+ beadhub/pagination.py,sha256=lcKBw_CBwBg5_wdBENtXuuL8U6Ncaxib9ajOwc_-Rcc,3893
18
+ beadhub/presence.py,sha256=OgKgooH9ZRdmK8INsVyUiz4IRrGEQ-MLrxJdQBvdn_0,15393
19
+ beadhub/rate_limit.py,sha256=KkicwCZv8aOwoENgFc2m1PMvLDa5CE4SBYXlmWBOsH4,4720
20
+ beadhub/redis_client.py,sha256=f9IRPQH0DOiM5hC7D_LxFiCr7yCyqjZNayA8a-Q9l4U,273
21
+ beadhub/roles.py,sha256=442UQxgQ9lYM_ccyvwn803s-Kt-0ZEcrDMk8-nsOHps,1086
22
+ beadhub/workspace_config.py,sha256=d_xECpDvYZ29qpQb9E1naBhQyHuKcAzjZnguRJVC8bQ,5548
23
+ beadhub/defaults/invariants/01-tracking-bdh-only.md,sha256=_ipwZg5sENZTBfPA-JUuxRniWA8nW5c9aoB09KeIiWA,375
24
+ beadhub/defaults/invariants/02-communication-mail-first.md,sha256=OIpgBFKAndqdL6Z37UAO_Jxfke9YcpDD9GPtswi3qsY,925
25
+ beadhub/defaults/invariants/03-communication-chat.md,sha256=D5_mLxTP-1B1BRWoZd-TQUkpmLbwotQ8tg4J2IoFiws,1844
26
+ beadhub/defaults/invariants/04-identity-no-impersonation.md,sha256=mlwztSun5hNxqD3ADcrXUBYHtcs86fFMnZAlZ_THuPo,534
27
+ beadhub/defaults/invariants/05-collaborate.md,sha256=KvOwHgB5cyn55IsySvZx5tDosaL_QTVUbwNcE3IQT4M,445
28
+ beadhub/defaults/roles/backend.md,sha256=M3FBwOb9MIb6NUVNooS3aFbz20KNBMsAEM45TMCFmmo,1404
29
+ beadhub/defaults/roles/coordinator.md,sha256=bjlMxNUNdmk0lVX0l9jwu-YbqkUzd26maiV19WHURG0,1200
30
+ beadhub/defaults/roles/frontend.md,sha256=gXBqQg2h0oOQqzmCqYDGIdoZZBNaCduLNbfVMjSOTMY,2014
31
+ beadhub/defaults/roles/implementer.md,sha256=s-mte97p5yEuKQctCgjOVb7ncRT1NMARlPujyYteZgk,1886
32
+ beadhub/defaults/roles/reviewer.md,sha256=8cs3vvI6AT0dcN2Qybq7Rr7zBIBtmq4AeRzlNvKSfa4,1442
33
+ beadhub/defaults/roles/startup-expert.md,sha256=JKygzye541J_fd2u989gBYocKNHEsvAyDZJfWRZ4EQA,4793
34
+ beadhub/migrations/beads/001_initial.sql,sha256=I47sncZ9R7fyF42tuBAmouCtyePw3UTWy-Had0G5yVw,2275
35
+ beadhub/migrations/beads/002_search_indexes.sql,sha256=R2ZIc-SO87nv8UyN7Q4nIZfsUUu7QYn_EiZAhYGvzWk,990
36
+ beadhub/migrations/server/001_initial.sql,sha256=FNLSpwg0X-vlPBLEtvYEsMpKG_12OspmH7upmZhPiv0,12339
37
+ beadhub/routes/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
38
+ beadhub/routes/agents.py,sha256=d_tu6GS-WjRnnAtok1QxGv2EtPeQysjY9aWPBbDZwDU,9667
39
+ beadhub/routes/bdh.py,sha256=UZ41aeSA1fnOukNZhXFHYbsHRd2piHCn4Toa4-TOGMU,21274
40
+ beadhub/routes/beads.py,sha256=NE1Dnyev9AXIXd6i42nUai4QVUIT3nx-d4JQaKRhGHY,27049
41
+ beadhub/routes/claims.py,sha256=Ab0PWkN2zziEHvS4b9IYFSuepAFeULhRSSg-iHzRHYE,4676
42
+ beadhub/routes/escalations.py,sha256=kTRV1-PqxnzAz0wFpuwcypXaJMixx10pL5EDY9_O5Cc,15766
43
+ beadhub/routes/init.py,sha256=YFSCB-mGQQSoDeUB5mDB4P9hiV2N1tJ_CLcQslsG-pA,12092
44
+ beadhub/routes/mcp.py,sha256=V46oiGUtG7iZ-Q4waRVBon7qezrYOm_jb0mM3u-ZhBs,12140
45
+ beadhub/routes/policies.py,sha256=8RKRb53uGdGAqAmWy5WwTm67jlgkwGHjbVusUwpXY6k,24885
46
+ beadhub/routes/repos.py,sha256=Yfa6ZRZDWAMnUitolFlCDln5Tl3q4Oh4uSPtgvMOfhk,16136
47
+ beadhub/routes/status.py,sha256=QvA8GsDYw9ZJxNMdq-Q6AvSmmnAk6_8vktvFiOgZQq8,19908
48
+ beadhub/routes/subscriptions.py,sha256=6EgpKseRnmMgY0STVRY02Ss5_hLUrmCcH1j9BZW__aI,11733
49
+ beadhub/routes/workspaces.py,sha256=qRwqdfewKMrQb_e772sJklUD5MtWxtl22Lm-lmHO_8Y,58554
50
+ beadhub-0.1.0.dist-info/METADATA,sha256=i0RxPsUCMdK1eBgmVxRzXrDQGtNFfmWr_nZwJE7V-7Y,8224
51
+ beadhub-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
52
+ beadhub-0.1.0.dist-info/entry_points.txt,sha256=R0WP_G-w5OLtcXmJBYWegf7nz19r8fWsLmvXcKhCVzg,41
53
+ beadhub-0.1.0.dist-info/licenses/LICENSE,sha256=xkOblX-z-aMOHH5l6MnEAVc0dFrpwFN2dPJGFvKsXtg,1068
54
+ beadhub-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ beadhub = beadhub:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Juan Reyero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.