akernel-runtime 0.1.0__py3-none-any.whl

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.
Files changed (40) hide show
  1. akernel_runtime-0.1.0.dist-info/METADATA +270 -0
  2. akernel_runtime-0.1.0.dist-info/RECORD +40 -0
  3. akernel_runtime-0.1.0.dist-info/WHEEL +5 -0
  4. akernel_runtime-0.1.0.dist-info/entry_points.txt +2 -0
  5. akernel_runtime-0.1.0.dist-info/licenses/LICENSE +201 -0
  6. akernel_runtime-0.1.0.dist-info/licenses/NOTICE +4 -0
  7. akernel_runtime-0.1.0.dist-info/top_level.txt +1 -0
  8. context_kernel/__init__.py +4 -0
  9. context_kernel/__main__.py +5 -0
  10. context_kernel/agent_reports.py +188 -0
  11. context_kernel/benchmarks.py +493 -0
  12. context_kernel/budget.py +72 -0
  13. context_kernel/cli.py +2953 -0
  14. context_kernel/context.py +161 -0
  15. context_kernel/evals.py +347 -0
  16. context_kernel/global_memory.py +126 -0
  17. context_kernel/loop.py +1617 -0
  18. context_kernel/marketplace.py +194 -0
  19. context_kernel/marketplace_data/skills/context_budget.json +27 -0
  20. context_kernel/marketplace_data/skills/context_compaction.json +27 -0
  21. context_kernel/marketplace_data/skills/edit_file.json +27 -0
  22. context_kernel/marketplace_data/skills/index.json +66 -0
  23. context_kernel/marketplace_data/skills/long_task_planning.json +27 -0
  24. context_kernel/marketplace_data/skills/multi_file_bugfix.json +28 -0
  25. context_kernel/memory.py +515 -0
  26. context_kernel/models.py +144 -0
  27. context_kernel/planner.py +155 -0
  28. context_kernel/policy.py +271 -0
  29. context_kernel/project.py +317 -0
  30. context_kernel/providers.py +1264 -0
  31. context_kernel/report_costs.py +375 -0
  32. context_kernel/runner.py +78 -0
  33. context_kernel/skills.py +318 -0
  34. context_kernel/state_writer.py +108 -0
  35. context_kernel/storage.py +171 -0
  36. context_kernel/tasks.py +549 -0
  37. context_kernel/text.py +42 -0
  38. context_kernel/tokenizer.py +22 -0
  39. context_kernel/tools.py +544 -0
  40. context_kernel/verifier.py +77 -0
@@ -0,0 +1,317 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from .models import utc_now
8
+ from .storage import Workspace
9
+ from .tokenizer import estimate_tokens
10
+
11
+
12
+ PROJECT_PROFILE_VERSION = 1
13
+ IGNORED_DIRS = {
14
+ ".akernel",
15
+ ".git",
16
+ ".mypy_cache",
17
+ ".pytest_cache",
18
+ ".ruff_cache",
19
+ ".sandbox",
20
+ ".venv",
21
+ "__pycache__",
22
+ "build",
23
+ "dist",
24
+ "node_modules",
25
+ "target",
26
+ }
27
+ KEY_FILE_NAMES = {
28
+ ".cursorrules",
29
+ "AGENTS.md",
30
+ "CLAUDE.md",
31
+ "README.md",
32
+ "README.rst",
33
+ "pyproject.toml",
34
+ "setup.py",
35
+ "requirements.txt",
36
+ "pytest.ini",
37
+ "tox.ini",
38
+ "package.json",
39
+ "pnpm-lock.yaml",
40
+ "yarn.lock",
41
+ "Cargo.toml",
42
+ "go.mod",
43
+ }
44
+ INSTRUCTION_FILE_NAMES = [
45
+ "AGENTS.md",
46
+ ".akernel/AGENTS.md",
47
+ "CLAUDE.md",
48
+ ".cursorrules",
49
+ ".github/copilot-instructions.md",
50
+ ]
51
+ MAX_PROJECT_INSTRUCTION_CHARS = 4000
52
+
53
+
54
+ def scan_project(workspace: Workspace, *, update_config: bool = True) -> dict[str, Any]:
55
+ files = list_project_files(workspace.root)
56
+ file_names = {path.name for path in files}
57
+ suffixes = {path.suffix.lower() for path in files}
58
+ top_level = {path.name for path in workspace.root.iterdir()} if workspace.root.exists() else set()
59
+
60
+ languages = detect_languages(file_names, suffixes)
61
+ package_managers = detect_package_managers(file_names)
62
+ commands = detect_commands(workspace.root, file_names, top_level, package_managers)
63
+ command_roots = detect_command_roots(languages, package_managers, commands)
64
+ key_files = detect_key_files(workspace.root, files)
65
+ instructions = detect_project_instructions(workspace.root)
66
+
67
+ profile = {
68
+ "version": PROJECT_PROFILE_VERSION,
69
+ "generated_at": utc_now(),
70
+ "root": str(workspace.root),
71
+ "languages": languages,
72
+ "package_managers": package_managers,
73
+ "commands": commands,
74
+ "command_roots": command_roots,
75
+ "key_files": key_files,
76
+ "instructions": instructions,
77
+ "file_summary": {
78
+ "scanned_files": len(files),
79
+ "top_level_entries": sorted(list(top_level))[:40],
80
+ },
81
+ "summary": summarize_project(languages, package_managers, commands, key_files),
82
+ }
83
+ Workspace.write_json(workspace.project_file, profile)
84
+ if update_config:
85
+ extend_command_policy(workspace, command_roots)
86
+ return profile
87
+
88
+
89
+ def load_project_profile(workspace: Workspace) -> dict[str, Any] | None:
90
+ if not workspace.project_file.exists():
91
+ return None
92
+ return Workspace.read_json(workspace.project_file)
93
+
94
+
95
+ def compact_project_profile(profile: dict[str, Any] | None, *, max_tokens: int = 220) -> dict[str, Any] | None:
96
+ if not profile:
97
+ return None
98
+ compact = {
99
+ "summary": profile.get("summary", ""),
100
+ "languages": profile.get("languages", [])[:6],
101
+ "package_managers": profile.get("package_managers", [])[:4],
102
+ "commands": profile.get("commands", {}),
103
+ "key_files": profile.get("key_files", [])[:12],
104
+ "command_roots": profile.get("command_roots", [])[:12],
105
+ "instructions": compact_project_instructions(profile.get("instructions", [])),
106
+ }
107
+ if estimate_tokens(compact) <= max_tokens:
108
+ return compact
109
+ compact["key_files"] = compact["key_files"][:6]
110
+ compact["commands"] = {
111
+ key: value
112
+ for key, value in compact["commands"].items()
113
+ if key in {"test", "lint", "build"}
114
+ }
115
+ compact["instructions"] = compact["instructions"][:2]
116
+ return compact
117
+
118
+
119
+ def list_project_files(root: Path, *, max_files: int = 5000) -> list[Path]:
120
+ files: list[Path] = []
121
+ if not root.exists():
122
+ return files
123
+ stack = [root]
124
+ while stack and len(files) < max_files:
125
+ current = stack.pop()
126
+ try:
127
+ entries = sorted(current.iterdir(), key=lambda item: item.name.lower())
128
+ except OSError:
129
+ continue
130
+ for entry in entries:
131
+ if entry.name in IGNORED_DIRS:
132
+ continue
133
+ if entry.is_dir():
134
+ stack.append(entry)
135
+ elif entry.is_file():
136
+ files.append(entry)
137
+ if len(files) >= max_files:
138
+ break
139
+ return files
140
+
141
+
142
+ def detect_languages(file_names: set[str], suffixes: set[str]) -> list[str]:
143
+ languages: list[str] = []
144
+ if {".py"}.intersection(suffixes) or {"pyproject.toml", "setup.py", "requirements.txt"}.intersection(file_names):
145
+ languages.append("python")
146
+ if {".js", ".jsx", ".ts", ".tsx"}.intersection(suffixes) or "package.json" in file_names:
147
+ languages.append("javascript/typescript")
148
+ if ".rs" in suffixes or "Cargo.toml" in file_names:
149
+ languages.append("rust")
150
+ if ".go" in suffixes or "go.mod" in file_names:
151
+ languages.append("go")
152
+ if ".java" in suffixes or {"pom.xml", "build.gradle", "build.gradle.kts"}.intersection(file_names):
153
+ languages.append("java")
154
+ return languages or ["unknown"]
155
+
156
+
157
+ def detect_package_managers(file_names: set[str]) -> list[str]:
158
+ managers: list[str] = []
159
+ if "pyproject.toml" in file_names:
160
+ managers.append("python/pyproject")
161
+ if "requirements.txt" in file_names:
162
+ managers.append("python/pip")
163
+ if "package.json" in file_names:
164
+ if "pnpm-lock.yaml" in file_names:
165
+ managers.append("node/pnpm")
166
+ elif "yarn.lock" in file_names:
167
+ managers.append("node/yarn")
168
+ else:
169
+ managers.append("node/npm")
170
+ if "Cargo.toml" in file_names:
171
+ managers.append("rust/cargo")
172
+ if "go.mod" in file_names:
173
+ managers.append("go")
174
+ return managers
175
+
176
+
177
+ def detect_commands(
178
+ root: Path,
179
+ file_names: set[str],
180
+ top_level: set[str],
181
+ package_managers: list[str],
182
+ ) -> dict[str, str]:
183
+ commands: dict[str, str] = {}
184
+ if "pyproject.toml" in file_names or "requirements.txt" in file_names or "setup.py" in file_names:
185
+ if "pytest.ini" in file_names or any(path.name.startswith("test_") and path.suffix == ".py" for path in list_project_files(root / "tests", max_files=200)):
186
+ commands["test"] = "python -m pytest"
187
+ elif "tests" in top_level:
188
+ commands["test"] = "python -m unittest discover -s tests"
189
+ commands["install"] = "python -m pip install -e ."
190
+
191
+ package_json = root / "package.json"
192
+ if package_json.exists():
193
+ package_data = read_package_json(package_json)
194
+ scripts = package_data.get("scripts", {}) if isinstance(package_data, dict) else {}
195
+ runner = "pnpm" if "node/pnpm" in package_managers else "yarn" if "node/yarn" in package_managers else "npm"
196
+ if isinstance(scripts, dict):
197
+ if "test" in scripts:
198
+ commands.setdefault("test", f"{runner} test")
199
+ if "lint" in scripts:
200
+ commands["lint"] = f"{runner} run lint"
201
+ if "build" in scripts:
202
+ commands["build"] = f"{runner} run build"
203
+ commands.setdefault("install_node", f"{runner} install")
204
+
205
+ if "Cargo.toml" in file_names:
206
+ commands.setdefault("test", "cargo test")
207
+ commands.setdefault("build", "cargo build")
208
+ if "go.mod" in file_names:
209
+ commands.setdefault("test", "go test ./...")
210
+ commands.setdefault("build", "go build ./...")
211
+ return commands
212
+
213
+
214
+ def detect_command_roots(languages: list[str], package_managers: list[str], commands: dict[str, str]) -> list[str]:
215
+ roots = {"akernel", "akernel.exe", "git"}
216
+ if "python" in languages or any(manager.startswith("python/") for manager in package_managers):
217
+ roots.update({"py", "pytest", "python", "python.exe"})
218
+ if any(manager.startswith("node/") for manager in package_managers):
219
+ roots.update({"node", "node.exe", "npm", "npm.cmd", "npx", "npx.cmd", "pnpm", "pnpm.cmd", "yarn", "yarn.cmd"})
220
+ if "rust" in languages:
221
+ roots.update({"cargo", "cargo.exe", "rustc", "rustc.exe"})
222
+ if "go" in languages:
223
+ roots.update({"go", "go.exe"})
224
+ for command in commands.values():
225
+ root = command.split()[0].strip().casefold()
226
+ if root:
227
+ roots.add(root)
228
+ return sorted(roots)
229
+
230
+
231
+ def detect_key_files(root: Path, files: list[Path]) -> list[str]:
232
+ key_files: list[str] = []
233
+ for path in files:
234
+ relative = path.relative_to(root).as_posix()
235
+ if path.name in KEY_FILE_NAMES or relative.startswith(".github/workflows/"):
236
+ key_files.append(relative)
237
+ return sorted(key_files)[:24]
238
+
239
+
240
+ def detect_project_instructions(root: Path) -> list[dict[str, Any]]:
241
+ instructions: list[dict[str, Any]] = []
242
+ for name in INSTRUCTION_FILE_NAMES:
243
+ path = root / name
244
+ if not path.exists() or not path.is_file():
245
+ continue
246
+ try:
247
+ text = path.read_text(encoding="utf-8-sig", errors="replace")
248
+ except OSError:
249
+ continue
250
+ content = text.strip()
251
+ if not content:
252
+ continue
253
+ instructions.append(
254
+ {
255
+ "path": name.replace("\\", "/"),
256
+ "content": content[:MAX_PROJECT_INSTRUCTION_CHARS],
257
+ "truncated": len(content) > MAX_PROJECT_INSTRUCTION_CHARS,
258
+ "estimated_tokens": estimate_tokens(content[:MAX_PROJECT_INSTRUCTION_CHARS]),
259
+ }
260
+ )
261
+ return instructions
262
+
263
+
264
+ def compact_project_instructions(instructions: Any) -> list[dict[str, Any]]:
265
+ if not isinstance(instructions, list):
266
+ return []
267
+ compact: list[dict[str, Any]] = []
268
+ for item in instructions[:3]:
269
+ if not isinstance(item, dict):
270
+ continue
271
+ compact.append(
272
+ {
273
+ "path": str(item.get("path", "")),
274
+ "content": str(item.get("content", ""))[:1800],
275
+ "truncated": bool(item.get("truncated", False)),
276
+ }
277
+ )
278
+ return compact
279
+
280
+
281
+ def extend_command_policy(workspace: Workspace, command_roots: list[str]) -> None:
282
+ config = workspace.load_config()
283
+ policy = config.setdefault("command_policy", {})
284
+ existing = policy.get("allowed_roots", [])
285
+ merged = []
286
+ seen: set[str] = set()
287
+ for root in list(existing) + command_roots:
288
+ if not isinstance(root, str) or not root.strip():
289
+ continue
290
+ normalized = root.strip().casefold()
291
+ if normalized in seen:
292
+ continue
293
+ seen.add(normalized)
294
+ merged.append(normalized)
295
+ policy["allowed_roots"] = merged
296
+ workspace.save_config(config)
297
+
298
+
299
+ def read_package_json(path: Path) -> dict[str, Any]:
300
+ try:
301
+ data = json.loads(path.read_text(encoding="utf-8"))
302
+ except (OSError, json.JSONDecodeError):
303
+ return {}
304
+ return data if isinstance(data, dict) else {}
305
+
306
+
307
+ def summarize_project(
308
+ languages: list[str],
309
+ package_managers: list[str],
310
+ commands: dict[str, str],
311
+ key_files: list[str],
312
+ ) -> str:
313
+ language_text = ", ".join(languages)
314
+ manager_text = ", ".join(package_managers) if package_managers else "none"
315
+ command_text = ", ".join(f"{name}=`{command}`" for name, command in commands.items()) or "none"
316
+ key_text = ", ".join(key_files[:6]) if key_files else "none"
317
+ return f"languages={language_text}; package_managers={manager_text}; commands={command_text}; key_files={key_text}"