agent-apprenticeship 0.1.5 → 0.1.7
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.
- package/README.md +0 -197
- package/bin/agent-apprenticeship.js +85 -37
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/agent_apprenticeship_trace/__init__.py +1 -1
- package/src/agent_apprenticeship_trace/actual_outputs_normalizer.py +104 -28
- package/src/agent_apprenticeship_trace/apprentice_adapters.py +3 -1
- package/src/agent_apprenticeship_trace/artifact_resolver.py +6 -0
- package/src/agent_apprenticeship_trace/bundle_exporter.py +132 -2
- package/src/agent_apprenticeship_trace/cli.py +1229 -269
- package/src/agent_apprenticeship_trace/codex_runner.py +89 -6
- package/src/agent_apprenticeship_trace/config.py +251 -32
- package/src/agent_apprenticeship_trace/ecosystem_r2.py +515 -0
- package/src/agent_apprenticeship_trace/env.py +5 -5
- package/src/agent_apprenticeship_trace/evaluator.py +127 -11
- package/src/agent_apprenticeship_trace/grader.py +12 -11
- package/src/agent_apprenticeship_trace/learning.py +270 -1
- package/src/agent_apprenticeship_trace/llm_output_normalizer.py +8 -7
- package/src/agent_apprenticeship_trace/loop.py +103 -4
- package/src/agent_apprenticeship_trace/loop_review.py +686 -0
- package/src/agent_apprenticeship_trace/mentor_checkpoints.py +49 -21
- package/src/agent_apprenticeship_trace/openai_structured.py +84 -14
- package/src/agent_apprenticeship_trace/package_exporter.py +1 -1
- package/src/agent_apprenticeship_trace/progress.py +2 -1
- package/src/agent_apprenticeship_trace/public_run.py +369 -57
- package/src/agent_apprenticeship_trace/public_sanitizer.py +40 -3
- package/src/agent_apprenticeship_trace/rubric_generation.py +11 -10
- package/src/agent_apprenticeship_trace/schemas.py +378 -3
- package/src/agent_apprenticeship_trace/task_intake.py +43 -9
- package/src/agent_apprenticeship_trace/tdo.py +2304 -0
- package/src/agent_apprenticeship_trace/trace_normalizer.py +351 -17
- package/src/agent_apprenticeship_trace/trace_prompt.py +38 -11
- package/src/agent_apprenticeship_trace/training_signals.py +1 -1
- package/src/agent_apprenticeship_trace/verifier.py +12 -6
|
@@ -6,10 +6,12 @@ import re
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from .config import Settings, get_settings, normalize_mentor_mode
|
|
9
|
+
from .config import Settings, apprenticeship_mode_display, get_settings, normalize_apprenticeship_mode, normalize_mentor_mode
|
|
10
10
|
from .io import append_jsonl, read_json, read_jsonl, write_json
|
|
11
11
|
from .public_sanitizer import sanitize_public_obj, sanitize_public_text
|
|
12
12
|
from .release_exporter import create_release
|
|
13
|
+
from .tdo import tdo_manifest_fields_from_report
|
|
14
|
+
from .loop_review import summarize_loop_reviews
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def _count_jsonl(path: Path) -> int:
|
|
@@ -96,7 +98,7 @@ def contribution_counts(release_root: Path) -> dict[str, int]:
|
|
|
96
98
|
|
|
97
99
|
def _write_card(bundle_root: Path) -> None:
|
|
98
100
|
(bundle_root / "contribution_card.md").write_text(
|
|
99
|
-
"# Agent Apprenticeship
|
|
101
|
+
"# Agent Apprenticeship Agent Experience Package\n\n"
|
|
100
102
|
"This local bundle packages an apprenticeship session for public ecosystem contribution. "
|
|
101
103
|
"It includes session events, task instructions, traces, actual outputs, evaluation results, "
|
|
102
104
|
"and learning-data views when available.\n\n"
|
|
@@ -110,6 +112,15 @@ def _session_mentor_mode(session: dict[str, Any], settings: Settings) -> str:
|
|
|
110
112
|
return normalize_mentor_mode(session.get("mentor_mode") or session.get("evaluation_mode") or settings.mentor_mode)
|
|
111
113
|
|
|
112
114
|
|
|
115
|
+
def _session_apprenticeship_mode(session: dict[str, Any], settings: Settings) -> str:
|
|
116
|
+
return normalize_apprenticeship_mode(
|
|
117
|
+
session.get("apprenticeship_mode")
|
|
118
|
+
or session.get("mentor_mode")
|
|
119
|
+
or session.get("evaluation_mode")
|
|
120
|
+
or settings.apprenticeship_mode
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
113
124
|
def _clean_session_metadata(session: dict[str, Any], settings: Settings) -> dict[str, Any]:
|
|
114
125
|
allowed = {
|
|
115
126
|
"run_id",
|
|
@@ -128,6 +139,8 @@ def _clean_session_metadata(session: dict[str, Any], settings: Settings) -> dict
|
|
|
128
139
|
"session_status",
|
|
129
140
|
}
|
|
130
141
|
clean = {k: v for k, v in session.items() if k in allowed and v is not None}
|
|
142
|
+
clean["apprenticeship_mode"] = _session_apprenticeship_mode(session, settings)
|
|
143
|
+
clean["apprenticeship_mode_display"] = apprenticeship_mode_display(clean["apprenticeship_mode"])
|
|
131
144
|
clean["mentor_mode"] = _session_mentor_mode(session, settings)
|
|
132
145
|
return clean
|
|
133
146
|
|
|
@@ -141,6 +154,8 @@ def _copy_session_files(run_root: Path, bundle_root: Path, settings: Settings) -
|
|
|
141
154
|
shutil.copytree(run_root / "task", bundle_root / "task", dirs_exist_ok=True)
|
|
142
155
|
if (run_root / "mentor_checkpoints").exists():
|
|
143
156
|
shutil.copytree(run_root / "mentor_checkpoints", bundle_root / "mentor_checkpoints", dirs_exist_ok=True)
|
|
157
|
+
if (run_root / "loops").exists():
|
|
158
|
+
shutil.copytree(run_root / "loops", bundle_root / "loops", dirs_exist_ok=True)
|
|
144
159
|
|
|
145
160
|
|
|
146
161
|
def _copy_clean_bundle_files(release_root: Path, bundle_root: Path, include_debug: bool) -> None:
|
|
@@ -153,6 +168,9 @@ def _copy_clean_bundle_files(release_root: Path, bundle_root: Path, include_debu
|
|
|
153
168
|
_copy_jsonl_if_nonempty(release_root / "actual_outputs.jsonl", bundle_root / "outputs" / "actual_outputs.jsonl")
|
|
154
169
|
_copy_json_if_exists(release_root / "artifacts_index.json", bundle_root / "outputs" / "artifacts_index.json")
|
|
155
170
|
_copy_indexed_package_files(release_root, bundle_root)
|
|
171
|
+
_copy_tdo_outputs(release_root, bundle_root)
|
|
172
|
+
_copy_experience_compiler_outputs(release_root, bundle_root)
|
|
173
|
+
_copy_loop_review_outputs(release_root, bundle_root)
|
|
156
174
|
|
|
157
175
|
for name in [
|
|
158
176
|
"grader_results.jsonl",
|
|
@@ -214,6 +232,42 @@ def _copy_indexed_package_files(release_root: Path, bundle_root: Path) -> None:
|
|
|
214
232
|
write_json(bundle_root / "outputs" / "artifacts_index.json", rewritten)
|
|
215
233
|
|
|
216
234
|
|
|
235
|
+
def _copy_tdo_outputs(release_root: Path, bundle_root: Path) -> None:
|
|
236
|
+
package_tdo_dirs = sorted(path for path in (release_root / "packages").glob("*/tdo") if path.is_dir())
|
|
237
|
+
if not package_tdo_dirs:
|
|
238
|
+
return
|
|
239
|
+
if len(package_tdo_dirs) == 1:
|
|
240
|
+
shutil.copytree(package_tdo_dirs[0], bundle_root / "tdo", dirs_exist_ok=True)
|
|
241
|
+
return
|
|
242
|
+
for src in package_tdo_dirs:
|
|
243
|
+
target = bundle_root / "tdo" / src.parent.name
|
|
244
|
+
shutil.copytree(src, target, dirs_exist_ok=True)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _copy_experience_compiler_outputs(release_root: Path, bundle_root: Path) -> None:
|
|
248
|
+
package_dirs = sorted(path for path in (release_root / "packages").glob("*/experience_compiler") if path.is_dir())
|
|
249
|
+
if not package_dirs:
|
|
250
|
+
return
|
|
251
|
+
if len(package_dirs) == 1:
|
|
252
|
+
shutil.copytree(package_dirs[0], bundle_root / "experience_compiler", dirs_exist_ok=True)
|
|
253
|
+
return
|
|
254
|
+
for src in package_dirs:
|
|
255
|
+
target = bundle_root / "experience_compiler" / src.parent.name
|
|
256
|
+
shutil.copytree(src, target, dirs_exist_ok=True)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _copy_loop_review_outputs(release_root: Path, bundle_root: Path) -> None:
|
|
260
|
+
package_dirs = sorted(path for path in (release_root / "packages").glob("*/loops") if path.is_dir())
|
|
261
|
+
if not package_dirs:
|
|
262
|
+
return
|
|
263
|
+
if len(package_dirs) == 1:
|
|
264
|
+
shutil.copytree(package_dirs[0], bundle_root / "loops", dirs_exist_ok=True)
|
|
265
|
+
return
|
|
266
|
+
for src in package_dirs:
|
|
267
|
+
target = bundle_root / "loops" / src.parent.name
|
|
268
|
+
shutil.copytree(src, target, dirs_exist_ok=True)
|
|
269
|
+
|
|
270
|
+
|
|
217
271
|
def is_unsafe_bundle_ref(ref: str) -> bool:
|
|
218
272
|
path = Path(ref)
|
|
219
273
|
return path.is_absolute() or ".." in path.parts
|
|
@@ -263,6 +317,8 @@ def _bundle_metadata_shape(bundle_root: Path, release_root: Path, settings: Sett
|
|
|
263
317
|
"agent_apprentice_role": role,
|
|
264
318
|
"expected_economic_value": task.get("expected_economic_value"),
|
|
265
319
|
"expected_economic_value_for_agent_apprentice": task.get("expected_economic_value_for_agent_apprentice"),
|
|
320
|
+
"apprenticeship_mode": _session_apprenticeship_mode(session, settings),
|
|
321
|
+
"apprenticeship_mode_display": apprenticeship_mode_display(_session_apprenticeship_mode(session, settings)),
|
|
266
322
|
"mentor_mode": _session_mentor_mode(session, settings),
|
|
267
323
|
"task_status": task_status,
|
|
268
324
|
"run_status": run_status,
|
|
@@ -280,9 +336,83 @@ def _write_manifest(bundle_root: Path, release_root: Path, settings: Settings, i
|
|
|
280
336
|
manifest["status_reason"] = session["status_reason"]
|
|
281
337
|
if include_internal_schema:
|
|
282
338
|
manifest["source_release_schema_version"] = release_manifest.get("schema_version")
|
|
339
|
+
manifest.update(_tdo_manifest_shape(release_root))
|
|
340
|
+
manifest.update(_loop_manifest_shape(release_root))
|
|
283
341
|
write_json(bundle_root / "contribution_manifest.json", manifest)
|
|
284
342
|
|
|
285
343
|
|
|
344
|
+
def _loop_manifest_shape(release_root: Path) -> dict[str, Any]:
|
|
345
|
+
summary = summarize_loop_reviews(release_root)
|
|
346
|
+
return {
|
|
347
|
+
"has_loop_review_packets": summary.get("has_loop_review_packets"),
|
|
348
|
+
"loop_iteration_count": summary.get("loop_iteration_count"),
|
|
349
|
+
"loop_reviewer_types": summary.get("reviewer_types") or [],
|
|
350
|
+
"final_loop_verdict": summary.get("final_loop_verdict"),
|
|
351
|
+
"loop_review_refs": summary.get("loop_review_refs") or [],
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _tdo_manifest_shape(release_root: Path) -> dict[str, Any]:
|
|
356
|
+
reports = []
|
|
357
|
+
for path in sorted((release_root / "packages").glob("*/tdo/tdo_report.json")):
|
|
358
|
+
try:
|
|
359
|
+
reports.append(read_json(path))
|
|
360
|
+
except Exception:
|
|
361
|
+
continue
|
|
362
|
+
if not reports:
|
|
363
|
+
return {
|
|
364
|
+
"tdo_enabled": False,
|
|
365
|
+
"tdo_status": "not_run",
|
|
366
|
+
"tdo_output_refs": [],
|
|
367
|
+
"experience_compiler_enabled": False,
|
|
368
|
+
"experience_compiler_status": "not_run",
|
|
369
|
+
"experience_compiler_output_refs": [],
|
|
370
|
+
}
|
|
371
|
+
latest = reports[-1]
|
|
372
|
+
output_refs: list[str] = []
|
|
373
|
+
package_tdo_dirs = sorted(path for path in (release_root / "packages").glob("*/tdo") if path.is_dir())
|
|
374
|
+
if len(package_tdo_dirs) == 1:
|
|
375
|
+
for child in sorted(package_tdo_dirs[0].iterdir()):
|
|
376
|
+
if child.is_file():
|
|
377
|
+
output_refs.append(f"tdo/{child.name}")
|
|
378
|
+
else:
|
|
379
|
+
for src in package_tdo_dirs:
|
|
380
|
+
for child in sorted(src.iterdir()):
|
|
381
|
+
if child.is_file():
|
|
382
|
+
output_refs.append(f"tdo/{src.parent.name}/{child.name}")
|
|
383
|
+
fields = tdo_manifest_fields_from_report(latest)
|
|
384
|
+
fields["tdo_output_refs"] = output_refs
|
|
385
|
+
fields.update(_experience_compiler_manifest_shape(release_root, latest))
|
|
386
|
+
if len(reports) > 1:
|
|
387
|
+
fields["tdo_package_count"] = len(reports)
|
|
388
|
+
return fields
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def _experience_compiler_manifest_shape(release_root: Path, latest_report: dict[str, Any]) -> dict[str, Any]:
|
|
392
|
+
compiler_dirs = sorted(path for path in (release_root / "packages").glob("*/experience_compiler") if path.is_dir())
|
|
393
|
+
refs: list[str] = []
|
|
394
|
+
if len(compiler_dirs) == 1:
|
|
395
|
+
for child in sorted(compiler_dirs[0].rglob("*")):
|
|
396
|
+
if child.is_file():
|
|
397
|
+
refs.append(f"experience_compiler/{child.relative_to(compiler_dirs[0]).as_posix()}")
|
|
398
|
+
else:
|
|
399
|
+
for src in compiler_dirs:
|
|
400
|
+
for child in sorted(src.rglob("*")):
|
|
401
|
+
if child.is_file():
|
|
402
|
+
refs.append(f"experience_compiler/{src.parent.name}/{child.relative_to(src).as_posix()}")
|
|
403
|
+
return {
|
|
404
|
+
"experience_compiler_enabled": bool(compiler_dirs),
|
|
405
|
+
"experience_compiler_status": latest_report.get("tdo_status"),
|
|
406
|
+
"experience_compiler_id": str(latest_report.get("tdo_id") or "").replace("tdo_", "compiler_", 1),
|
|
407
|
+
"experience_compiler_output_refs": refs,
|
|
408
|
+
"experience_compiler_rows_by_type": latest_report.get("rows_accepted_by_type") or {},
|
|
409
|
+
"experience_compiler_rounds_run": latest_report.get("rounds_run"),
|
|
410
|
+
"experience_compiler_average_quality_score": latest_report.get("average_quality_score"),
|
|
411
|
+
"experience_compiler_average_reuse_value_score": latest_report.get("average_reuse_value_score"),
|
|
412
|
+
"experience_compiler_judge_source": latest_report.get("tdo_judge_source"),
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
286
416
|
def create_contribution_bundle(
|
|
287
417
|
run_root: Path,
|
|
288
418
|
bundle_root: Path | None = None,
|