devops-bot-sdk 1.4.45__tar.gz → 1.4.47__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.45 → devops_bot_sdk-1.4.47}/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/pyproject.toml +1 -1
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/client.py +1 -1
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/ipc/handlers.py +28 -29
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/run_auto.py +25 -10
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/README.md +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/SOURCES.txt +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/config.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/test.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/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.47"
|
|
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.47
|
|
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.47"
|
|
34
34
|
__author__ = "AgentOS"
|
|
35
35
|
|
|
36
36
|
from sdk.client import BackendClient
|
|
@@ -653,18 +653,24 @@ async def _handle_story(
|
|
|
653
653
|
github_token=await client.github_token(),
|
|
654
654
|
)
|
|
655
655
|
prd = (gen.get("result") or "").strip() if gen.get("ok") else ""
|
|
656
|
-
if
|
|
656
|
+
if prd:
|
|
657
|
+
# PRD lives alongside the user story in the (now Task) description.
|
|
658
|
+
new_description = f"{user_story}\n\n---\n\n{_PRD_MARKER}\n\n{prd}"[:20000]
|
|
659
|
+
else:
|
|
660
|
+
# PRD generation failed — do NOT abandon the story: it must still become
|
|
661
|
+
# a Task (per "a Story once run should be changed into Task"). The PRD
|
|
662
|
+
# directive stays in humanInstructions, so the later coding run can still
|
|
663
|
+
# produce the PRD.md file.
|
|
657
664
|
reason = (gen.get("error") or "PRD generation produced no content")[:200]
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
665
|
+
await client.log_activity(
|
|
666
|
+
f"Story {jira_key}: PRD not pre-generated ({reason}) — converting to Task anyway"
|
|
667
|
+
)
|
|
661
668
|
await send(Envelope(
|
|
662
|
-
type=
|
|
663
|
-
data={"
|
|
669
|
+
type="step_update", thread_id=thread_id,
|
|
670
|
+
data={"jira_task_id": tid,
|
|
671
|
+
"current_step": f"Story {jira_key}: PRD generation skipped ({reason[:60]}) "
|
|
672
|
+
"— converting to Task"},
|
|
664
673
|
).model_dump())
|
|
665
|
-
return
|
|
666
|
-
# PRD lives alongside the user story in the (now Task) description.
|
|
667
|
-
new_description = f"{user_story}\n\n---\n\n{_PRD_MARKER}\n\n{prd}"[:20000]
|
|
668
674
|
|
|
669
675
|
# Convert Story → Task on the SAME ticket; leave it To Do so the next run codes
|
|
670
676
|
# it. humanInstructions are untouched (they still carry the location + any PRD
|
|
@@ -682,14 +688,15 @@ async def _handle_story(
|
|
|
682
688
|
).model_dump())
|
|
683
689
|
return
|
|
684
690
|
|
|
691
|
+
prd_in_desc = bool(new_description) or already_has_prd
|
|
685
692
|
await client.log_activity(
|
|
686
|
-
f"Story {jira_key}: converted to Task{' with PRD' if
|
|
693
|
+
f"Story {jira_key}: converted to Task{' with PRD' if prd_in_desc else ''} (To Do)"
|
|
687
694
|
)
|
|
688
695
|
await send(Envelope(
|
|
689
696
|
type="step_update", thread_id=thread_id,
|
|
690
697
|
data={"jira_task_id": tid,
|
|
691
698
|
"current_step": f"Story {jira_key} → Task (To Do)"
|
|
692
|
-
+ (" + PRD in description" if
|
|
699
|
+
+ (" + PRD in description" if prd_in_desc else "")
|
|
693
700
|
+ " — run again to implement"},
|
|
694
701
|
).model_dump())
|
|
695
702
|
|
|
@@ -2493,10 +2500,16 @@ async def handle_orchestrate_auto_local_run(
|
|
|
2493
2500
|
# raised earliest is started first. Unknown/invalid timestamps sort last.
|
|
2494
2501
|
tasks = sorted(tasks, key=_task_created_key)
|
|
2495
2502
|
|
|
2503
|
+
# `stories_only` (agentos-auto story) → convert Stories to Tasks ONLY: no
|
|
2504
|
+
# epic decomposition, no coding. Narrow the queue to Story-type tickets.
|
|
2505
|
+
stories_only = bool(payload.get("stories_only"))
|
|
2506
|
+
if stories_only:
|
|
2507
|
+
tasks = [t for t in tasks if str(t.get("type") or "").strip().lower() == "story"]
|
|
2508
|
+
|
|
2496
2509
|
await send(Envelope(
|
|
2497
2510
|
type="pipeline_started", thread_id=thread_id,
|
|
2498
2511
|
data={"mode": "orchestrate-auto-local", "task_count": len(tasks),
|
|
2499
|
-
"only_keys": only_keys or None},
|
|
2512
|
+
"only_keys": only_keys or None, "stories_only": stories_only or None},
|
|
2500
2513
|
).model_dump())
|
|
2501
2514
|
|
|
2502
2515
|
if not tasks:
|
|
@@ -2527,21 +2540,6 @@ async def handle_orchestrate_auto_local_run(
|
|
|
2527
2540
|
project_path = _resolve_local_project_path(task, payload)
|
|
2528
2541
|
ttype = str(task.get("type") or "").strip().lower()
|
|
2529
2542
|
|
|
2530
|
-
# User STORIES are for the ASSIGNED DEVELOPERS, not the bot: the default
|
|
2531
|
-
# auto-loop skips Story-type tickets and never marks them In Progress or
|
|
2532
|
-
# Done. (An explicit target — `agentos-auto ticket <KEY>`, i.e. only_keys
|
|
2533
|
-
# set — still lets the bot act on a Story: generate its PRD and convert
|
|
2534
|
-
# it to a Task.) Once a ticket is a TASK it is coded normally
|
|
2535
|
-
# (In Progress → Done), even when it descended from an Epic/Story.
|
|
2536
|
-
if ttype == "story" and not only_keys:
|
|
2537
|
-
await send(Envelope(
|
|
2538
|
-
type="step_update", thread_id=thread_id,
|
|
2539
|
-
data={"jira_task_id": tid,
|
|
2540
|
-
"current_step": f"({idx}/{total}) {jira_key}: skipped — user Story "
|
|
2541
|
-
f"left for the assigned developer"},
|
|
2542
|
-
).model_dump())
|
|
2543
|
-
continue
|
|
2544
|
-
|
|
2545
2543
|
await send(Envelope(
|
|
2546
2544
|
type="step_update", thread_id=thread_id,
|
|
2547
2545
|
data={"current_step": f"({idx}/{total}) {jira_key}: {task.get('summary', '')}".rstrip(": "),
|
|
@@ -2550,8 +2548,9 @@ async def handle_orchestrate_auto_local_run(
|
|
|
2550
2548
|
|
|
2551
2549
|
# Staged decomposition — an EPIC and a STORY are transformed, not coded:
|
|
2552
2550
|
# Epic → decompose into user Stories (To Do), mark Epic Done
|
|
2553
|
-
# Story → (optional PRD) + convert to Task (To Do)
|
|
2554
|
-
#
|
|
2551
|
+
# Story → (optional PRD) + ALWAYS convert to Task (To Do); a Story is
|
|
2552
|
+
# never marked In Progress/Done — only ever converted
|
|
2553
|
+
# Task → implemented by the normal pipeline below (In Progress → Done)
|
|
2555
2554
|
# Each is isolated: a failure must not abort the remaining queue.
|
|
2556
2555
|
if ttype in ("epic", "story"):
|
|
2557
2556
|
handler = _handle_epic if ttype == "epic" else _handle_story
|
|
@@ -11,6 +11,8 @@ Commands:
|
|
|
11
11
|
agentos-auto resume alias for run — re-fetches remaining To Do tasks
|
|
12
12
|
agentos-auto ticket K [K...] run ONLY the named Jira ticket(s), e.g. BBW-81 —
|
|
13
13
|
any status, in the order given (alias: tickets)
|
|
14
|
+
agentos-auto story [K ...] convert Story(ies) → Task(s) only (with PRD), NO
|
|
15
|
+
coding; no keys = all To Do Stories (alias: stories)
|
|
14
16
|
agentos-auto stop ask the running loop to pause after the current task
|
|
15
17
|
agentos-auto status show whether the background loop is running / stop pending
|
|
16
18
|
agentos-auto update upgrade the SDK to the latest version
|
|
@@ -298,7 +300,8 @@ async def _send(env: dict) -> None:
|
|
|
298
300
|
print(f" [{etype}] {json.dumps(data)[:200]}")
|
|
299
301
|
|
|
300
302
|
|
|
301
|
-
def _run_loop(workspace_root: str | None, only_keys: list[str] | None = None
|
|
303
|
+
def _run_loop(workspace_root: str | None, only_keys: list[str] | None = None,
|
|
304
|
+
stories_only: bool = False) -> None:
|
|
302
305
|
from sdk import local_exec
|
|
303
306
|
from sdk.client import BackendClient, register_status_observer
|
|
304
307
|
from sdk.ipc import handlers
|
|
@@ -320,6 +323,9 @@ def _run_loop(workspace_root: str | None, only_keys: list[str] | None = None) ->
|
|
|
320
323
|
if only_keys:
|
|
321
324
|
# Targeted run: only these Jira tickets, in this order, regardless of status.
|
|
322
325
|
payload["only_keys"] = only_keys
|
|
326
|
+
if stories_only:
|
|
327
|
+
# Story→Task-only run: convert Stories to Tasks (with PRD), no coding.
|
|
328
|
+
payload["stories_only"] = True
|
|
323
329
|
|
|
324
330
|
_clear_stop() # a fresh run/resume clears any stale stop flag
|
|
325
331
|
_clear_backlogged() # session-scoped: only track Backlog moves from THIS run
|
|
@@ -458,17 +464,22 @@ def main() -> None:
|
|
|
458
464
|
print("stop pending: yes" if _stop_requested() else "stop pending: no")
|
|
459
465
|
return
|
|
460
466
|
|
|
461
|
-
if cmd in ("run", "resume", "ticket", "tickets"):
|
|
462
|
-
#
|
|
463
|
-
#
|
|
467
|
+
if cmd in ("run", "resume", "ticket", "tickets", "story", "stories"):
|
|
468
|
+
# Run modes:
|
|
469
|
+
# run/resume → the whole To Do queue
|
|
470
|
+
# ticket K... → ONLY the named Jira keys (any status, in order)
|
|
471
|
+
# story [K...] → convert Stories → Tasks only (with PRD); NO coding.
|
|
472
|
+
# With keys: those Stories; without: every To Do Story.
|
|
464
473
|
only_keys: list[str] | None = None
|
|
465
|
-
|
|
474
|
+
stories_only = cmd in ("story", "stories")
|
|
475
|
+
if cmd in ("ticket", "tickets", "story", "stories"):
|
|
466
476
|
only_keys = _parse_ticket_keys(argv)
|
|
467
|
-
if not only_keys:
|
|
477
|
+
if cmd in ("ticket", "tickets") and not only_keys:
|
|
468
478
|
print("usage: agentos-auto ticket <JIRA-KEY> [<JIRA-KEY> ...]")
|
|
469
479
|
print(" e.g. agentos-auto ticket BBW-81")
|
|
470
480
|
print(" agentos-auto ticket BBW-81 BBW-80")
|
|
471
481
|
sys.exit(1)
|
|
482
|
+
# `story` keys are OPTIONAL — no keys means "all To Do Stories".
|
|
472
483
|
|
|
473
484
|
# Self-update FIRST (before the already-running check) so the installed
|
|
474
485
|
# package is refreshed even when a daemon is already running — otherwise a
|
|
@@ -494,14 +505,18 @@ def main() -> None:
|
|
|
494
505
|
# attached (useful for debugging). On platforms without fork we stay attached.
|
|
495
506
|
foreground = "--foreground" in argv or "-f" in argv
|
|
496
507
|
if not foreground and hasattr(os, "fork"):
|
|
497
|
-
|
|
508
|
+
if stories_only:
|
|
509
|
+
target = (f" — stories→tasks: {', '.join(only_keys)}" if only_keys
|
|
510
|
+
else " — converting all To Do Stories → Tasks")
|
|
511
|
+
else:
|
|
512
|
+
target = f" — tickets: {', '.join(only_keys)}" if only_keys else ""
|
|
498
513
|
print(f"▶ agentos-auto started in the background{target} — it keeps running "
|
|
499
514
|
"after you close this terminal.")
|
|
500
515
|
print(f" logs: {_LOG_FILE}")
|
|
501
516
|
print(" status: agentos-auto status")
|
|
502
517
|
print(" stop: agentos-auto stop")
|
|
503
518
|
if not foreground and _daemonize():
|
|
504
|
-
_run_loop(workspace_root, only_keys) #
|
|
519
|
+
_run_loop(workspace_root, only_keys, stories_only) # detached daemon child only
|
|
505
520
|
return
|
|
506
521
|
if not foreground:
|
|
507
522
|
print("note: background mode unavailable on this platform — running in the "
|
|
@@ -510,10 +525,10 @@ def main() -> None:
|
|
|
510
525
|
# Foreground run still records a PID so stop/status can find it.
|
|
511
526
|
_AGENTOS_DIR.mkdir(parents=True, exist_ok=True)
|
|
512
527
|
_PID_FILE.write_text(str(os.getpid()))
|
|
513
|
-
_run_loop(workspace_root, only_keys)
|
|
528
|
+
_run_loop(workspace_root, only_keys, stories_only)
|
|
514
529
|
return
|
|
515
530
|
|
|
516
|
-
print(f"unknown command '{cmd}'. use: run | resume | ticket | stop | status | update")
|
|
531
|
+
print(f"unknown command '{cmd}'. use: run | resume | ticket | story | stop | status | update")
|
|
517
532
|
sys.exit(1)
|
|
518
533
|
|
|
519
534
|
|
|
File without changes
|
|
File without changes
|
{devops_bot_sdk-1.4.45 → devops_bot_sdk-1.4.47}/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
|