d3-mini-agentcode / extractor /make_state.py
stonefish-labs's picture
d3-mini-agentcode v0.1-preview (pre-release)
21a9138 verified
Raw History Blame Contribute Delete
3.02 kB
"""Build the model's input state exactly as in training and evaluation.
python make_state.py diff CHANGE.diff --task-file TASK.txt [--baseline-file BASELINE.txt]
python make_state.py snippet CODE.py --lang py --task "Clean up the build cache"
Prints the state. Use it as `state=` in `model.system_one(...)` (see ../examples/usage.py).
"""
import argparse
import sys
from collections import Counter, defaultdict
from pathlib import Path
from behaviour import analyse_diff, analyse_snippet
BUDGET_CHARS = 8192 * 3 # ≈ 8k tokens; longer changes are cut with a marker, as in training
def summary(rep):
t = (rep or {}).get("text") or ""
return t.strip() or "(no security-relevant behaviour found)"
def baseline_text(counter_by_kind):
"""Repository baseline: the most common operands per behaviour kind across the repo's ordinary changes."""
if not counter_by_kind:
return "(no repository history available)"
lines = []
for kind in sorted(counter_by_kind):
top = counter_by_kind[kind].most_common(8)
lines.append(f"- {kind}: " + "; ".join(f"{op} ({n})" for op, n in top))
return "\n".join(lines)
def add_to_baseline(acc, rep):
"""Accumulate one ordinary change's report into acc (a defaultdict(Counter)) for baseline_text."""
for b in (rep or {}).get("behaviours", []):
acc[b["kind"]][str(b.get("operand") or b.get("path") or "?")[:80]] += 1
def new_baseline():
return defaultdict(Counter)
def state(task, baseline, beh, change):
parts = [f"Task:\n{(task or '(not provided)').strip()}",
f"Repository baseline (normal behaviour of this repo/org):\n{baseline}",
f"Behaviour summary (automated, not a verdict):\n{beh}"]
head = "\n\n".join(parts) + "\n\nChange:\n"
room = BUDGET_CHARS - len(head)
if len(change) > room:
change = change[:max(room - 80, 0)] + f"\n[... {len(change) - room + 80} more characters omitted]"
return head + change
def main(argv=None):
ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
ap.add_argument("mode", choices=("diff", "snippet"))
ap.add_argument("input", help="file, or - for stdin")
ap.add_argument("--task"); ap.add_argument("--task-file")
ap.add_argument("--baseline-file", help="precomputed baseline text (default: no repository history)")
ap.add_argument("--lang", choices=("js", "ts", "py", "sh"), help="snippet language")
a = ap.parse_args(argv)
change = sys.stdin.read() if a.input == "-" else Path(a.input).read_text(encoding="utf-8", errors="replace")
task = a.task or (Path(a.task_file).read_text(errors="replace") if a.task_file else None)
rep = analyse_diff(change, task=task) if a.mode == "diff" else analyse_snippet(change, lang=a.lang, task=task)
base = Path(a.baseline_file).read_text().strip() if a.baseline_file else baseline_text(None)
print(state(task, base, summary(rep), change))
return 0
if __name__ == "__main__":
sys.exit(main())