devops-bot-sdk 1.4.65__tar.gz → 1.4.67__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.
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/pyproject.toml +1 -1
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/client.py +1 -1
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/ipc/handlers.py +92 -20
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/README.md +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/SOURCES.txt +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/config.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/run_auto.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/test.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/setup.cfg +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "devops-bot-sdk"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.67"
|
|
8
8
|
description = "DevOps Bot Desktop SDK — thin client for the AgentOS Electron desktop app"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "LicenseRef-Proprietary"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
|
|
2
2
|
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.67
|
|
4
4
|
|
|
5
5
|
Public surface:
|
|
6
6
|
BackendClient.from_config() — create client from ~/.agentos/config.toml
|
|
@@ -30,7 +30,7 @@ Rules:
|
|
|
30
30
|
- All data egress through submit_webhook only
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
__version__ = "1.4.
|
|
33
|
+
__version__ = "1.4.67"
|
|
34
34
|
__author__ = "AgentOS"
|
|
35
35
|
|
|
36
36
|
from sdk.client import BackendClient
|
|
@@ -594,6 +594,34 @@ def _epic_inherited_fields(task: dict) -> dict:
|
|
|
594
594
|
return {k: v for k, v in fields.items() if v}
|
|
595
595
|
|
|
596
596
|
|
|
597
|
+
# Lines that name a directory to WRITE the generated user stories into (distinct
|
|
598
|
+
# from a code repo path). Matches story/file/folder/directory/mkdir/write hints
|
|
599
|
+
# and skips repo lines (github URL / "path:").
|
|
600
|
+
_STORIES_DIR_HINT = re.compile(
|
|
601
|
+
r"\b(user\s+stor|stories|mkdir|directory|folder|write|\.md)\b", re.I,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def _extract_stories_dir(text: str | None) -> str | None:
|
|
606
|
+
"""A directory the instructions ask the user stories to be WRITTEN into, or None.
|
|
607
|
+
|
|
608
|
+
Scans lines that mention stories/files/a directory (but not code-repo lines that
|
|
609
|
+
carry a GitHub URL or a "path:" repo label) and returns the first filesystem path
|
|
610
|
+
found — e.g. "Create a new directory at /home/me/new_tasks and write the stories".
|
|
611
|
+
"""
|
|
612
|
+
if not text:
|
|
613
|
+
return None
|
|
614
|
+
for line in text.splitlines():
|
|
615
|
+
low = line.lower()
|
|
616
|
+
if "github.com" in low or "path:" in low:
|
|
617
|
+
continue # a code repo line, not a stories-output directory
|
|
618
|
+
if _STORIES_DIR_HINT.search(line):
|
|
619
|
+
p = _extract_path_from_text(line)
|
|
620
|
+
if p:
|
|
621
|
+
return p
|
|
622
|
+
return None
|
|
623
|
+
|
|
624
|
+
|
|
597
625
|
# ── Ticket validation gate (Epics + USER-driven Stories) ────────────────────
|
|
598
626
|
# A strict quality gate: before the bot actions an Epic or a USER-created Story it
|
|
599
627
|
# checks the ticket meets the required standard. On failure it posts a harsh,
|
|
@@ -616,30 +644,42 @@ def _build_validation_prompt(kind: str, jira_key: str, summary: str,
|
|
|
616
644
|
"Description:\n" + (_clip_text(description.strip()) if description and description.strip() else "(none provided)"),
|
|
617
645
|
"Human Instructions:\n" + (human.strip() if human and human.strip() else "(none provided)"),
|
|
618
646
|
]
|
|
647
|
+
is_epic = kind == "epic"
|
|
619
648
|
parts.append(
|
|
620
|
-
"Judge the ticket
|
|
621
|
-
"
|
|
622
|
-
"
|
|
649
|
+
"Judge the ticket for what it ACTUALLY asks for — software, documentation, "
|
|
650
|
+
"analysis, Finance, HR or operations. Do NOT impose requirements the ticket "
|
|
651
|
+
"does not need.\n\n"
|
|
623
652
|
"A VALID ticket MUST have:\n"
|
|
624
653
|
"- A clear, unambiguous goal and scope (no hand-waving).\n"
|
|
625
|
-
"- A clearly-defined deliverable
|
|
626
|
-
"
|
|
627
|
-
"- Observable
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
654
|
+
"- A clearly-defined deliverable/outcome (and where to produce it when a "
|
|
655
|
+
"location matters).\n"
|
|
656
|
+
"- Observable acceptance criteria (or an equally concrete definition of done).\n"
|
|
657
|
+
+ (
|
|
658
|
+
# EPIC: a decomposition container — NEVER require code-execution details.
|
|
659
|
+
"- Enough substance to DECOMPOSE into user stories.\n"
|
|
660
|
+
"IMPORTANT: this is an EPIC — a high-level container the system decomposes "
|
|
661
|
+
"into user stories. Do NOT require a repository URL, file paths, branch/PR "
|
|
662
|
+
"convention, or build/run/test commands at the epic level; those are "
|
|
663
|
+
"established LATER at the story/task stage, never in the epic. Even when the "
|
|
664
|
+
"epic describes software features, judge it ONLY on goal, scope, user "
|
|
665
|
+
"stories and epic-level acceptance criteria. NEVER reject an epic for missing "
|
|
666
|
+
"repository, branch, PR, build, or test details.\n"
|
|
667
|
+
if is_epic else
|
|
668
|
+
# STORY: repo details help but the PRD/coding stage grounds them.
|
|
669
|
+
"- A clear 'As a <role>, I want <capability>, so that <benefit>' intent plus "
|
|
670
|
+
"testable acceptance criteria.\n"
|
|
671
|
+
"For a code story, a target repo/path is helpful but NOT mandatory here — the "
|
|
672
|
+
"PRD/coding stage grounds it against the codebase. Do NOT reject solely for a "
|
|
673
|
+
"missing branch/PR convention or build/test steps.\n"
|
|
674
|
+
)
|
|
636
675
|
+ "- Any THIRD-PARTY INTEGRATION or human-effort dependency the work GENUINELY "
|
|
637
|
-
"needs (API keys, OAuth credentials, external accounts, secrets,
|
|
638
|
-
"
|
|
639
|
-
"
|
|
640
|
-
"
|
|
641
|
-
"
|
|
642
|
-
"ambiguous information — not for absent
|
|
676
|
+
"needs (API keys, OAuth credentials, external accounts, secrets, provisioning) "
|
|
677
|
+
"MUST be named WITH who provides it; if a REQUIRED dependency is undefined, REJECT.\n\n"
|
|
678
|
+
"Unrendered template placeholders — an EMPTY `{{...}}` or `<...>` with no real "
|
|
679
|
+
"content — are a valid reason to reject. But if a section contains real content "
|
|
680
|
+
"merely wrapped in stray markers, treat it as PRESENT, not missing.\n"
|
|
681
|
+
"Reject only for genuinely missing or ambiguous information — not for absent "
|
|
682
|
+
"execution details the ticket does not need at this stage.\n\n"
|
|
643
683
|
"Output ONLY a fenced ```json block, nothing else:\n"
|
|
644
684
|
"{\n"
|
|
645
685
|
' "valid": true or false,\n'
|
|
@@ -827,6 +867,38 @@ async def _handle_epic(
|
|
|
827
867
|
data={"current_step": f" ↳ created To Do task: {fields['summary']}"},
|
|
828
868
|
).model_dump())
|
|
829
869
|
|
|
870
|
+
# 3b. Optionally ALSO write each story as a Markdown file to a directory named in
|
|
871
|
+
# the instructions (e.g. "create /home/me/new_tasks and write the user stories
|
|
872
|
+
# there"). This is IN ADDITION to the Story tickets. Best-effort — a file-write
|
|
873
|
+
# failure never fails the Epic.
|
|
874
|
+
stories_dir = _extract_stories_dir(human)
|
|
875
|
+
if stories_dir:
|
|
876
|
+
from pathlib import Path
|
|
877
|
+
try:
|
|
878
|
+
d = Path(stories_dir).expanduser()
|
|
879
|
+
d.mkdir(parents=True, exist_ok=True) # create from scratch
|
|
880
|
+
written = 0
|
|
881
|
+
for i, st in enumerate(stories[:_MAX_EPIC_STORIES], 1):
|
|
882
|
+
if not isinstance(st, dict) or not (st.get("summary") or "").strip():
|
|
883
|
+
continue
|
|
884
|
+
title = str(st.get("summary", "")).strip()
|
|
885
|
+
slug = re.sub(r"[^a-z0-9]+", "-", title.lower()).strip("-")[:50] or f"story-{i}"
|
|
886
|
+
content = f"# {title}\n\n{str(st.get('description', '') or '').strip()}\n"
|
|
887
|
+
(d / f"{i:02d}-{slug}.md").write_text(content, encoding="utf-8")
|
|
888
|
+
written += 1
|
|
889
|
+
await client.log_activity(f"Epic {jira_key}: wrote {written} user-story file(s) to {stories_dir}")
|
|
890
|
+
await send(Envelope(
|
|
891
|
+
type="step_update", thread_id=thread_id,
|
|
892
|
+
data={"jira_task_id": tid,
|
|
893
|
+
"current_step": f"Epic {jira_key}: wrote {written} user-story file(s) to {stories_dir}"},
|
|
894
|
+
).model_dump())
|
|
895
|
+
except Exception as exc: # noqa: BLE001
|
|
896
|
+
await send(Envelope(
|
|
897
|
+
type="step_update", thread_id=thread_id,
|
|
898
|
+
data={"jira_task_id": tid,
|
|
899
|
+
"current_step": f"Epic {jira_key}: could not write story files to {stories_dir} — {str(exc)[:120]}"},
|
|
900
|
+
).model_dump())
|
|
901
|
+
|
|
830
902
|
await client.log_activity(
|
|
831
903
|
f"Epic {jira_key}: Done — created {len(created)}/{len(stories)} To Do user Story(ies)"
|
|
832
904
|
)
|
|
File without changes
|
|
File without changes
|
{devops_bot_sdk-1.4.65 → devops_bot_sdk-1.4.67}/devops_bot_sdk.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|