@sakanano-moe/agenthelm 6.7.0 → 6.8.0
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/package.json +1 -1
- package/runtime/index.json +5 -5
- package/runtime/plugins/agent-pack/.codex-plugin/plugin.json +1 -1
- package/runtime/plugins/agent-pack/plugin.json +1 -1
- package/runtime/plugins/agent-pack/runtime/agenthelm.py +237 -6
- package/runtime/plugins/agent-pack/runtime/agenthelm_runtime.py +19 -0
- package/runtime/plugins/agents-init/.codex-plugin/plugin.json +1 -1
- package/runtime/plugins/agents-init/content.json +15 -0
- package/runtime/plugins/agents-init/plugin.json +1 -1
- package/runtime/plugins/agents-init/skills/agents-init/SKILL.md +13 -0
- package/runtime/plugins/agents-init/skills/agents-init/project.schema.json +18 -3
- package/runtime/plugins/agents-init/skills/agents-init/scripts/init_project.py +43 -4
- package/runtime/plugins/agents-init/skills/agents-init/scripts/scaffold.py +933 -0
- package/runtime/plugins/agents-init/skills/agents-init/scripts/test_scaffold.py +551 -0
- package/runtime/plugins/agents-init/skills/agents-init/skeleton.json +64 -0
- package/runtime/plugins/agents-init/skills/agents-init/skill.json +1 -1
- package/runtime/plugins/project-orchestrator/.codex-plugin/plugin.json +1 -1
- package/runtime/plugins/project-orchestrator/plugin.json +1 -1
- package/runtime/plugins/project-orchestrator/runtime/project_cli.py +69 -9
- package/runtime/plugins/project-orchestrator/runtime/project_maintain.py +380 -27
- package/runtime/plugins/project-orchestrator/runtime/project_menu.py +18 -0
- package/runtime/plugins/project-orchestrator/runtime/project_real.py +7 -1
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
agenthelm project progress [词] 看进展:按状态分组;--status 只看一种,--all 含已完成
|
|
9
9
|
agenthelm project show <事项> 事项详情:编号、旧编号、别名或标题片段都可以
|
|
10
10
|
agenthelm project guide 项目指南
|
|
11
|
-
agenthelm project health
|
|
11
|
+
agenthelm project health 检查项目与环境(含脚手架是否与最新版一致);有必须处理的项时退出码为 1
|
|
12
12
|
agenthelm project fix [项…] 修复与更新:默认只预览,--apply 执行;--keep / --accept 选择定制文件
|
|
13
|
+
agenthelm project fix add-skeleton [路径…] 按模板补上缺少的骨架文件(已有文件不动)
|
|
14
|
+
agenthelm project fix profile [字段…] 只改所选 Profile 字段,预览里有 diff
|
|
15
|
+
agenthelm project fix --skip <ID> --reason … 永久跳过某个发现(记入随项目同步的决定文件);--unskip <ID> 撤销
|
|
13
16
|
agenthelm project record <事项|new> 记录事项:默认只预览,--apply 写入
|
|
14
17
|
agenthelm project tools [工具] 项目自行声明的工具;--run --apply 执行
|
|
15
18
|
agenthelm project capabilities 各项能力当前是否可用、为什么
|
|
@@ -19,8 +22,10 @@
|
|
|
19
22
|
--demo study|personal|research|blank 使用内置的虚构项目体验,可加 --demo-fault
|
|
20
23
|
index-broken|offline|runtime-old|conflict;演示结果都标注「演示」,不读写真实文件。
|
|
21
24
|
|
|
22
|
-
退出码:0 成功;1 没有结果或有必须处理的项;2
|
|
23
|
-
4
|
|
25
|
+
退出码:0 成功;1 没有结果或有必须处理的项;2 用法错误(含 --skip 了现在不存在的发现 ID);
|
|
26
|
+
3 运行时与项目入口不兼容;4 能力当前不可用(含决定文件损坏);5 写入冲突(别人刚改过,
|
|
27
|
+
含决定文件刚被另一台机器同步更新);6 执行失败;130 中断。
|
|
28
|
+
脚手架差异只算“建议处理”,不会让 health 退出码变成 1。
|
|
24
29
|
"""
|
|
25
30
|
from __future__ import annotations
|
|
26
31
|
|
|
@@ -231,7 +236,7 @@ def render_guide(guide: dict) -> list[str]:
|
|
|
231
236
|
return lines
|
|
232
237
|
|
|
233
238
|
|
|
234
|
-
def render_health(health: dict) -> tuple[list[str], list[dict]]:
|
|
239
|
+
def render_health(health: dict, show_skipped: bool = False) -> tuple[list[str], list[dict]]:
|
|
235
240
|
lines, numbered = [], []
|
|
236
241
|
source = health["update_source"]
|
|
237
242
|
if source["status"] == "online":
|
|
@@ -258,6 +263,18 @@ def render_health(health: dict) -> tuple[list[str], list[dict]]:
|
|
|
258
263
|
lines.append(f" 影响:{finding['impact']}")
|
|
259
264
|
for step in finding["next"]:
|
|
260
265
|
lines.append(f" 下一步:{step['label']}" + S.dim(command_hint(step["action"])))
|
|
266
|
+
if finding.get("decision"):
|
|
267
|
+
where = "只记在这台机器上" if finding["decision"]["scope"] == "machine" else "记入项目,所有机器生效"
|
|
268
|
+
lines.append(S.dim(f" 不需要?fix --skip {finding['decision']['id']} --reason …({where})"))
|
|
269
|
+
skipped = health.get("skipped") or []
|
|
270
|
+
if show_skipped:
|
|
271
|
+
lines.append(S.bold(f"已跳过({len(skipped)})") if skipped else S.dim("没有被跳过的项。"))
|
|
272
|
+
for item in skipped:
|
|
273
|
+
decision = item["decision"]
|
|
274
|
+
lines.append(f" {item['id']}:{decision.get('reason') or '(未写理由)'} "
|
|
275
|
+
+ S.dim(f"[{decision['decision']} {decision.get('decided_at', '')}]"))
|
|
276
|
+
elif skipped:
|
|
277
|
+
lines.append(S.dim(f"另有 {len(skipped)} 项已被跳过:health --show-skipped 查看"))
|
|
261
278
|
if health["ok"]:
|
|
262
279
|
lines.append(S.green("正常:") + "、".join(health["ok"]))
|
|
263
280
|
return lines, numbered
|
|
@@ -280,7 +297,10 @@ def render_plan(plan: dict, choices: dict[str, str] | None = None) -> list[str]:
|
|
|
280
297
|
for item in step["custom"]:
|
|
281
298
|
chosen = (choices or {}).get(item["path"])
|
|
282
299
|
decision = chosen or item["default"]
|
|
283
|
-
if item
|
|
300
|
+
if item.get("options"):
|
|
301
|
+
label = ("" if chosen else "默认") + {"accept": "采用(按模板处理)", "skip": "永久跳过(记入决定文件)",
|
|
302
|
+
"later": "稍后(本次不处理)"}.get(decision, decision)
|
|
303
|
+
elif item["path"] == "README.md":
|
|
284
304
|
label = ("" if chosen else "默认") + ("不改" if decision == "keep" else "追加「怎样使用」")
|
|
285
305
|
else:
|
|
286
306
|
label = ("" if chosen else "默认") + ("保留你的版本" if decision == "keep" else "采用新模板")
|
|
@@ -397,25 +417,60 @@ def cmd_guide(provider: Provider, args: argparse.Namespace) -> tuple[int, Any, l
|
|
|
397
417
|
|
|
398
418
|
|
|
399
419
|
def cmd_health(provider: Provider, args: argparse.Namespace) -> tuple[int, Any, list[str]]:
|
|
420
|
+
provider.reprompt = bool(getattr(args, "reprompt", False))
|
|
400
421
|
health = provider.health()
|
|
401
|
-
lines, _ = render_health(health)
|
|
422
|
+
lines, _ = render_health(health, bool(getattr(args, "show_skipped", False)))
|
|
402
423
|
must = any(finding["level"] == "must" for finding in health["findings"])
|
|
403
424
|
return (EXIT_ATTENTION if must else EXIT_OK), health, header(provider, "检查项目与环境") + lines
|
|
404
425
|
|
|
405
426
|
|
|
406
427
|
def cmd_fix(provider: Provider, args: argparse.Namespace) -> tuple[int, Any, list[str]]:
|
|
428
|
+
if args.skip or args.unskip:
|
|
429
|
+
return _fix_decisions(provider, args)
|
|
407
430
|
choices = {path: "keep" for path in args.keep} | {path: "accept" for path in args.accept}
|
|
408
431
|
if args.entry_name:
|
|
409
432
|
choices["entry-name"] = args.entry_name
|
|
410
|
-
|
|
433
|
+
ids, targets = _split_targets(args.ids)
|
|
434
|
+
if targets:
|
|
435
|
+
choices["_targets"] = "\n".join(targets)
|
|
436
|
+
if args.reason:
|
|
437
|
+
choices["_reason"] = args.reason
|
|
438
|
+
plan = provider.fix_plan(ids, choices)
|
|
411
439
|
lines = header(provider, "修复与更新") + render_plan(plan, choices)
|
|
412
440
|
if not args.apply:
|
|
413
441
|
lines.append(S.dim("以上为预览,没有写入。确认后加 --apply;定制文件用 --keep / --accept 指定。"))
|
|
442
|
+
if any(item.get("options") for step in plan["steps"] for item in step["custom"]):
|
|
443
|
+
lines.append(S.dim("不想要其中某项:fix --skip <ID> --reason …(ID 见 health / check);只处理几项:在处理项后列出路径或字段。"))
|
|
414
444
|
return EXIT_OK, {"plan": plan, "applied": False}, lines
|
|
415
445
|
result = provider.apply_fix(plan, choices)
|
|
416
446
|
return EXIT_OK, {"plan": plan, "applied": True, **result}, lines + render_apply(result)
|
|
417
447
|
|
|
418
448
|
|
|
449
|
+
def _split_targets(ids: list[str]) -> tuple[list[str], list[str]]:
|
|
450
|
+
if ids and ids[0] in ("add-skeleton", "profile"):
|
|
451
|
+
return ids[:1], ids[1:]
|
|
452
|
+
return ids, []
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def _fix_decisions(provider: Provider, args: argparse.Namespace) -> tuple[int, Any, list[str]]:
|
|
456
|
+
"""--skip / --unskip: write only the decision file; the check itself stays read-only."""
|
|
457
|
+
if not hasattr(provider, "decide"):
|
|
458
|
+
raise EntryError("演示项目没有决定文件", "usage")
|
|
459
|
+
result = provider.decide(args.skip, args.unskip, args.reason or "", args.apply)
|
|
460
|
+
lines = header(provider, "记录决定")
|
|
461
|
+
for item in result["decisions"]:
|
|
462
|
+
if item["mode"] == "decide":
|
|
463
|
+
verb = "已记录" if item["applied"] else "将记录"
|
|
464
|
+
lines.append(f" {verb}:{item['id']} → {item['entry']['decision']}"
|
|
465
|
+
+ (f"({item['entry']['reason']})" if item["entry"].get("reason") else "(没有写理由)")
|
|
466
|
+
+ f",写入 {item['file']}({'随项目同步' if item['scope'] == 'project' else '只在这台机器'})")
|
|
467
|
+
else:
|
|
468
|
+
lines.append(f" {'已撤销' if item['applied'] else '将撤销'}:{item['id']}({item['file']})")
|
|
469
|
+
if not args.apply:
|
|
470
|
+
lines.append(S.dim("以上为预览,没有写入。确认后加 --apply。"))
|
|
471
|
+
return EXIT_OK, result, lines
|
|
472
|
+
|
|
473
|
+
|
|
419
474
|
def _record_change(args: argparse.Namespace) -> dict:
|
|
420
475
|
status = "done" if args.close else "active" if args.reopen else args.status
|
|
421
476
|
return {"title": args.title, "goal": args.goal, "slug": args.slug, "log": args.log,
|
|
@@ -527,9 +582,14 @@ def parser() -> argparse.ArgumentParser:
|
|
|
527
582
|
progress.add_argument("--all", action="store_true", help="同时列出已完成与放弃的事项")
|
|
528
583
|
add("show", "事项详情").add_argument("item")
|
|
529
584
|
add("guide", "项目指南")
|
|
530
|
-
add("health", "检查项目与环境")
|
|
585
|
+
health = add("health", "检查项目与环境")
|
|
586
|
+
health.add_argument("--show-skipped", action="store_true", help="列出被你跳过的项及理由")
|
|
587
|
+
health.add_argument("--reprompt", action="store_true", help="忽略已记录的决定,重新评估全部差异")
|
|
531
588
|
fix = add("fix", "修复与更新")
|
|
532
|
-
fix.add_argument("ids", nargs="*")
|
|
589
|
+
fix.add_argument("ids", nargs="*", help="处理项;add-skeleton / profile 后可跟路径 / 字段")
|
|
590
|
+
fix.add_argument("--skip", action="append", default=[], metavar="ID", help="永久跳过这个发现(记入决定文件)")
|
|
591
|
+
fix.add_argument("--unskip", action="append", default=[], metavar="ID", help="撤销对这个发现的跳过")
|
|
592
|
+
fix.add_argument("--reason", help="--skip 的理由(建议写;随项目同步,换一台机器也看得到)")
|
|
533
593
|
fix.add_argument("--apply", action="store_true")
|
|
534
594
|
fix.add_argument("--keep", action="append", default=[])
|
|
535
595
|
fix.add_argument("--accept", action="append", default=[])
|