jac-coder 0.2.7__tar.gz → 0.2.9__tar.gz
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.
- {jac_coder-0.2.7 → jac_coder-0.2.9}/PKG-INFO +5 -3
- {jac_coder-0.2.7 → jac_coder-0.2.9}/README.md +1 -3
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/api.impl.jac +12 -64
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/api.jac +1 -9
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/cli.jac +2 -7
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/core/nodes.impl.jac +18 -63
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/core/nodes.jac +209 -54
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/core/walkers.impl.jac +43 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/core/walkers.jac +2 -10
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/config.jac +1 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/events.jac +15 -3
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/kv.jac +10 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/mcp_manager.jac +0 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/lib/coder.impl.jac +1 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/lib/coder.jac +1 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/context.impl.jac +2 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/cost_tracker.impl.jac +0 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/file_logger.jac +0 -6
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/permission.impl.jac +1 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/prompt.impl.jac +5 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/prompt.jac +16 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/skills.impl.jac +21 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/skills.jac +3 -3
- jac_coder-0.2.9/jac_coder/runtime/struggle_report.jac +326 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/server.jac +1 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/__init__.jac +0 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/git.impl.jac +0 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/delegation.impl.jac +21 -13
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/delegation.jac +2 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/net/preview.impl.jac +12 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/net/preview.jac +1 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/filesystem.impl.jac +0 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/filesystem.jac +0 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/jac_analyzer.impl.jac +0 -108
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/jac_analyzer.jac +0 -4
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/shell.jac +0 -1
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/write/checked.impl.jac +0 -3
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/tool_output.impl.jac +0 -2
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder.egg-info/PKG-INFO +5 -3
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder.egg-info/SOURCES.txt +1 -6
- jac_coder-0.2.9/jac_coder.egg-info/requires.txt +8 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/pyproject.toml +5 -3
- jac_coder-0.2.7/jac_coder/runtime/memory.impl.jac +0 -247
- jac_coder-0.2.7/jac_coder/runtime/memory.jac +0 -21
- jac_coder-0.2.7/jac_coder/tool/meta/task.impl.jac +0 -12
- jac_coder-0.2.7/jac_coder/tool/meta/task.jac +0 -9
- jac_coder-0.2.7/jac_coder/tool/meta/validate.impl.jac +0 -254
- jac_coder-0.2.7/jac_coder/tool/meta/validate.jac +0 -11
- jac_coder-0.2.7/jac_coder.egg-info/requires.txt +0 -6
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/__init__.py +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/cli.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/cli_entry.py +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/core/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/config.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/infra/mcp_manager.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/lib/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/compaction.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/context.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/cost_tracker.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/events.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/runtime/permission.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/serve_entry.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/git.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/mcp.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/mcp.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/clarify_intent.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/clarify_intent.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/think.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/think.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/todo.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/meta/todo.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/net/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/net/web.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/net/web.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/load_jac_skill.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/load_jac_skill.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/search.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/read/search.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/guarded.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/guarded.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/jac_tools.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/jac_tools.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/run/shell.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/write/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/tool/write/checked.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/__init__.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/banner.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/colors.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/md_render.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/sandbox.impl.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/sandbox.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder/util/tool_output.jac +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder.egg-info/dependency_links.txt +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder.egg-info/entry_points.txt +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/jac_coder.egg-info/top_level.txt +0 -0
- {jac_coder-0.2.7 → jac_coder-0.2.9}/setup.cfg +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-coder
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: AI coding agent backend for Jac, powered by jac-byllm
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Requires-Dist: python-dotenv>=1.0.0
|
|
7
|
-
Requires-Dist: jaclang
|
|
8
|
-
Requires-Dist: byllm
|
|
9
7
|
Requires-Dist: mcp>=1.0.0
|
|
10
8
|
Requires-Dist: jac-mcp
|
|
11
9
|
Requires-Dist: rich>=13.0
|
|
10
|
+
Requires-Dist: litellm<=1.82.6,>=1.70.0
|
|
11
|
+
Requires-Dist: httpx>=0.27.0
|
|
12
|
+
Requires-Dist: loguru<0.8.0,>=0.7.2
|
|
13
|
+
Requires-Dist: pillow<13.0.0,>=12.0.0
|
|
@@ -64,7 +64,6 @@ Root → Session → MainAgent
|
|
|
64
64
|
- **WorkerAgent (walker)** — in-process SubAgent with 14 tools (can write/edit/run). For known changes.
|
|
65
65
|
- **ExplorerAgent (walker)** — in-process SubAgent with 10 tools (read-only + web search). For root-cause investigation.
|
|
66
66
|
- **Session (node)** — persistent chat state, history, active files, errors, mode hint.
|
|
67
|
-
- **ProjectMemory (node)** — AST-derived codebase knowledge (nodes, walkers, edges, imports). Backed by `.jaccoder/progress.md` as primary source of truth.
|
|
68
67
|
- **McpRegistry (node)** — persisted MCP server configs.
|
|
69
68
|
|
|
70
69
|
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full picture.
|
|
@@ -130,7 +129,7 @@ jac-code/
|
|
|
130
129
|
│ ├── api.jac # Public API — the only module external apps import
|
|
131
130
|
│ ├── server.jac # JSON-RPC stdio server for the VS Code extension
|
|
132
131
|
│ ├── core/
|
|
133
|
-
│ │ ├── nodes.jac # MainAgent, WorkerAgent, ExplorerAgent, Session
|
|
132
|
+
│ │ ├── nodes.jac # MainAgent, WorkerAgent, ExplorerAgent, Session
|
|
134
133
|
│ │ └── walkers.jac # interact, new_session, list_sessions, etc.
|
|
135
134
|
│ ├── lib/
|
|
136
135
|
│ │ └── coder.jac # JacCoder library-mode class (stateless + service modes)
|
|
@@ -140,7 +139,6 @@ jac-code/
|
|
|
140
139
|
│ ├── runtime/
|
|
141
140
|
│ │ ├── context.jac # Tiered compaction with LLM-summary fallback
|
|
142
141
|
│ │ ├── events.jac # Event bus, doom-loop detection, abort signal
|
|
143
|
-
│ │ ├── memory.jac # AST-first ProjectMemory (LLM fallback)
|
|
144
142
|
│ │ ├── permission.jac # Permission rule engine (allow / ask / deny)
|
|
145
143
|
│ │ ├── prompt.jac # Mode-aware dynamic prompt assembly
|
|
146
144
|
│ │ ├── skills.jac # SKILL.md registry + listing injection
|
|
@@ -197,7 +197,6 @@ impl chat(
|
|
|
197
197
|
return {"error": "Session is stale after a server update. Please close this session and open a new one.", "agent": "error"};
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
# Override directory if provided
|
|
201
200
|
if directory {
|
|
202
201
|
session.directory = directory;
|
|
203
202
|
}
|
|
@@ -230,7 +229,6 @@ impl chat(
|
|
|
230
229
|
# whether to auto-allow, prompt, or deny write/edit/bash operations.
|
|
231
230
|
_set_chat_session(session_id, edit_mode);
|
|
232
231
|
|
|
233
|
-
# Setup
|
|
234
232
|
clear_abort();
|
|
235
233
|
reset_steps();
|
|
236
234
|
start_turn();
|
|
@@ -242,7 +240,6 @@ impl chat(
|
|
|
242
240
|
}
|
|
243
241
|
|
|
244
242
|
try {
|
|
245
|
-
# Memory initialization
|
|
246
243
|
_ensure_memory(session, work_dir);
|
|
247
244
|
|
|
248
245
|
session.updated_at = datetime.now().isoformat();
|
|
@@ -339,7 +336,7 @@ impl chat(
|
|
|
339
336
|
user_image = None;
|
|
340
337
|
if images and len(images) > 0 {
|
|
341
338
|
try {
|
|
342
|
-
import from byllm.lib { Image }
|
|
339
|
+
import from jaclang.byllm.lib { Image }
|
|
343
340
|
;
|
|
344
341
|
first_img = images[0];
|
|
345
342
|
data_url = first_img.get("data_url", "") if isinstance(first_img, dict) else str(first_img);
|
|
@@ -358,6 +355,7 @@ impl chat(
|
|
|
358
355
|
|
|
359
356
|
response_text = stream_result["content"];
|
|
360
357
|
tools_used = stream_result["tools_used"];
|
|
358
|
+
tool_records = stream_result.get("tool_records", []);
|
|
361
359
|
|
|
362
360
|
# Finalize turn — get accumulated file/error data from tool internals
|
|
363
361
|
tool_end();
|
|
@@ -366,7 +364,6 @@ impl chat(
|
|
|
366
364
|
files_modified = summary.get("files_modified", []);
|
|
367
365
|
has_errors = summary.get("errors", 0) > 0;
|
|
368
366
|
|
|
369
|
-
# Update session state
|
|
370
367
|
if files_modified {
|
|
371
368
|
for f in files_modified {
|
|
372
369
|
if f not in session.active_files {
|
|
@@ -421,6 +418,14 @@ impl chat(
|
|
|
421
418
|
import from jac_coder.runtime.prompt { infer_mode_hint as _infer_hint }
|
|
422
419
|
session.last_mode_hint = _infer_hint(tools_used, files_modified);
|
|
423
420
|
|
|
421
|
+
# Guaranteed end-of-turn struggle reflection (work turns only).
|
|
422
|
+
if not is_abort_requested() {
|
|
423
|
+
import from jac_coder.runtime.struggle_report { reflect_and_log }
|
|
424
|
+
reflect_and_log(
|
|
425
|
+
main_agent, tool_records, files_modified, has_errors, response_text
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
424
429
|
return {
|
|
425
430
|
"response": response_text,
|
|
426
431
|
"agent": "main",
|
|
@@ -474,63 +479,6 @@ def _ensure_memory(session: Session, work_dir: str) -> None {
|
|
|
474
479
|
}
|
|
475
480
|
|
|
476
481
|
|
|
477
|
-
def _post_process(session: Session, response_obj: Any) -> None {
|
|
478
|
-
# Track files
|
|
479
|
-
if response_obj.files_modified {
|
|
480
|
-
for f in response_obj.files_modified {
|
|
481
|
-
if f not in session.active_files {
|
|
482
|
-
session.active_files.append(f);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
if len(session.active_files) > 10 {
|
|
486
|
-
session.active_files = session.active_files[-10:];
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
# Track errors
|
|
491
|
-
if response_obj.has_errors {
|
|
492
|
-
files_str = ", ".join(response_obj.files_modified)
|
|
493
|
-
if response_obj.files_modified
|
|
494
|
-
else "unknown";
|
|
495
|
-
session.pending_errors = [f"Errors in previous turn (files: {files_str})"];
|
|
496
|
-
} else {
|
|
497
|
-
session.pending_errors = [];
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
# Refresh project_summary from progress.md (agent may have updated it).
|
|
501
|
-
if session.directory {
|
|
502
|
-
progress_path = os.path.join(session.directory, ".jaccoder", "progress.md");
|
|
503
|
-
if os.path.isfile(progress_path) {
|
|
504
|
-
try {
|
|
505
|
-
with open(progress_path, "r", encoding="utf-8") as f {
|
|
506
|
-
pc = f.read();
|
|
507
|
-
}
|
|
508
|
-
if len(pc) > 4000 {
|
|
509
|
-
pc = pc[:4000] + "\n\n[... truncated]";
|
|
510
|
-
}
|
|
511
|
-
session.project_summary = pc;
|
|
512
|
-
} except Exception { }
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
# Persist response
|
|
517
|
-
record: dict = {
|
|
518
|
-
"role": "assistant",
|
|
519
|
-
"content": response_obj.content,
|
|
520
|
-
"agent": "main"
|
|
521
|
-
};
|
|
522
|
-
if response_obj.tools_used {
|
|
523
|
-
record["tools_used"] = response_obj.tools_used;
|
|
524
|
-
}
|
|
525
|
-
if response_obj.files_modified {
|
|
526
|
-
record["files_modified"] = response_obj.files_modified;
|
|
527
|
-
}
|
|
528
|
-
session.chat_history.append(record);
|
|
529
|
-
session.last_agent = "main";
|
|
530
|
-
session.updated_at = datetime.now().isoformat();
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
|
|
534
482
|
# ---------------------------------------------------------------------------
|
|
535
483
|
# Model management API
|
|
536
484
|
# ---------------------------------------------------------------------------
|
|
@@ -552,8 +500,8 @@ impl api_check_local_setup(alias: str) -> dict {
|
|
|
552
500
|
model: bool = False;
|
|
553
501
|
valid_alias: bool = False;
|
|
554
502
|
try {
|
|
555
|
-
import from byllm.local_runtime { LOCAL_MODELS }
|
|
556
|
-
import from byllm.model_cache { is_downloaded }
|
|
503
|
+
import from jaclang.byllm.local_runtime { LOCAL_MODELS }
|
|
504
|
+
import from jaclang.byllm.model_cache { is_downloaded }
|
|
557
505
|
spec = LOCAL_MODELS.get(alias);
|
|
558
506
|
if spec is not None {
|
|
559
507
|
valid_alias = True;
|
|
@@ -11,8 +11,7 @@ import from jac_coder.infra.config {
|
|
|
11
11
|
}
|
|
12
12
|
import from jac_coder.util.tool_output { tool_end }
|
|
13
13
|
import from jac_coder.runtime.permission { permission_engine }
|
|
14
|
-
import from jac_coder.util.sandbox { set_sandbox_root
|
|
15
|
-
import from jac_coder.runtime.context { build_context, ContextConfig }
|
|
14
|
+
import from jac_coder.util.sandbox { set_sandbox_root }
|
|
16
15
|
import from jac_coder.core.walkers {
|
|
17
16
|
new_session,
|
|
18
17
|
ensure_main_agent,
|
|
@@ -28,11 +27,6 @@ import from jac_coder.infra.mcp_manager {
|
|
|
28
27
|
mcp_get_tools,
|
|
29
28
|
mcp_register_builtin
|
|
30
29
|
}
|
|
31
|
-
import from jac_coder.runtime.memory {
|
|
32
|
-
find_or_create_memory,
|
|
33
|
-
_init_memory,
|
|
34
|
-
update_memory_from_session
|
|
35
|
-
}
|
|
36
30
|
import from jac_coder.core.nodes { Session, MainAgent }
|
|
37
31
|
import from jac_coder.runtime.cost_tracker {
|
|
38
32
|
get_summary as _ct_get_summary,
|
|
@@ -41,7 +35,6 @@ import from jac_coder.runtime.cost_tracker {
|
|
|
41
35
|
import from jac_coder.tool.run.guarded {
|
|
42
36
|
_set_chat_session,
|
|
43
37
|
_clear_chat_session,
|
|
44
|
-
_chat_contexts,
|
|
45
38
|
_clarification_events,
|
|
46
39
|
_clarification_decisions,
|
|
47
40
|
_CLRFY_KEY_PREFIX
|
|
@@ -52,7 +45,6 @@ import from jac_coder.runtime.events {
|
|
|
52
45
|
reset_steps,
|
|
53
46
|
start_turn,
|
|
54
47
|
emit_turn_summary,
|
|
55
|
-
emit_event,
|
|
56
48
|
is_abort_requested,
|
|
57
49
|
clear_abort
|
|
58
50
|
}
|
|
@@ -2,19 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import os;
|
|
4
4
|
import sys;
|
|
5
|
-
import from datetime { datetime }
|
|
6
5
|
import from jac_coder.core.nodes { Session, MainAgent }
|
|
7
6
|
import from jac_coder.core.walkers {
|
|
8
7
|
new_session,
|
|
9
|
-
list_sessions,
|
|
10
|
-
get_session,
|
|
11
|
-
close_session,
|
|
12
8
|
interact,
|
|
13
9
|
ensure_main_agent
|
|
14
10
|
}
|
|
15
|
-
import from jac_coder.infra.config {
|
|
11
|
+
import from jac_coder.infra.config { model_name, get_config, set_model, get_model }
|
|
16
12
|
import from jac_coder.runtime.permission { permission_engine }
|
|
17
|
-
import from jac_coder.runtime.events { register_event_callback
|
|
13
|
+
import from jac_coder.runtime.events { register_event_callback }
|
|
18
14
|
import from jac_coder.runtime.file_logger { init_file_logger, file_log_event, close_file_logger }
|
|
19
15
|
import from jac_coder.tool.meta.todo { get_todos }
|
|
20
16
|
import from jac_coder.util.colors {
|
|
@@ -26,7 +22,6 @@ import from jac_coder.util.colors {
|
|
|
26
22
|
GREEN,
|
|
27
23
|
YELLOW,
|
|
28
24
|
RED,
|
|
29
|
-
MAGENTA,
|
|
30
25
|
WHITE,
|
|
31
26
|
AGENT_COLORS
|
|
32
27
|
}
|
|
@@ -14,68 +14,6 @@ impl Session.postinit{
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
# ---------------------------------------------------------------------------
|
|
18
|
-
# ProjectMemory
|
|
19
|
-
# ---------------------------------------------------------------------------
|
|
20
|
-
sem ProjectMemory.profile_project = """Analyze a Jac project and extract structured memory.
|
|
21
|
-
Given the file tree and key file contents, return:
|
|
22
|
-
- architecture: 1-2 sentences describing the project purpose, tech stack, and node/walker structure
|
|
23
|
-
- file_map: dict mapping up to 15 important file paths (relative) to 1-line descriptions of their role
|
|
24
|
-
- conventions: list of coding conventions observed (naming style, file organization, patterns)
|
|
25
|
-
Be concise and factual. This context will help future coding sessions start smart.""";
|
|
26
|
-
|
|
27
|
-
sem ProjectMemory.collect_learnings = """Extract learnings from a completed coding session.
|
|
28
|
-
Given the files modified and a session summary, return only NEW information:
|
|
29
|
-
- new_files: dict of newly created or significantly changed file paths to 1-line descriptions
|
|
30
|
-
- new_conventions: new coding patterns or conventions established (empty list if none)
|
|
31
|
-
- new_decisions: architectural or design decisions made (empty list if none)
|
|
32
|
-
- known_issues: bugs or issues discovered but not yet fixed (empty list if none)
|
|
33
|
-
Be selective — only include genuinely new information.""";
|
|
34
|
-
|
|
35
|
-
sem ProjectScan.architecture = "1-2 sentences: project purpose, tech stack, and overall node/walker structure";
|
|
36
|
-
sem ProjectScan.file_map = "dict mapping relative file paths to 1-line role descriptions (max 15 files)";
|
|
37
|
-
sem ProjectScan.conventions = "list of coding conventions: naming style, file organization, patterns used";
|
|
38
|
-
|
|
39
|
-
sem SessionLearnings.new_files = "dict of new/modified file paths to 1-line descriptions of their content";
|
|
40
|
-
sem SessionLearnings.new_conventions = "new coding conventions established this session (empty list if none)";
|
|
41
|
-
sem SessionLearnings.new_decisions = "architectural decisions made this session (empty list if none)";
|
|
42
|
-
sem SessionLearnings.known_issues = "bugs or issues discovered but not yet fixed (empty list if none)";
|
|
43
|
-
|
|
44
|
-
impl ProjectMemory.summarize() -> str {
|
|
45
|
-
parts = [];
|
|
46
|
-
if self.architecture {
|
|
47
|
-
parts.append("Architecture: " + self.architecture);
|
|
48
|
-
}
|
|
49
|
-
if self.node_details {
|
|
50
|
-
parts.append(self.node_details);
|
|
51
|
-
}
|
|
52
|
-
if self.walker_details {
|
|
53
|
-
parts.append(self.walker_details);
|
|
54
|
-
}
|
|
55
|
-
if self.graph_topology {
|
|
56
|
-
parts.append("Graph: " + self.graph_topology);
|
|
57
|
-
}
|
|
58
|
-
if self.import_map {
|
|
59
|
-
parts.append(self.import_map);
|
|
60
|
-
}
|
|
61
|
-
if self.file_map {
|
|
62
|
-
items = list(self.file_map.items())[:10];
|
|
63
|
-
file_lines = [f" {k}: {v}" for (k, v) in items];
|
|
64
|
-
parts.append("Key files:\n" + "\n".join(file_lines));
|
|
65
|
-
}
|
|
66
|
-
if self.conventions {
|
|
67
|
-
parts.append("Conventions: " + ", ".join(self.conventions[:5]));
|
|
68
|
-
}
|
|
69
|
-
if self.past_decisions {
|
|
70
|
-
parts.append("Past decisions: " + "; ".join(self.past_decisions[:3]));
|
|
71
|
-
}
|
|
72
|
-
if self.known_issues {
|
|
73
|
-
parts.append("Known issues: " + "; ".join(self.known_issues[:3]));
|
|
74
|
-
}
|
|
75
|
-
return "\n".join(parts);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
17
|
# ---------------------------------------------------------------------------
|
|
80
18
|
# MainAgent — the orchestrator
|
|
81
19
|
# ---------------------------------------------------------------------------
|
|
@@ -87,10 +25,14 @@ sem MainAgent.respond = "Respond to the user's coding request.";
|
|
|
87
25
|
# ---------------------------------------------------------------------------
|
|
88
26
|
# SubAgent walkers — sem annotations and entry ability implementations
|
|
89
27
|
# ---------------------------------------------------------------------------
|
|
90
|
-
sem WorkerAgent.do_work = "Execute the delegated coding task.";
|
|
28
|
+
sem WorkerAgent.do_work = "Execute the delegated coding task as a pure implementer. When .jaccoder/ui_spec.json exists, treat it as a binding UI contract — never change style, theme, base_color, nav_pattern, or pages (those belong to UIDesignerAgent). If a mechanical implementation need arises for a component not in primitive_components (e.g. a spinner), add it to primitive_components in ui_spec.json first, then run jac add --shadcn. Never make freestyle design decisions.";
|
|
91
29
|
|
|
92
30
|
sem ExplorerAgent.do_work = "Investigate the codebase and report findings.";
|
|
93
31
|
|
|
32
|
+
sem UIDesignerAgent = "UI design authority — produces or updates .jaccoder/ui_spec.json, the living design contract for the application.";
|
|
33
|
+
sem UIDesignerAgent.do_work = "Write or update .jaccoder/ui_spec.json. Create mode (no UISpec in task): analyse project from scratch and produce a full spec. Update mode (current UISpec JSON provided in task): apply the user's change request to only the affected fields, preserve everything else.";
|
|
34
|
+
sem UIDesignerAgent.task = "Input context in one of two forms. Create: project path + directory listing + jac.toml + user request. Update: project path + current UISpec JSON + user request.";
|
|
35
|
+
|
|
94
36
|
|
|
95
37
|
"""Consume a SubAgent's by llm() stream, forward events, and return results."""
|
|
96
38
|
def _consume_subagent_stream(event_stream: Any, prefix: str, track_files: bool = False) -> dict {
|
|
@@ -134,6 +76,11 @@ def _consume_subagent_stream(event_stream: Any, prefix: str, track_files: bool =
|
|
|
134
76
|
}
|
|
135
77
|
} elif event.event_type == "steps_done" {
|
|
136
78
|
emit_event("llm_steps_done", dict(event.data));
|
|
79
|
+
} elif event.event_type == "stream_reset" {
|
|
80
|
+
# byllm retried a transient mid-stream drop; drop the partial subagent
|
|
81
|
+
# reply so the regenerated text isn't doubled.
|
|
82
|
+
content = "";
|
|
83
|
+
emit_event("llm_stream_reset", dict(event.data));
|
|
137
84
|
} elif event.event_type == "chunk" {
|
|
138
85
|
content += event.data.get("content", "");
|
|
139
86
|
} elif event.event_type == "usage" {
|
|
@@ -169,3 +116,11 @@ impl ExplorerAgent.execute with MainAgent entry {
|
|
|
169
116
|
self.result_files = [];
|
|
170
117
|
self.result_errors = list(result["errors"]);
|
|
171
118
|
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
impl UIDesignerAgent.execute with MainAgent entry {
|
|
122
|
+
result = _consume_subagent_stream(
|
|
123
|
+
self.do_work(task_str=self.task), "sub:designer"
|
|
124
|
+
);
|
|
125
|
+
self.result_content = str(result["content"]);
|
|
126
|
+
}
|