This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 3.3 kB View raw
1"""Issue session context injected before the agent runs (no issue-fetch tools).""" 2 3from __future__ import annotations 4 5import json 6from dataclasses import asdict, dataclass, field 7from typing import Any 8 9 10@dataclass 11class IssueSessionContext: 12 """Everything the caller already knows about the issue + repo.""" 13 14 issue_uri: str 15 issue_rkey: str 16 title: str 17 body: str 18 state: str 19 author_did: str 20 author_handle: str 21 repo_did: str 22 repo_owner_handle: str 23 repo_name: str 24 knot_hostname: str 25 # Repo paths relative to root (provided by caller — primary navigation aid). 26 file_tree: list[str] = field(default_factory=list) 27 ref: str = "HEAD" 28 extra: dict[str, Any] = field(default_factory=dict) 29 30 @classmethod 31 def from_dict(cls, data: dict[str, Any]) -> IssueSessionContext: 32 known = {f.name for f in cls.__dataclass_fields__.values()} # type: ignore[attr-defined] 33 core = {k: v for k, v in data.items() if k in known and k != "extra"} 34 extra = dict(data.get("extra") or {}) 35 for k, v in data.items(): 36 if k not in known: 37 extra[k] = v 38 return cls(**core, extra=extra) 39 40 def to_dict(self) -> dict[str, Any]: 41 payload = asdict(self) 42 extra = payload.pop("extra", {}) 43 if extra: 44 payload.update(extra) 45 return payload 46 47 48ISSUE_AGENT_SYSTEM_PROMPT = """\ 49You investigate a single Tangled issue. The issue metadata, repo identifiers, and 50repository file tree are already provided below — do not ask the user to resolve 51handles or DIDs. 52 53Your job: 541. Read the issue title/body and identify which files are relevant. 552. Use ``read_repo_file`` to pull exact source from the knot when you need code. 563. Use ``list_repo_files`` only if the provided file tree is incomplete or you 57 need to explore a subdirectory that was not listed. 58 59Rules: 60- Prefer paths from the provided file tree. 61- Read the smallest set of files needed to answer well. 62- Cite file paths when referencing code. 63- You cannot file issues, push code, or browse outside this repo. 64""" 65 66 67def format_issue_context_block(ctx: IssueSessionContext) -> str: 68 """Serialize session context for the system prompt (cache-friendly static prefix).""" 69 tree = ctx.file_tree 70 if len(tree) > 500: 71 tree_display = tree[:500] + [f"... (+{len(tree) - 500} more paths)"] 72 else: 73 tree_display = tree 74 75 block = { 76 "issue": { 77 "uri": ctx.issue_uri, 78 "rkey": ctx.issue_rkey, 79 "title": ctx.title, 80 "body": ctx.body, 81 "state": ctx.state, 82 "author": {"did": ctx.author_did, "handle": ctx.author_handle}, 83 }, 84 "repo": { 85 "did": ctx.repo_did, 86 "owner_handle": ctx.repo_owner_handle, 87 "name": ctx.repo_name, 88 "knot_hostname": ctx.knot_hostname, 89 "ref": ctx.ref, 90 }, 91 "file_tree": tree_display, 92 } 93 if ctx.extra: 94 block["extra"] = ctx.extra 95 return json.dumps(block, indent=2, ensure_ascii=False) 96 97 98def build_issue_system_prompt(ctx: IssueSessionContext) -> str: 99 return ( 100 f"{ISSUE_AGENT_SYSTEM_PROMPT}\n\n" 101 f"## Session context (issue + repo)\n\n" 102 f"```json\n{format_issue_context_block(ctx)}\n```" 103 )