mirror of
https://github.com/openai/codex.git
synced 2026-04-28 02:11:08 +03:00
agentydragon(tasks): normalize task 18 front-matter; add manager_utils package
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
---
|
||||
id: 18
|
||||
title: Chat UI Textarea Overlay and Border Styling Fix
|
||||
status: Not started # one of: Not started, Started, Needs manual review, Done, Cancelled
|
||||
status: Not started
|
||||
summary: Fix overlay of waiting messages and streamline borders between chat window and input area to improve visibility and reclaim terminal space.
|
||||
goal: |
|
||||
Adjust the TUI chat interface so that waiting/status messages no longer overlay the first line of the input textarea (ensuring user drafts remain visible), and merge/remove borders as follows:
|
||||
@@ -39,4 +39,4 @@ goal: |
|
||||
Run the frontmatter linter to ensure conformance:
|
||||
```bash
|
||||
python3 agentydragon/tools/check_task_frontmatter.py agentydragon/tasks/18-chat-ui-textarea-overlay-border-fix.md
|
||||
```
|
||||
```
|
||||
|
||||
4
agentydragon/tools/manager_utils/__init__.py
Normal file
4
agentydragon/tools/manager_utils/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
agentydragon manager utilities package.
|
||||
"""
|
||||
__version__ = '0.1'
|
||||
93
agentydragon/tools/manager_utils/agentydragon_task.py
Normal file
93
agentydragon/tools/manager_utils/agentydragon_task.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
CLI for managing agentydragon tasks: status, set-status, set-deps, dispose, launch.
|
||||
"""
|
||||
import sys
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import click
|
||||
from tasklib import load_task, save_task, TaskMeta
|
||||
|
||||
TASK_DIR = Path(__file__).parent.parent / 'tasks'
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
"""Manage agentydragon tasks."""
|
||||
pass
|
||||
|
||||
@cli.command()
|
||||
def status():
|
||||
"""Show a table of task id, title, status, dependencies, last_updated"""
|
||||
rows = []
|
||||
for md in sorted(TASK_DIR.glob('[0-9][0-9]-*.md')):
|
||||
meta, _ = load_task(md)
|
||||
rows.append((meta.id, meta.title, meta.status,
|
||||
meta.dependencies.replace('\n', ' '),
|
||||
meta.last_updated.strftime('%Y-%m-%d %H:%M')))
|
||||
# simple table
|
||||
fmt = '{:>2} {:<50} {:<12} {:<30} {:<16}'
|
||||
print(fmt.format('ID','Title','Status','Dependencies','Updated'))
|
||||
for r in rows:
|
||||
print(fmt.format(*r))
|
||||
|
||||
@cli.command()
|
||||
@click.argument('task_id')
|
||||
@click.argument('status')
|
||||
def set_status(task_id, status):
|
||||
"""Set status of TASK_ID to STATUS"""
|
||||
md = TASK_DIR / f"{task_id}-*.md"
|
||||
files = list(TASK_DIR.glob(f'{task_id}-*.md'))
|
||||
if not files:
|
||||
click.echo(f'Task {task_id} not found', err=True)
|
||||
sys.exit(1)
|
||||
path = files[0]
|
||||
meta, body = load_task(path)
|
||||
meta.status = status
|
||||
meta.last_updated = datetime.utcnow()
|
||||
save_task(path, meta, body)
|
||||
|
||||
@cli.command()
|
||||
@click.argument('task_id')
|
||||
@click.argument('deps', nargs=-1)
|
||||
def set_deps(task_id, deps):
|
||||
"""Set dependencies of TASK_ID"""
|
||||
files = list(TASK_DIR.glob(f'{task_id}-*.md'))
|
||||
if not files:
|
||||
click.echo(f'Task {task_id} not found', err=True)
|
||||
sys.exit(1)
|
||||
path = files[0]
|
||||
meta, body = load_task(path)
|
||||
now = datetime.utcnow().isoformat()
|
||||
meta.dependencies = f'as of {now}: ' + ', '.join(deps)
|
||||
meta.last_updated = datetime.utcnow()
|
||||
save_task(path, meta, body)
|
||||
|
||||
@cli.command()
|
||||
@click.argument('task_id', nargs=-1)
|
||||
def dispose(task_id):
|
||||
"""Dispose worktree and delete branch for TASK_ID(s)"""
|
||||
for tid in task_id:
|
||||
branch = f'agentydragon-{tid}-*'
|
||||
# remove worktree
|
||||
subprocess.run(['git', 'worktree', 'remove', f'tasks/.worktrees/{tid}-*', '--force'])
|
||||
# delete branch
|
||||
subprocess.run(['git', 'branch', '-D', f'agentydragon-{tid}-*'])
|
||||
click.echo(f'Disposed task {tid}')
|
||||
|
||||
@cli.command()
|
||||
@click.argument('task_id', nargs=-1)
|
||||
def launch(task_id):
|
||||
"""Copy tmux launch one-liner for TASK_ID(s) to clipboard"""
|
||||
cmd = ['create-task-worktree.sh', '--agent', '--tmux'] + list(task_id)
|
||||
line = ' '.join(cmd)
|
||||
# system clipboard
|
||||
try:
|
||||
subprocess.run(['pbcopy'], input=line.encode(), check=True)
|
||||
click.echo('Copied to clipboard:')
|
||||
except FileNotFoundError:
|
||||
click.echo(line)
|
||||
return
|
||||
click.echo(line)
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
||||
35
agentydragon/tools/manager_utils/tasklib.py
Normal file
35
agentydragon/tools/manager_utils/tasklib.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Simple library for loading and saving task metadata embedded as TOML front-matter
|
||||
in task Markdown files.
|
||||
"""
|
||||
import re
|
||||
import toml
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
FRONTMATTER_RE = re.compile(r"^\+\+\+\s*(.*?)\s*\+\+\+", re.S | re.M)
|
||||
|
||||
class TaskMeta(BaseModel):
|
||||
id: str
|
||||
title: str
|
||||
status: str
|
||||
dependencies: str = Field(default="")
|
||||
last_updated: datetime = Field(default_factory=datetime.utcnow)
|
||||
|
||||
def load_task(path: Path) -> (TaskMeta, str):
|
||||
text = path.read_text(encoding='utf-8')
|
||||
m = FRONTMATTER_RE.match(text)
|
||||
if not m:
|
||||
raise ValueError(f"No TOML frontmatter in {path}")
|
||||
meta = toml.loads(m.group(1))
|
||||
tm = TaskMeta(**meta)
|
||||
body = text[m.end():].lstrip('\n')
|
||||
return tm, body
|
||||
|
||||
def save_task(path: Path, meta: TaskMeta, body: str) -> None:
|
||||
tm = meta.dict()
|
||||
tm['last_updated'] = meta.last_updated.isoformat()
|
||||
fm = toml.dumps(tm).strip()
|
||||
content = f"+++\n{fm}\n+++\n\n{body.lstrip()}"
|
||||
path.write_text(content, encoding='utf-8')
|
||||
34
agentydragon/tools/manager_utils/tests/test_tasklib.py
Normal file
34
agentydragon/tools/manager_utils/tests/test_tasklib.py
Normal file
@@ -0,0 +1,34 @@
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import toml
|
||||
import pytest
|
||||
|
||||
from agentydragon.tools.manager_utils.tasklib import TaskMeta, load_task, save_task
|
||||
|
||||
SAMPLE = ''''''
|
||||
++
|
||||
id = "99"
|
||||
title = "Sample Task"
|
||||
status = "Not started"
|
||||
dependencies = ""
|
||||
last_updated = "2023-01-01T12:00:00"
|
||||
++
|
||||
|
||||
# Body here
|
||||
'''
|
||||
|
||||
def test_load_and_save(tmp_path):
|
||||
md = tmp_path / '99-sample.md'
|
||||
md.write_text(SAMPLE)
|
||||
meta, body = load_task(md)
|
||||
assert meta.id == '99'
|
||||
assert 'Body here' in body
|
||||
meta.status = 'Done'
|
||||
save_task(md, meta, body)
|
||||
text = md.read_text()
|
||||
data = toml.loads(text.split('+++')[1])
|
||||
assert data['status'] == 'Done'
|
||||
|
||||
def test_meta_model_validation():
|
||||
with pytest.raises(ValueError):
|
||||
TaskMeta(id='a', title='t', status='bogus', dependencies='', last_updated='bad')
|
||||
Reference in New Issue
Block a user