taskboy 0.1.1__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.
- taskboy/__init__.py +0 -0
- taskboy/adapters/__init__.py +0 -0
- taskboy/adapters/_util.py +30 -0
- taskboy/adapters/aws_read.py +107 -0
- taskboy/adapters/confluence.py +88 -0
- taskboy/adapters/github_api.py +564 -0
- taskboy/adapters/issues.py +435 -0
- taskboy/adapters/jira.py +263 -0
- taskboy/adapters/sentry.py +82 -0
- taskboy/adapters/slack_history.py +204 -0
- taskboy/assets.py +27 -0
- taskboy/audit.py +78 -0
- taskboy/broker.py +266 -0
- taskboy/classifier.py +219 -0
- taskboy/cli.py +161 -0
- taskboy/config.py +539 -0
- taskboy/dashboard/__init__.py +5 -0
- taskboy/dashboard/api.py +963 -0
- taskboy/dashboard/app.py +78 -0
- taskboy/dashboard/auth.py +117 -0
- taskboy/dashboard/editors.py +140 -0
- taskboy/dashboard/gitops.py +60 -0
- taskboy/dashboard/render.py +48 -0
- taskboy/debug_feed.py +170 -0
- taskboy/deploy/env.example +17 -0
- taskboy/deploy/git-cred-helper.py +36 -0
- taskboy/deploy/install.sh +101 -0
- taskboy/deploy/remote-update.sh +52 -0
- taskboy/deploy/taskboy-restart.path +10 -0
- taskboy/deploy/taskboy-restart.service +8 -0
- taskboy/deploy/taskboy.service +22 -0
- taskboy/hooks.py +208 -0
- taskboy/issue_runs.py +203 -0
- taskboy/llm.py +125 -0
- taskboy/main.py +269 -0
- taskboy/memory.py +59 -0
- taskboy/models.py +103 -0
- taskboy/mrkdwn.py +19 -0
- taskboy/notify.py +41 -0
- taskboy/orchestrator.py +401 -0
- taskboy/personality.py +17 -0
- taskboy/prompts.py +288 -0
- taskboy/quick.py +234 -0
- taskboy/redact.py +49 -0
- taskboy/repocache.py +117 -0
- taskboy/review_requests.py +388 -0
- taskboy/router.py +146 -0
- taskboy/runner.py +581 -0
- taskboy/scheduler.py +301 -0
- taskboy/secrets.py +83 -0
- taskboy/settings.py +19 -0
- taskboy/setup_checks.py +184 -0
- taskboy/setup_wizard.py +699 -0
- taskboy/skills.py +95 -0
- taskboy/slack.py +666 -0
- taskboy/slack_users.py +32 -0
- taskboy/started_messages.py +33 -0
- taskboy/store.py +1393 -0
- taskboy/task_actions.py +86 -0
- taskboy/templates/config.example.yaml +149 -0
- taskboy/templates/conventions.md +60 -0
- taskboy/templates/help.example.md +29 -0
- taskboy/templates/personality_agent.example.md +5 -0
- taskboy/templates/personality_reviewer.example.md +5 -0
- taskboy/templates/services/aws.yaml +7 -0
- taskboy/templates/services/confluence.yaml +4 -0
- taskboy/templates/services/github.yaml +14 -0
- taskboy/templates/services/jira.yaml +6 -0
- taskboy/templates/services/sentry.yaml +4 -0
- taskboy/templates/services/slack.yaml +9 -0
- taskboy/templates/skills/README.md +33 -0
- taskboy/templates/skills/discoverissues/SKILL.md +46 -0
- taskboy/templates/skills/implementapprovedissues/SKILL.md +41 -0
- taskboy/templates/skills/jira2pr/SKILL.md +66 -0
- taskboy/templates/skills/monitor/SKILL.md +32 -0
- taskboy/templates/skills/monitornew/SKILL.md +27 -0
- taskboy/templates/skills/refineissue/SKILL.md +35 -0
- taskboy/templates/skills/release/SKILL.md +36 -0
- taskboy/templates/skills/review/SKILL.md +89 -0
- taskboy/templates/skills/reviewandmonitor/SKILL.md +22 -0
- taskboy/templates/skills/reviews/SKILL.md +26 -0
- taskboy/templates/skills/slack2jira/SKILL.md +47 -0
- taskboy/templates/skills/slack2pr/SKILL.md +64 -0
- taskboy/templates/skills/spec2pr/SKILL.md +35 -0
- taskboy/templates/slack_app_manifest.yaml +48 -0
- taskboy/templates/task_started_messages.yaml +14 -0
- taskboy/ui_dist/assets/index-DmYxR9Qy.css +1 -0
- taskboy/ui_dist/assets/index-LDDO4iT2.js +15 -0
- taskboy/ui_dist/index.html +15 -0
- taskboy/workspace.py +86 -0
- taskboy-0.1.1.dist-info/METADATA +120 -0
- taskboy-0.1.1.dist-info/RECORD +95 -0
- taskboy-0.1.1.dist-info/WHEEL +5 -0
- taskboy-0.1.1.dist-info/entry_points.txt +2 -0
- taskboy-0.1.1.dist-info/top_level.txt +1 -0
taskboy/slack_users.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""shared Slack user-profile cache and refresh logic."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
|
|
5
|
+
from taskboy.store import Store
|
|
6
|
+
|
|
7
|
+
USER_CACHE_SECONDS = 24 * 60 * 60
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def cached_user_profile(store: Store, client, user_id: str) -> dict | None:
|
|
11
|
+
cached = store.get_slack_user(user_id)
|
|
12
|
+
if cached:
|
|
13
|
+
try:
|
|
14
|
+
age = datetime.now(timezone.utc) - datetime.fromisoformat(cached["updated_at"])
|
|
15
|
+
if age.total_seconds() < USER_CACHE_SECONDS:
|
|
16
|
+
return cached
|
|
17
|
+
except (KeyError, TypeError, ValueError):
|
|
18
|
+
pass
|
|
19
|
+
response = await client.users_info(user=user_id)
|
|
20
|
+
user = response.get("user") or {}
|
|
21
|
+
profile = user.get("profile") or {}
|
|
22
|
+
return store.upsert_slack_user(
|
|
23
|
+
user_id,
|
|
24
|
+
team_id=user.get("team_id"),
|
|
25
|
+
username=user.get("name"),
|
|
26
|
+
real_name=user.get("real_name") or profile.get("real_name"),
|
|
27
|
+
display_name=profile.get("display_name"),
|
|
28
|
+
email=profile.get("email"),
|
|
29
|
+
title=profile.get("title"),
|
|
30
|
+
tz=user.get("tz"),
|
|
31
|
+
is_bot=int(bool(user.get("is_bot"))),
|
|
32
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""token-free task-started message selection from agent and reviewer yaml pools."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import yaml
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def validate_content(content: str) -> dict[str, list[str]]:
|
|
10
|
+
try:
|
|
11
|
+
pools = yaml.safe_load(content)
|
|
12
|
+
except yaml.YAMLError as e:
|
|
13
|
+
raise ValueError(f"task-started messages are not valid yaml: {e}") from e
|
|
14
|
+
if not isinstance(pools, dict) or set(pools) != {"agent", "reviewer"}:
|
|
15
|
+
raise ValueError("task-started messages must be a yaml mapping with 'agent' and 'reviewer' lists")
|
|
16
|
+
for pool, choices in pools.items():
|
|
17
|
+
if not isinstance(choices, list) or not choices or not all(isinstance(item, str) and item.strip() for item in choices):
|
|
18
|
+
raise ValueError(f"task-started messages for {pool!r} must be a non-empty list of non-empty strings")
|
|
19
|
+
return pools
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def pick(path: str | None, pool: str | None) -> str | None:
|
|
23
|
+
if not path or not pool:
|
|
24
|
+
return None
|
|
25
|
+
try:
|
|
26
|
+
pools = yaml.safe_load(Path(path).read_text())
|
|
27
|
+
choices = pools.get(pool) if isinstance(pools, dict) else None
|
|
28
|
+
if not isinstance(choices, list):
|
|
29
|
+
return None
|
|
30
|
+
valid = [item.strip() for item in choices if isinstance(item, str) and item.strip()]
|
|
31
|
+
return random.choice(valid) if valid else None
|
|
32
|
+
except (OSError, UnicodeError, yaml.YAMLError):
|
|
33
|
+
return None
|