devops-bot-sdk 1.4.81__tar.gz → 1.4.83__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.81 → devops_bot_sdk-1.4.83}/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/pyproject.toml +1 -1
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/client.py +1 -1
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/ipc/handlers.py +65 -11
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/README.md +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/SOURCES.txt +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/config.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/run_auto.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/test.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/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.83"
|
|
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.83
|
|
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.83"
|
|
34
34
|
__author__ = "AgentOS"
|
|
35
35
|
|
|
36
36
|
from sdk.client import BackendClient
|
|
@@ -531,7 +531,8 @@ _PRD_FORMAT = (
|
|
|
531
531
|
|
|
532
532
|
|
|
533
533
|
def _build_epic_prompt(jira_key: str, summary: str, description: str | None,
|
|
534
|
-
human_instructions: str | None, story_count: int | None = None
|
|
534
|
+
human_instructions: str | None, story_count: int | None = None,
|
|
535
|
+
story_titles: list[str] | None = None) -> str:
|
|
535
536
|
"""Read-only prompt that turns an Epic into a decomposition JSON."""
|
|
536
537
|
parts: list[str] = [
|
|
537
538
|
"You are decomposing a JIRA EPIC into implementable user stories. This is "
|
|
@@ -578,11 +579,21 @@ def _build_epic_prompt(jira_key: str, summary: str, description: str | None,
|
|
|
578
579
|
"}\n\n"
|
|
579
580
|
"Do NOT produce humanInstructions for the stories — created stories are clean "
|
|
580
581
|
"user-story artifacts; implementation instructions are added later.\n"
|
|
581
|
-
+ (
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
582
|
+
+ (
|
|
583
|
+
# The epic ENUMERATES its stories → reproduce them EXACTLY (verbatim titles).
|
|
584
|
+
("The epic already lists its user stories. Produce EXACTLY these "
|
|
585
|
+
f"{len(story_titles)} stor{'y' if len(story_titles) == 1 else 'ies'}, in this "
|
|
586
|
+
"order, using each title VERBATIM as the story's summary — do NOT invent, "
|
|
587
|
+
"rename, merge, add, drop, or reorder any. Only expand each into the USER "
|
|
588
|
+
"STORY FORMAT for its description:\n"
|
|
589
|
+
+ "\n".join(f" {i}. {t}" for i, t in enumerate(story_titles, 1)) + "\n")
|
|
590
|
+
if story_titles else
|
|
591
|
+
(f"Generate EXACTLY {story_count} user stor{'y' if story_count == 1 else 'ies'} — "
|
|
592
|
+
"the epic explicitly asks for this many; do not produce more or fewer.\n"
|
|
593
|
+
if story_count else
|
|
594
|
+
"Create as many stories as the epic genuinely needs (do not pad or truncate "
|
|
595
|
+
"artificially); each story must be independently implementable.\n")
|
|
596
|
+
)
|
|
586
597
|
+ "assigneeEmail is OPTIONAL per story: set it ONLY when the epic explicitly "
|
|
587
598
|
"assigns that specific work to a named person/email (e.g. 'assign the API to "
|
|
588
599
|
"alice@x.com'); otherwise omit it.\n\n"
|
|
@@ -684,6 +695,42 @@ def _extract_story_count(text: str | None) -> int | None:
|
|
|
684
695
|
return min(n, 50) if n and n >= 1 else None
|
|
685
696
|
|
|
686
697
|
|
|
698
|
+
_STORY_LIST_ITEM_RE = re.compile(r"^\s*(?:\d+[.)]|[-*•])\s+(.+?)\s*$")
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
def _extract_story_titles(text: str | None) -> list[str]:
|
|
702
|
+
"""Titles of the user stories the epic ENUMERATES under a 'User Stories' heading.
|
|
703
|
+
|
|
704
|
+
When the epic already lists its stories ("1. Login — …", "- Logout"), those are
|
|
705
|
+
the authoritative stories — the bot must reproduce EXACTLY them (same count, same
|
|
706
|
+
titles), not invent its own. Returns the list of titles (the part before an
|
|
707
|
+
em/en-dash or colon separator), or [] when the epic gives no explicit list.
|
|
708
|
+
"""
|
|
709
|
+
if not text:
|
|
710
|
+
return []
|
|
711
|
+
lines = text.splitlines()
|
|
712
|
+
start = None
|
|
713
|
+
for i, ln in enumerate(lines):
|
|
714
|
+
if re.match(r"\s*#{0,6}\s*user\s+stor(?:y|ies)\b\s*:?\s*$", ln, re.I):
|
|
715
|
+
start = i + 1
|
|
716
|
+
break
|
|
717
|
+
if start is None:
|
|
718
|
+
return []
|
|
719
|
+
titles: list[str] = []
|
|
720
|
+
for ln in lines[start:]:
|
|
721
|
+
if re.match(r"\s*#{1,6}\s+\S", ln): # next heading → section ends
|
|
722
|
+
break
|
|
723
|
+
m = _STORY_LIST_ITEM_RE.match(ln)
|
|
724
|
+
if not m:
|
|
725
|
+
continue
|
|
726
|
+
item = m.group(1).strip()
|
|
727
|
+
title = re.split(r"\s+[—–-]\s+|:\s+", item, maxsplit=1)[0]
|
|
728
|
+
title = title.strip(" *`_").strip()
|
|
729
|
+
if title:
|
|
730
|
+
titles.append(title[:250])
|
|
731
|
+
return titles[:50]
|
|
732
|
+
|
|
733
|
+
|
|
687
734
|
def _extract_stories_dir(text: str | None) -> str | None:
|
|
688
735
|
"""A directory the instructions ask the user stories to be WRITTEN into, or None.
|
|
689
736
|
|
|
@@ -879,16 +926,22 @@ async def _handle_epic(
|
|
|
879
926
|
).model_dump())
|
|
880
927
|
|
|
881
928
|
# 1. Generate the decomposition, grounded in the codebase where one exists.
|
|
882
|
-
#
|
|
883
|
-
#
|
|
884
|
-
|
|
929
|
+
# Priority for how many stories + their titles:
|
|
930
|
+
# (a) the epic ENUMERATES its stories (a "User Stories" list) → use those
|
|
931
|
+
# exact titles and count, verbatim;
|
|
932
|
+
# (b) else an explicit "build N stories" count → exactly N;
|
|
933
|
+
# (c) else the model decides (bounded by _MAX_EPIC_STORIES).
|
|
934
|
+
story_titles = _extract_story_titles(description) or _extract_story_titles(human)
|
|
935
|
+
story_count = (len(story_titles) if story_titles
|
|
936
|
+
else (_extract_story_count(description) or _extract_story_count(human)))
|
|
885
937
|
limit = story_count or _MAX_EPIC_STORIES
|
|
886
938
|
try:
|
|
887
939
|
await graphify.prepare(project_path)
|
|
888
940
|
except Exception: # noqa: BLE001
|
|
889
941
|
pass
|
|
890
942
|
gen = await _run_generation(
|
|
891
|
-
_build_epic_prompt(jira_key, summary, description, human,
|
|
943
|
+
_build_epic_prompt(jira_key, summary, description, human,
|
|
944
|
+
story_count=story_count, story_titles=story_titles or None),
|
|
892
945
|
project_path, send=send, thread_id=thread_id,
|
|
893
946
|
label=f"Epic {jira_key}: generating user stories",
|
|
894
947
|
github_token=await client.github_token(),
|
|
@@ -976,7 +1029,8 @@ async def _handle_epic(
|
|
|
976
1029
|
# the instructions (e.g. "create /home/me/new_tasks and write the user stories
|
|
977
1030
|
# there"). This is IN ADDITION to the Story tickets. Best-effort — a file-write
|
|
978
1031
|
# failure never fails the Epic.
|
|
979
|
-
|
|
1032
|
+
# Folder may be named in the humanInstructions OR the description — check both.
|
|
1033
|
+
stories_dir = _extract_stories_dir(human) or _extract_stories_dir(description)
|
|
980
1034
|
if stories_dir:
|
|
981
1035
|
from pathlib import Path
|
|
982
1036
|
try:
|
|
File without changes
|
|
File without changes
|
{devops_bot_sdk-1.4.81 → devops_bot_sdk-1.4.83}/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
|