agent-apprenticeship 0.1.4 → 0.1.6

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 CHANGED
@@ -1,5 +1,3 @@
1
- # Agent Apprenticeship
2
-
3
1
  The living ecosystem where AI agents learn from real-world work through iterative workflow loops, reusable experience, and collective training signal exchange.
4
2
 
5
3
  As agents move into long-horizon, economically valuable work, Agent Apprenticeship creates the open infrastructure where real-world tasks generate reusable learning signals and complex workflows advance through agent loops that turn execution into shared improvement.
@@ -11,198 +9,3 @@ Agent Apprenticeship is built for iterative workflow loops across domains, from
11
9
  Agent Apprenticeship is now available for anyone to start using with local agents including Codex, Cursor, Claude Code, OpenClaw, OpenCode, Hermes Agent, and custom agents, alongside different model providers. Users can run automated agent workflow loops locally, contribute agent learning signals back to the ecosystem, and use shared ecosystem signals to improve their own agents.
12
10
 
13
11
  Agent Apprenticeship is about the future of work and the economic value of agents. For every task executed through Agent Apprenticeship, the system can estimate task-level economic value, especially across specialized domains. It is built for everyday use to improve agent performance and outcome quality, while enabling users to exchange agent work experience with each other and with domain-expert-led agents in one living ecosystem.
14
-
15
- ## Install
16
-
17
- ```bash
18
- npx agent-apprenticeship init
19
- ```
20
-
21
- ```bash
22
- npm install -g agent-apprenticeship
23
- apprentice init
24
- ```
25
-
26
- The installed command is:
27
-
28
- ```bash
29
- apprentice
30
- ```
31
-
32
- The long-form command also remains available:
33
-
34
- ```bash
35
- agent-apprenticeship
36
- ```
37
-
38
- ## Quickstart
39
-
40
- ```bash
41
- apprentice init
42
- apprentice settings
43
- apprentice run "Create a short market map for AI procurement tools."
44
- ```
45
-
46
- Runs print the artifacts path and Contribution Bundle path.
47
-
48
- ```bash
49
- apprentice ecosystem contribute <bundle_path>
50
- ```
51
-
52
- Public ecosystem:
53
-
54
- https://github.com/Forsy-AI/agent-apprenticeship
55
-
56
- ## Apprentice Agents
57
-
58
- Selected v0 Apprentice Agents:
59
-
60
- * Codex
61
- * Cursor
62
- * Claude Code
63
- * OpenClaw
64
- * OpenCode
65
- * Hermes Agent
66
- * Custom
67
-
68
- Agent Apprenticeship auto-detects installed CLIs. If multiple are detected, choose one during setup.
69
-
70
- Custom lets you provide a command template:
71
-
72
- ```bash
73
- apprentice configure agent custom --command-template "my-agent run --workspace {workspace} --prompt-file {prompt_file}"
74
- ```
75
-
76
- ## Mentor Model Providers
77
-
78
- Store local keys in:
79
-
80
- ```text
81
- ~/.agent-apprenticeship/.env.local
82
- ```
83
-
84
- Example:
85
-
86
- ```bash
87
- OPENAI_API_KEY=""
88
- ANTHROPIC_API_KEY=""
89
- GEMINI_API_KEY=""
90
- OPENROUTER_API_KEY=""
91
- ```
92
-
93
- Configure:
94
-
95
- ```bash
96
- apprentice configure model
97
- apprentice doctor
98
- ```
99
-
100
- ## Mentor Modes
101
-
102
- ```bash
103
- apprentice run "..." --mentor-mode model-assisted
104
- apprentice run "..." --mentor-mode expert-led
105
- apprentice run "..." --mentor-mode hybrid
106
- ```
107
-
108
- * `model-assisted`: Mentor Model Provider handles the mentor loop.
109
- * `expert-led`: human expert checkpoints guide the mentor loop.
110
- * `hybrid`: Mentor Model Provider drafts and human expert checkpoints approve or edit.
111
-
112
- ## Seed Dataset
113
-
114
- The seed dataset is included under:
115
-
116
- ```text
117
- seed_dataset/
118
- ```
119
-
120
- Explore seed tasks:
121
-
122
- ```bash
123
- apprentice ecosystem list
124
- apprentice ecosystem search cloud
125
- apprentice ecosystem inspect aa-seed-task-501
126
- apprentice ecosystem pull aa-seed-task-501
127
- ```
128
-
129
- ## Ecosystem Learning
130
-
131
- Create Experience Packs from ecosystem experience:
132
-
133
- ```bash
134
- apprentice learn create aa-seed-task-501
135
- apprentice learn preview <pack_id>
136
- apprentice learn replay <pack_id>
137
- apprentice learn keep <pack_id>
138
- apprentice run "Create a related incident response checklist." --experience-pack <pack_id>
139
- apprentice learn revert <pack_id>
140
- ```
141
-
142
- Use active packs explicitly:
143
-
144
- ```bash
145
- apprentice run "..." --use-active-experience-packs
146
- apprentice run "..." --no-experience-packs
147
- ```
148
-
149
- ## Contribution Bundles
150
-
151
- Runs produce Contribution Bundles.
152
-
153
- Contribute one to the public ecosystem:
154
-
155
- ```bash
156
- apprentice ecosystem contribute <bundle_path>
157
- apprentice bundle contribute <bundle_path>
158
- ```
159
-
160
- Public ecosystem:
161
-
162
- https://github.com/Forsy-AI/agent-apprenticeship
163
-
164
- ## Ecosystem Auto-Share
165
-
166
- Default mode is Manual.
167
-
168
- ```bash
169
- apprentice ecosystem configure --repo Forsy-AI/agent-apprenticeship
170
- apprentice ecosystem configure --auto-share manual
171
- apprentice ecosystem configure --auto-share ask
172
- apprentice ecosystem configure --auto-share automatic
173
- apprentice ecosystem status
174
- ```
175
-
176
- Requirements:
177
-
178
- * GitHub CLI installed
179
- * `gh` authenticated
180
- * ecosystem repo configured
181
-
182
- ## Search, Inspect, Pull
183
-
184
- Discover and export ecosystem experience:
185
-
186
- ```bash
187
- apprentice ecosystem search <query>
188
- apprentice ecosystem inspect <id>
189
- apprentice ecosystem pull <id>
190
- ```
191
-
192
- ## Public Repo Structure
193
-
194
- ```text
195
- seed_dataset/
196
- ecosystem/
197
- ecosystem/contributions/
198
- schemas/
199
- examples/
200
- ```
201
-
202
- ## Development Commands
203
-
204
- ```bash
205
- .venv/bin/python -m pytest -q tests
206
- PYTHONPATH=src .venv/bin/python -m compileall -q src tests scripts examples
207
- bash scripts/export_public_repo.sh
208
- ```
@@ -120,7 +120,7 @@ function runQuiet(command, args, label, timeoutMs) {
120
120
  console.error(message);
121
121
  }
122
122
  const out = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
123
- if (out) console.error(out.slice(-4000));
123
+ if (out) console.error(out.slice(-8000));
124
124
  process.exit(result.status || 1);
125
125
  }
126
126
  }
@@ -157,10 +157,10 @@ function ensureRuntime(python) {
157
157
  runQuiet(python, ["-m", "venv", venvDir], "create the Python environment", 120000);
158
158
  runQuiet(py, [
159
159
  "-m", "pip", "install",
160
- "-q",
161
160
  "--disable-pip-version-check",
162
161
  "--progress-bar", "off",
163
162
  "--no-input",
163
+ "--no-build-isolation",
164
164
  "--retries", "10",
165
165
  "--timeout", "60",
166
166
  packageRoot
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-apprenticeship",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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,14 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-apprenticeship"
7
- version = "0.1.4"
7
+ version = "0.1.6"
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"
11
- dependencies = ["pydantic>=2", "typer>=0.12", "openai>=1.0"]
11
+ dependencies = ["pydantic>=2.7,<3", "typer>=0.12,<1", "openai>=2,<3"]
12
12
 
13
13
  [project.optional-dependencies]
14
- llm = ["openai>=1.0"]
14
+ llm = ["openai>=2,<3"]
15
15
  test = ["pytest>=8"]
16
16
 
17
17
  [project.scripts]
@@ -1,2 +1,2 @@
1
1
  """Agent Apprenticeship framework."""
2
- __version__ = "0.1.4"
2
+ __version__ = "0.1.6"
@@ -48,6 +48,7 @@ from .config import (
48
48
  )
49
49
  from .openai_structured import run_llm_smoke, format_smoke_counters
50
50
  from .env import contains_secret, redact_secrets
51
+ from .public_sanitizer import sanitize_public_obj, sanitize_public_text
51
52
  from .command_discovery import AGENT_COMMAND_CANDIDATES, resolve_command, resolve_agent_command
52
53
  from .integration_status import integrations_report
53
54
  from .certification import certification_exit_code, run_certification_matrix
@@ -2188,6 +2189,55 @@ def _zip_dir(src: Path, dst: Path) -> str:
2188
2189
  return f"sha256:{digest}"
2189
2190
 
2190
2191
 
2192
+ def _sanitize_submission_copy(root: Path) -> None:
2193
+ text_suffixes = {
2194
+ ".json",
2195
+ ".jsonl",
2196
+ ".md",
2197
+ ".txt",
2198
+ ".yaml",
2199
+ ".yml",
2200
+ ".csv",
2201
+ ".tsv",
2202
+ ".log",
2203
+ }
2204
+ for path in root.rglob("*"):
2205
+ if not path.is_file() or path.stat().st_size > 5_000_000:
2206
+ continue
2207
+ if path.suffix.lower() not in text_suffixes:
2208
+ continue
2209
+ raw = path.read_text(errors="ignore")
2210
+ if path.suffix.lower() == ".json":
2211
+ try:
2212
+ data = json.loads(raw or "{}")
2213
+ except Exception:
2214
+ path.write_text(sanitize_public_text(raw) or "")
2215
+ else:
2216
+ if isinstance(data, dict):
2217
+ write_json(path, sanitize_public_obj(data))
2218
+ elif isinstance(data, list):
2219
+ path.write_text(json.dumps(sanitize_public_obj({"items": data})["items"], indent=2, sort_keys=True) + "\n")
2220
+ else:
2221
+ path.write_text(sanitize_public_text(raw) or "")
2222
+ elif path.suffix.lower() == ".jsonl":
2223
+ rows = []
2224
+ for line in raw.splitlines():
2225
+ if not line.strip():
2226
+ continue
2227
+ try:
2228
+ data = json.loads(line)
2229
+ except Exception:
2230
+ rows.append(json.dumps(sanitize_public_text(line) or "", sort_keys=True))
2231
+ else:
2232
+ if isinstance(data, dict):
2233
+ rows.append(json.dumps(sanitize_public_obj(data), sort_keys=True))
2234
+ else:
2235
+ rows.append(json.dumps(sanitize_public_obj({"item": data})["item"], sort_keys=True))
2236
+ path.write_text("\n".join(rows) + ("\n" if rows else ""))
2237
+ else:
2238
+ path.write_text(sanitize_public_text(raw) or "")
2239
+
2240
+
2191
2241
  def _create_ecosystem_submission(bundle: Path) -> tuple[Path, Path, dict]:
2192
2242
  bundle = _safe_bundle_path(bundle)
2193
2243
  secret_hits = _bundle_secret_hits(bundle)
@@ -2206,6 +2256,7 @@ def _create_ecosystem_submission(bundle: Path) -> tuple[Path, Path, dict]:
2206
2256
  submission_dir / "contribution_bundle",
2207
2257
  ignore=shutil.ignore_patterns(".env", ".env.local", "__pycache__", "*.pyc"),
2208
2258
  )
2259
+ _sanitize_submission_copy(submission_dir / "contribution_bundle")
2209
2260
  package_zip = bundle.parent / f"{bundle.name}_ecosystem_submission.zip"
2210
2261
  metadata = _bundle_submission_metadata(bundle, package_name=package_zip.name)
2211
2262
  write_json(submission_dir / "ecosystem_submission.json", metadata)
@@ -2757,9 +2808,9 @@ def ecosystem_contribute(
2757
2808
  typer.echo("")
2758
2809
  typer.echo(f"Bundle ID: {metadata.get('bundle_id')}")
2759
2810
  typer.echo(f"Title: {metadata.get('title')}")
2760
- typer.echo(f"Bundle: {bundle}")
2761
- typer.echo(f"Submission package: {package_zip}")
2762
- typer.echo(f"Submission metadata: {submission_dir / 'ecosystem_submission.json'}")
2811
+ typer.echo(f"Bundle folder: {bundle.name}")
2812
+ typer.echo(f"Submission package: {package_zip.name}")
2813
+ typer.echo("Submission metadata: ecosystem_submission/ecosystem_submission.json")
2763
2814
  if result["contribution_created"]:
2764
2815
  typer.echo(f"Public contribution URL: {result['contribution_url']}")
2765
2816
  typer.echo("No bundle files were uploaded automatically. Attach or submit the generated package according to the repo instructions.")
@@ -2769,7 +2820,7 @@ def ecosystem_contribute(
2769
2820
  typer.echo(str(result.get("gh_error") or ""))
2770
2821
  elif target_repo and _gh_path() and _gh_authenticated() and dry_run:
2771
2822
  typer.echo("Dry run: no GitHub issue was created.")
2772
- typer.echo(f"Would run: gh issue create --repo {target_repo} --title \"Contribution Bundle: {metadata.get('bundle_id')}\" --body-file {issue_body}")
2823
+ typer.echo(f"Would run: gh issue create --repo {target_repo} --title \"Contribution Bundle: {metadata.get('bundle_id')}\" --body-file GITHUB_ISSUE_BODY.md")
2773
2824
  else:
2774
2825
  typer.echo("No upload was performed in v0.")
2775
2826
  typer.echo(f"Public ecosystem: {_ecosystem_repo_url(target_repo)}")
@@ -2780,8 +2831,8 @@ def ecosystem_contribute(
2780
2831
  typer.echo("")
2781
2832
  typer.echo("Manual public submission steps:")
2782
2833
  typer.echo(f"1. Open {_ecosystem_repo_url(target_repo)} in GitHub.")
2783
- typer.echo(f"2. Create a new issue using: {issue_body}")
2784
- typer.echo(f"3. Attach or share the submission package: {package_zip}")
2834
+ typer.echo("2. Create a new issue using: ecosystem_submission/GITHUB_ISSUE_BODY.md")
2835
+ typer.echo(f"3. Attach or share the submission package: {package_zip.name}")
2785
2836
  typer.echo(f"Community Slack: {SLACK_LINK}")
2786
2837
 
2787
2838
 
@@ -3123,8 +3174,8 @@ def bundle_contribute(path: Path=typer.Argument(..., help='Contribution Bundle f
3123
3174
  typer.echo(str(path))
3124
3175
  typer.echo('')
3125
3176
  typer.echo('No upload was performed by this command.')
3126
- typer.echo(f"Submission package: {package_zip}")
3127
- typer.echo(f"Submission metadata: {submission_dir / 'ecosystem_submission.json'}")
3177
+ typer.echo(f"Submission package: {package_zip.name}")
3178
+ typer.echo("Submission metadata: ecosystem_submission/ecosystem_submission.json")
3128
3179
  typer.echo('')
3129
3180
  typer.echo('Contribute to public ecosystem:')
3130
3181
  typer.echo(f'apprentice ecosystem contribute {path}')
@@ -16,11 +16,11 @@ CONTROLLER_TELEMETRY_KEYS={
16
16
  }
17
17
  CONTROLLER_TELEMETRY_PATTERNS=list(CONTROLLER_TELEMETRY_KEYS)
18
18
  PUBLIC_OMIT_KEYS={
19
- 'source_url_or_ref','source_kind','source_url','source_ref','source_license',
19
+ 'source_url_or_ref','source_kind','source_url','source_ref','source_basis','source_license',
20
20
  'expected_pay','expected_apprentice_pay',
21
21
  'evaluation_mode','data_sharing_level','sensitive_info_masking',
22
22
  }
23
- _ABS_LOCAL_PATH_RE=re.compile(r"(/Users/[^\s\"\']+|/home/[^\s\"\']+|/private/[^\s\"\']+|/tmp/[^\s\"\']+)")
23
+ _ABS_LOCAL_PATH_RE=re.compile(r"(/Users/[^\s\"\']+|/home/[^\s\"\']+|/private/[^\s\"\']+|/tmp/[^\s\"\']+|/var/folders/[^\s\"\']+)")
24
24
  _USAGE_RE=re.compile(r"(you['’]?ve hit your usage limit|usage limit|rate limit|quota)", re.I)
25
25
  PUBLIC_TEXT_REPLACEMENTS=[
26
26
  ("source_url_or_ref", "reference_or_context"),
@@ -29,6 +29,7 @@ PUBLIC_TEXT_REPLACEMENTS=[
29
29
  ("source_urls", "reference_links"),
30
30
  ("source_url", "reference_link"),
31
31
  ("source_ref", "reference_id"),
32
+ ("source_basis", "reference_basis"),
32
33
  ("source_kind", "reference_kind"),
33
34
  ("source_license", "reference_license"),
34
35
  ("expected_apprentice_pay", "expected_economic_value_for_agent_apprentice"),