agent-apprenticeship 0.1.0 → 0.1.1

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.
@@ -34,20 +34,50 @@ function runCandidate(command, args) {
34
34
  });
35
35
  }
36
36
 
37
- function pythonIsUsable(command) {
37
+ function pythonCheck(command) {
38
38
  const check = runCandidate(command, [
39
39
  "-c",
40
40
  "import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)"
41
41
  ]);
42
- return !check.error && check.status === 0;
42
+ return {
43
+ usable: !check.error && check.status === 0,
44
+ error: check.error ? String(check.error.message || check.error) : null,
45
+ status: check.status
46
+ };
43
47
  }
44
48
 
45
49
  function findPython() {
46
- const candidates = [];
47
- if (process.env.AA_PYTHON) candidates.push(process.env.AA_PYTHON);
48
- candidates.push("python3", "python");
50
+ if (process.env.AA_PYTHON) {
51
+ const candidate = expandHome(process.env.AA_PYTHON);
52
+ const check = pythonCheck(candidate);
53
+ if (check.usable) return candidate;
54
+ console.error("AA_PYTHON is set but does not point to Python 3.11 or newer.");
55
+ console.error(`AA_PYTHON=${candidate}`);
56
+ console.error("");
57
+ console.error("Agent Apprenticeship requires Python 3.11 or newer.");
58
+ console.error("");
59
+ console.error("macOS Homebrew:");
60
+ console.error("brew install python@3.11");
61
+ console.error("");
62
+ console.error("Or set:");
63
+ console.error("AA_PYTHON=/path/to/python3.11");
64
+ process.exit(1);
65
+ }
66
+ const candidates = [
67
+ "python3.13",
68
+ "python3.12",
69
+ "python3.11",
70
+ "/opt/homebrew/bin/python3.13",
71
+ "/opt/homebrew/bin/python3.12",
72
+ "/opt/homebrew/bin/python3.11",
73
+ "/usr/local/bin/python3.13",
74
+ "/usr/local/bin/python3.12",
75
+ "/usr/local/bin/python3.11",
76
+ "python3",
77
+ "python"
78
+ ];
49
79
  for (const candidate of candidates) {
50
- if (pythonIsUsable(candidate)) return candidate;
80
+ if (pythonCheck(candidate).usable) return candidate;
51
81
  }
52
82
  return null;
53
83
  }
@@ -120,7 +150,12 @@ function runCli(python, args, usePackagedSource) {
120
150
  const python = findPython();
121
151
  if (!python) {
122
152
  console.error("Agent Apprenticeship requires Python 3.11 or newer.");
123
- console.error("Install python3 or set AA_PYTHON=/path/to/python.");
153
+ console.error("");
154
+ console.error("macOS Homebrew:");
155
+ console.error("brew install python@3.11");
156
+ console.error("");
157
+ console.error("Or set:");
158
+ console.error("AA_PYTHON=/path/to/python3.11");
124
159
  process.exit(1);
125
160
  }
126
161
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-apprenticeship",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "The living ecosystem for AI agents learning from real-world work through iterative loops and training-signal exchange.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-apprenticeship"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Open framework for turning real agent work into transferable agent experience"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,2 +1,2 @@
1
1
  """Agent Apprenticeship framework."""
2
- __version__ = "0.1.0"
2
+ __version__ = "0.1.1"
@@ -289,7 +289,7 @@ def _configure_detected_model_provider(row: dict) -> None:
289
289
  )
290
290
 
291
291
 
292
- def _first_run_setup(*, interactive: bool) -> None:
292
+ def _first_run_setup(*, interactive: bool, defaults: bool=False) -> None:
293
293
  detected_agents = _detect_apprentice_agents()
294
294
  typer.echo("")
295
295
  if detected_agents:
@@ -298,7 +298,10 @@ def _first_run_setup(*, interactive: bool) -> None:
298
298
  typer.echo(f"{idx}. {row['display_name']} - command found ({row['command']})")
299
299
  custom_index = len(detected_agents) + 1
300
300
  typer.echo(f"{custom_index}. Custom - use a custom command template")
301
- if interactive:
301
+ if defaults:
302
+ _configure_detected_apprentice_agent(detected_agents[0])
303
+ typer.echo(f"Configured Apprentice Agent: {detected_agents[0]['display_name']}")
304
+ elif interactive:
302
305
  choice = _choose_detected_index(custom_index, default=1)
303
306
  if choice and choice <= len(detected_agents):
304
307
  _configure_detected_apprentice_agent(detected_agents[choice - 1])
@@ -318,7 +321,10 @@ def _first_run_setup(*, interactive: bool) -> None:
318
321
  typer.echo("Detected Mentor Model Provider keys:")
319
322
  for idx, row in enumerate(detected_providers, 1):
320
323
  typer.echo(f"{idx}. {row['display_name']} - {row['api_key_env_var']} visible")
321
- if interactive:
324
+ if defaults:
325
+ _configure_detected_model_provider(detected_providers[0])
326
+ typer.echo(f"Configured Mentor Model Provider: {detected_providers[0]['display_name']}")
327
+ elif interactive:
322
328
  choice = _choose_detected_index(len(detected_providers), default=1)
323
329
  if choice:
324
330
  _configure_detected_model_provider(detected_providers[choice - 1])
@@ -641,10 +647,13 @@ def _ensure_apprentice_agent_ready(settings, runner: str | None=None, interactiv
641
647
  def init(
642
648
  overwrite: bool=typer.Option(False, help='Replace existing settings.json with defaults.'),
643
649
  setup: bool=typer.Option(False, '--setup', help='Detect installed Apprentice Agents and Mentor Model Provider keys.'),
650
+ defaults: bool=typer.Option(False, '--defaults', '--non-interactive', help='Initialize with deterministic defaults and never prompt.'),
644
651
  ):
645
652
  path=init_settings(overwrite=overwrite)
646
653
  typer.echo(f'initialized Agent Apprenticeship settings at {path}')
647
- if setup or sys.stdin.isatty():
654
+ if defaults:
655
+ _first_run_setup(interactive=False, defaults=True)
656
+ elif setup or sys.stdin.isatty():
648
657
  _first_run_setup(interactive=bool(setup or sys.stdin.isatty()))
649
658
 
650
659
  @app.command('settings')
@@ -2812,27 +2821,27 @@ def bundle_contribute(path: Path=typer.Argument(..., help='Contribution Bundle f
2812
2821
  typer.echo('View files:')
2813
2822
  typer.echo(f'open {path}')
2814
2823
 
2815
- @app.command('init-env')
2824
+ @app.command('init-env', hidden=True)
2816
2825
  def init_env():
2817
2826
  dst=Path('.env.local')
2818
2827
  if not dst.exists(): shutil.copyfile('.env.example', dst); typer.echo('created .env.local from .env.example')
2819
2828
  else: typer.echo('.env.local already exists')
2820
2829
 
2821
- @app.command('run-task')
2830
+ @app.command('run-task', hidden=True)
2822
2831
  def run_task(input: Path=typer.Option(Path('data/seed_tasks/hard_finance_reconciliation.jsonl')), output_root: Path=Path('outputs'), runner: str='deterministic'):
2823
2832
  raw=RawTaskRecord.model_validate(read_jsonl(input)[0])
2824
2833
  run_root=output_root/'runs'/'single'
2825
2834
  pkg=run_one(raw, run_root, runner=runner); typer.echo(str(pkg))
2826
2835
 
2827
- @app.command('run-batch')
2836
+ @app.command('run-batch', hidden=True)
2828
2837
  def run_batch(input: Path=typer.Option(...), limit: int|None=None, resume: bool=False, max_parallel: int=1, retry_limit: int=0, task_timeout_seconds: int=900, runner: str='deterministic', release_id: str|None=None, output_root: Path=Path('outputs'), max_iterations: int|None=None):
2829
2838
  typer.echo(str(run_batch_impl(input, output_root, limit, resume, max_parallel, retry_limit, task_timeout_seconds, runner, release_id, max_iterations=max_iterations)))
2830
2839
 
2831
- @app.command('run-many')
2840
+ @app.command('run-many', hidden=True)
2832
2841
  def run_many(input: Path=typer.Option(...), limit: int|None=None, resume: bool=False, max_parallel: int=1, retry_limit: int=0, task_timeout_seconds: int=900, runner: str='deterministic', release_id: str|None=None, output_root: Path=Path('outputs'), max_iterations: int|None=None):
2833
2842
  typer.echo(str(run_batch_impl(input, output_root, limit, resume, max_parallel, retry_limit, task_timeout_seconds, runner, release_id, max_iterations=max_iterations)))
2834
2843
 
2835
- @app.command('create-bundle')
2844
+ @app.command('create-bundle', hidden=True)
2836
2845
  def create_bundle(
2837
2846
  run_root: Path=typer.Option(...),
2838
2847
  bundle_root: Path|None=typer.Option(None),
@@ -2841,15 +2850,15 @@ def create_bundle(
2841
2850
  ):
2842
2851
  typer.echo(str(create_contribution_bundle(run_root, bundle_root, include_debug=include_debug, release_style=release_style)))
2843
2852
 
2844
- @app.command('create-release')
2853
+ @app.command('create-release', hidden=True)
2845
2854
  def create_release(run_root: Path=typer.Option(Path('outputs/runs/single')), release_root: Path=typer.Option(Path('outputs/releases/manual'))):
2846
2855
  typer.echo(str(create_release_impl(run_root, release_root)))
2847
2856
 
2848
- @app.command('validate-release')
2857
+ @app.command('validate-release', hidden=True)
2849
2858
  def validate_release(release_root: Path=typer.Option(...)):
2850
2859
  c=validate_release_impl(release_root); typer.echo(format_counters(c)); raise typer.Exit(0 if c['release_valid'] else 1)
2851
2860
 
2852
- @app.command('validate-public-release')
2861
+ @app.command('validate-public-release', hidden=True)
2853
2862
  def validate_public_release(release_root: Path=typer.Option(...)):
2854
2863
  public=release_root/'public' if (release_root/'public').exists() else release_root
2855
2864
  c=validate_release_impl(release_root if (release_root/'public').exists() else release_root.parent) if public.name == 'public' else validate_release_impl(release_root)
@@ -2857,7 +2866,7 @@ def validate_public_release(release_root: Path=typer.Option(...)):
2857
2866
  raise typer.Exit(0 if c.get('public_release_valid') else 1)
2858
2867
 
2859
2868
 
2860
- @app.command('repair-roles')
2869
+ @app.command('repair-roles', hidden=True)
2861
2870
  def repair_roles(run_root: Path=typer.Option(...), task_id: str=typer.Option(...), roles: str=typer.Option('evaluator_agent,grader_agent,verifier_agent'), attempts: str=typer.Option('baseline,revised'), rebuild_release: Path|None=typer.Option(None)):
2862
2871
  """Re-run model evaluation roles from existing task package artifacts/traces."""
2863
2872
  from .schemas import RubricSpec, ActualOutputs, AgentTrace, GraderResult, VerifierResult
@@ -2916,7 +2925,7 @@ def repair_roles(run_root: Path=typer.Option(...), task_id: str=typer.Option(...
2916
2925
  typer.echo(f'rebuilt release={rebuild_release}')
2917
2926
 
2918
2927
 
2919
- @app.command('summarize-releases')
2928
+ @app.command('summarize-releases', hidden=True)
2920
2929
  def summarize_releases(release_root: Path=typer.Option(Path('outputs/releases')), pattern: str=typer.Option('tasks-*')):
2921
2930
  """Summarize release readiness across a release directory."""
2922
2931
  from .validation import validate_release
@@ -2952,17 +2961,17 @@ def summarize_releases(release_root: Path=typer.Option(Path('outputs/releases'))
2952
2961
  typer.echo('task_ids_publishable_with_warnings=' + ','.join(warnings))
2953
2962
  typer.echo('task_ids_clean_publishable=' + ','.join(clean))
2954
2963
 
2955
- @app.command('inspect-trace')
2964
+ @app.command('inspect-trace', hidden=True)
2956
2965
  def inspect_trace(trace_path: Path):
2957
2966
  t=AgentTrace.model_validate_json(trace_path.read_text()); typer.echo(f'trace_id={t.trace_id}\ntask_id={t.task_id}\nsteps={len(t.steps)}')
2958
2967
 
2959
- @app.command('codex-smoke')
2968
+ @app.command('codex-smoke', hidden=True)
2960
2969
  def codex_smoke():
2961
2970
  if not shutil.which('codex'):
2962
2971
  typer.echo('codex_available=false'); raise typer.Exit(1)
2963
2972
  typer.echo('codex_available=true')
2964
2973
 
2965
- @app.command('llm-smoke')
2974
+ @app.command('llm-smoke', hidden=True)
2966
2975
  def llm_smoke(
2967
2976
  output_dir: Path=Path('outputs/llm_smoke'),
2968
2977
  provider: str | None=typer.Option(None, '--provider', help='Mentor Model Provider id to test. Defaults to configured provider.'),