gaia-cli 4.3.5__tar.gz → 4.3.7__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.
- {gaia_cli-4.3.5/src/gaia_cli.egg-info → gaia_cli-4.3.7}/PKG-INFO +2 -2
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/README.md +1 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/pyproject.toml +1 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/cardRenderer.py +14 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/commands/stats.py +3 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/graph.py +1 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/main.py +32 -20
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/pathEngine.py +6 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/prWriter.py +5 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7/src/gaia_cli.egg-info}/PKG-INFO +2 -2
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_card_renderer.py +27 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_dx.py +22 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_intake.py +2 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_path_command.py +8 -8
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_push.py +2 -2
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_stats.py +20 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_validate.py +1 -1
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/LICENSE +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/setup.cfg +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/__init__.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/__main__.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/authz.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/combinator.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/commands/__init__.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/commands/dev.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/gaia.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/named/devin-ai/autonomous-swe.md +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/named/karpathy/autoresearch.md +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/named-skills.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/combination.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/meta.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/namedSkill.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/pluginConfig.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/realSkillCatalog.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/skill.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/skillBatch.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/skillSuite.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/skillTree.schema.json +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/embeddings.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/evidence.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/formatting.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/hook.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/install.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/interactive.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/leveling.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/localContext.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/name.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/promotion.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/push.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/redaction.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/registry.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/resolver.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/scanner.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/semantic_search.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/timeline.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/treeManager.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/__init__.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/app.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/__init__.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/agent.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/hero.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/levelup.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/scan.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/screens/tree.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/theme.tcss +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/tui/tokens.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/versioning.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli.egg-info/SOURCES.txt +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli.egg-info/dependency_links.txt +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli.egg-info/entry_points.txt +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli.egg-info/requires.txt +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli.egg-info/top_level.txt +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_authz.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_crawlers.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_docs_site.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_docs_skill_explorer.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_embeddings.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_evidence_inheritance.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_formatting.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_graph.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_install.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_interactive.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_leveling.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_lifecycle.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_local_context.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_meta_ops.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_named_skills.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_packaging.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_path_engine.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_pr540_review.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_pr_writer.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_promotion.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_real_skill_catalog.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_redaction.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_registry_layout.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_scanner.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_suite_install.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_timelines.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_treeManager.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_tui_tokens.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_unlocked_at_datetime.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_verify_evidence.py +0 -0
- {gaia_cli-4.3.5 → gaia_cli-4.3.7}/tests/test_workflows.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gaia-cli
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.7
|
|
4
4
|
Summary: Gaia AI Agent Skill Registry CLI
|
|
5
5
|
Author: Gaia contributors
|
|
6
6
|
License: MIT
|
|
@@ -167,7 +167,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
|
|
|
167
167
|
**1. Install the CLI**
|
|
168
168
|
|
|
169
169
|
<!-- gaia:version-start -->
|
|
170
|
-
Current Gaia CLI version: `4.3.
|
|
170
|
+
Current Gaia CLI version: `4.3.7`.
|
|
171
171
|
|
|
172
172
|
```bash
|
|
173
173
|
curl -fsSL https://gaia.tiongson.co/install.sh | sh
|
|
@@ -118,7 +118,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
|
|
|
118
118
|
**1. Install the CLI**
|
|
119
119
|
|
|
120
120
|
<!-- gaia:version-start -->
|
|
121
|
-
Current Gaia CLI version: `4.3.
|
|
121
|
+
Current Gaia CLI version: `4.3.7`.
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
curl -fsSL https://gaia.tiongson.co/install.sh | sh
|
|
@@ -561,6 +561,20 @@ def render_appraise_card(
|
|
|
561
561
|
deriv_line = prefix + ", ".join(deriv_items)
|
|
562
562
|
if len(derivatives) > 4:
|
|
563
563
|
deriv_line += f" +{len(derivatives) - 4} more"
|
|
564
|
+
# Truncate at comma boundary instead of mid-word
|
|
565
|
+
if len(deriv_line) > inner:
|
|
566
|
+
truncated = prefix
|
|
567
|
+
for i, item in enumerate(deriv_items):
|
|
568
|
+
candidate = truncated + (", " if i > 0 else "") + item
|
|
569
|
+
if len(candidate) > inner - 2: # leave room for " …"
|
|
570
|
+
remaining = len(deriv_items) - i + (len(derivatives) - 4 if len(derivatives) > 4 else 0)
|
|
571
|
+
truncated += f" +{remaining} more" if remaining > 0 else ""
|
|
572
|
+
break
|
|
573
|
+
truncated = candidate
|
|
574
|
+
else:
|
|
575
|
+
if len(derivatives) > 4:
|
|
576
|
+
truncated += f" +{len(derivatives) - 4} more"
|
|
577
|
+
deriv_line = truncated
|
|
564
578
|
lines.append(f"{bc}{V}{r} {fg(*COLOR_MUTED)}{_pad(deriv_line, inner)}{r} {bc}{V}{r}")
|
|
565
579
|
else:
|
|
566
580
|
lines.append(f"{bc}{V}{r} {fg(*COLOR_MUTED)}{_pad('Unlocks: (terminal skill)', inner)}{r} {bc}{V}{r}")
|
|
@@ -133,7 +133,9 @@ def collect_stats(registry_path: str | Path) -> dict:
|
|
|
133
133
|
]
|
|
134
134
|
|
|
135
135
|
type_counts = Counter(skill.get("type", "unknown") for skill in skills)
|
|
136
|
-
level_counts = Counter(
|
|
136
|
+
level_counts = Counter(
|
|
137
|
+
skill["level"] for skill in skills if "level" in skill
|
|
138
|
+
)
|
|
137
139
|
effective_level_counts = Counter()
|
|
138
140
|
demerit_counts: Counter[str] = Counter()
|
|
139
141
|
skills_with_demerits = 0
|
|
@@ -1205,7 +1205,7 @@ def graph_command(args: Any) -> None:
|
|
|
1205
1205
|
pass # Degrade gracefully to canon mode
|
|
1206
1206
|
|
|
1207
1207
|
out_path = write_graph_artifact(registry_path, output=output, fmt=fmt, user_ctx=user_ctx)
|
|
1208
|
-
print(f" saved {
|
|
1208
|
+
print(f" saved {out_path}")
|
|
1209
1209
|
|
|
1210
1210
|
# Regenerate the GEXF from current node data
|
|
1211
1211
|
if fmt == "html":
|
|
@@ -294,8 +294,8 @@ def init_command(args):
|
|
|
294
294
|
config_dir = '.gaia'
|
|
295
295
|
os.makedirs(config_dir, exist_ok=True)
|
|
296
296
|
config_path = os.path.join(config_dir, 'config.toml')
|
|
297
|
-
if os.path.exists(config_path):
|
|
298
|
-
print("Gaia is already initialized in this repository.")
|
|
297
|
+
if os.path.exists(config_path) and not getattr(args, "force", False):
|
|
298
|
+
print("Gaia is already initialized in this repository. Use --force to overwrite.")
|
|
299
299
|
return
|
|
300
300
|
|
|
301
301
|
username = args.user or _detect_github_username()
|
|
@@ -472,16 +472,20 @@ def scan_command(args):
|
|
|
472
472
|
skill_map = {s['id']: s for s in graph_data.get('skills', [])}
|
|
473
473
|
unlocked = [s.get('skillId') for s in tree.get('unlockedSkills', [])]
|
|
474
474
|
combos = get_combinations(graph_data, unlocked, resolved)
|
|
475
|
-
if combos
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
print(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
475
|
+
if combos:
|
|
476
|
+
# Persist fusion candidates so `gaia fuse` can find them
|
|
477
|
+
tree['pendingCombinations'] = combos
|
|
478
|
+
save_tree(username, tree, registry_path=args.registry)
|
|
479
|
+
if not quiet:
|
|
480
|
+
print("\nNew fusion candidates:")
|
|
481
|
+
for c in combos:
|
|
482
|
+
result_skill = skill_map.get(c['candidateResult'], {})
|
|
483
|
+
result_type = result_skill.get('type', 'extra')
|
|
484
|
+
print(render_fusion_diagram(
|
|
485
|
+
c['detectedSkills'], c['candidateResult'], result_type,
|
|
486
|
+
canon=canon, ctx=ctx
|
|
487
|
+
))
|
|
488
|
+
print("Run `gaia fuse <skill>` to confirm.")
|
|
485
489
|
|
|
486
490
|
# Path engine integration
|
|
487
491
|
old_paths = load_paths()
|
|
@@ -537,7 +541,7 @@ def render_user_tree_outputs(username: str, tree: dict | None, graph_data: dict
|
|
|
537
541
|
with open(html_path, "w", encoding="utf-8") as f:
|
|
538
542
|
f.write(html)
|
|
539
543
|
if not quiet:
|
|
540
|
-
print(f" saved {
|
|
544
|
+
print(f" saved {html_path} & {md_path}")
|
|
541
545
|
return html_path, md_path
|
|
542
546
|
|
|
543
547
|
|
|
@@ -599,7 +603,8 @@ def lookup_command(args):
|
|
|
599
603
|
display = skill.get("name") or f"/{skill_id}"
|
|
600
604
|
print(f"{display}")
|
|
601
605
|
|
|
602
|
-
|
|
606
|
+
user_level = ctx.skill_level(skill_id) if ctx else skill.get('level', '?')
|
|
607
|
+
print(f"Type: {skill.get('type', 'unknown')} Level: {user_level}")
|
|
603
608
|
if skill.get("description"):
|
|
604
609
|
print(skill["description"])
|
|
605
610
|
|
|
@@ -792,7 +797,7 @@ def promote_command(args):
|
|
|
792
797
|
return
|
|
793
798
|
if not skill_id:
|
|
794
799
|
# Try interactive picker
|
|
795
|
-
candidates = promotable_candidates(
|
|
800
|
+
candidates = promotable_candidates(args.registry, username)
|
|
796
801
|
if candidates:
|
|
797
802
|
picked = select_promotion_candidate(candidates, "Select skill to promote:")
|
|
798
803
|
if picked:
|
|
@@ -1284,9 +1289,9 @@ def install_command(args):
|
|
|
1284
1289
|
interactive_install(args.registry, location=location)
|
|
1285
1290
|
return
|
|
1286
1291
|
if not args.skill_id:
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1292
|
+
print("Usage: gaia install <skill_id>", file=sys.stderr)
|
|
1293
|
+
print(" To update all installed skills, use: gaia update", file=sys.stderr)
|
|
1294
|
+
sys.exit(2)
|
|
1290
1295
|
|
|
1291
1296
|
# Use suite logic if flagged or implicitly requested
|
|
1292
1297
|
if getattr(args, 'ultimate', False) or getattr(args, 'suite', False):
|
|
@@ -1300,7 +1305,7 @@ def install_command(args):
|
|
|
1300
1305
|
|
|
1301
1306
|
def uninstall_command(args):
|
|
1302
1307
|
from gaia_cli.install import uninstall_skill
|
|
1303
|
-
success = uninstall_skill(args.skill_id)
|
|
1308
|
+
success = uninstall_skill(args.skill_id.lstrip("/"))
|
|
1304
1309
|
if not success:
|
|
1305
1310
|
sys.exit(1)
|
|
1306
1311
|
|
|
@@ -1362,7 +1367,7 @@ def skills_command(args):
|
|
|
1362
1367
|
|
|
1363
1368
|
|
|
1364
1369
|
available = [
|
|
1365
|
-
{"id": sid, "name": meta.get("name") or sid, "level": meta.get("level", "?"), "description": meta.get("description", "")}
|
|
1370
|
+
{"id": sid, "name": meta.get("name") or sid, "level": meta.get("level", "?"), "type": meta.get("type", "basic"), "description": meta.get("description", "")}
|
|
1366
1371
|
for sid, meta in list_available(args.registry)
|
|
1367
1372
|
]
|
|
1368
1373
|
items = available + pending
|
|
@@ -1459,6 +1464,12 @@ def pull_command(args):
|
|
|
1459
1464
|
print("Note: Registry could not be updated via git (no upstream configured). Local registry unchanged.", file=sys.stderr)
|
|
1460
1465
|
else:
|
|
1461
1466
|
print(f"Warning: git pull failed. Local registry unchanged.\n {stderr}", file=sys.stderr)
|
|
1467
|
+
else:
|
|
1468
|
+
stdout = res.stdout.strip()
|
|
1469
|
+
if "Already up to date" in stdout:
|
|
1470
|
+
print("Registry is already up to date.")
|
|
1471
|
+
else:
|
|
1472
|
+
print("Registry updated successfully.")
|
|
1462
1473
|
|
|
1463
1474
|
|
|
1464
1475
|
def update_command(args):
|
|
@@ -1647,6 +1658,7 @@ def get_parser():
|
|
|
1647
1658
|
init_parser.add_argument('--registry-ref', help='Gaia registry URL to write into .gaia/config.toml')
|
|
1648
1659
|
init_parser.add_argument('--scan', action='append', help='Path to scan; repeat for multiple paths')
|
|
1649
1660
|
init_parser.add_argument('--yes', action='store_true', help='Use non-interactive defaults')
|
|
1661
|
+
init_parser.add_argument('--force', action='store_true', help='Overwrite existing .gaia/config.toml')
|
|
1650
1662
|
init_parser.add_argument(
|
|
1651
1663
|
'--auto-prompt-combinations',
|
|
1652
1664
|
action='store_true',
|
|
@@ -144,7 +144,12 @@ def render_unlock_path(
|
|
|
144
144
|
total += c_total
|
|
145
145
|
return owned, total
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
# Count prerequisites only (children of root — root is the target, not a prereq).
|
|
148
|
+
owned_count, total_count = 0, 0
|
|
149
|
+
for child in tree.get('children', []):
|
|
150
|
+
c_owned, c_total = _count(child)
|
|
151
|
+
owned_count += c_owned
|
|
152
|
+
total_count += c_total
|
|
148
153
|
|
|
149
154
|
# Render root line manually.
|
|
150
155
|
root_sid = tree['id']
|
|
@@ -203,6 +203,11 @@ def open_intake_issue(username, batch_data, batch_path=None, repo_root="."):
|
|
|
203
203
|
|
|
204
204
|
issue_url = issue.stdout.strip().splitlines()[-1] if issue.stdout.strip() else ""
|
|
205
205
|
print(f"Success: intake issue opened ({issue_url}).")
|
|
206
|
+
# Clean up temp body file
|
|
207
|
+
try:
|
|
208
|
+
os.remove(body_path)
|
|
209
|
+
except OSError:
|
|
210
|
+
pass
|
|
206
211
|
return issue_url or None
|
|
207
212
|
|
|
208
213
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gaia-cli
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.7
|
|
4
4
|
Summary: Gaia AI Agent Skill Registry CLI
|
|
5
5
|
Author: Gaia contributors
|
|
6
6
|
License: MIT
|
|
@@ -167,7 +167,7 @@ Skills rank up through **verifiable evidence** (Class A/B/C) and can be demoted
|
|
|
167
167
|
**1. Install the CLI**
|
|
168
168
|
|
|
169
169
|
<!-- gaia:version-start -->
|
|
170
|
-
Current Gaia CLI version: `4.3.
|
|
170
|
+
Current Gaia CLI version: `4.3.7`.
|
|
171
171
|
|
|
172
172
|
```bash
|
|
173
173
|
curl -fsSL https://gaia.tiongson.co/install.sh | sh
|
|
@@ -18,6 +18,7 @@ from gaia_cli.cardRenderer import (
|
|
|
18
18
|
load_and_render,
|
|
19
19
|
_pad,
|
|
20
20
|
_wrap_lines,
|
|
21
|
+
render_appraise_card,
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
|
|
@@ -520,3 +521,29 @@ class TestRenderFusionDiagram:
|
|
|
520
521
|
# First line (shorter name) should be padded
|
|
521
522
|
assert "/ab" in lines[0]
|
|
522
523
|
assert "/longername" in lines[2]
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def test_render_appraise_card_truncation():
|
|
527
|
+
skill_data = {
|
|
528
|
+
"id": "test-skill",
|
|
529
|
+
"name": "Test Skill",
|
|
530
|
+
"type": "basic",
|
|
531
|
+
"level": "0★",
|
|
532
|
+
"rarity": "common",
|
|
533
|
+
"description": "Short description.",
|
|
534
|
+
}
|
|
535
|
+
derivatives = [
|
|
536
|
+
{"id": "d1", "name": "First Derivative Skill Name"},
|
|
537
|
+
{"id": "d2", "name": "Second Derivative Skill Name"},
|
|
538
|
+
{"id": "d3", "name": "Third Derivative Skill Name"},
|
|
539
|
+
]
|
|
540
|
+
output = render_appraise_card(
|
|
541
|
+
skill_data=skill_data,
|
|
542
|
+
prereq_status={},
|
|
543
|
+
derivatives=derivatives,
|
|
544
|
+
actions=[],
|
|
545
|
+
)
|
|
546
|
+
assert "First Derivative Skill Name" in output
|
|
547
|
+
assert "+2 more" in output
|
|
548
|
+
assert "Second Derivative" not in output
|
|
549
|
+
|
|
@@ -445,3 +445,25 @@ def test_gaia_uninstall_command_removes_skill(tmp_path, monkeypatch):
|
|
|
445
445
|
from gaia_cli.install import load_manifest
|
|
446
446
|
manifest = load_manifest()
|
|
447
447
|
assert not any(e["id"] == "testuser/test-skill" for e in manifest["installed"])
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def test_init_force_overwrite(tmp_path, monkeypatch, capsys):
|
|
451
|
+
monkeypatch.chdir(tmp_path)
|
|
452
|
+
|
|
453
|
+
# First init
|
|
454
|
+
run_cli(monkeypatch, ["init", "--user", "firstuser", "--yes"])
|
|
455
|
+
config = parse_config(tmp_path / ".gaia" / "config.toml")
|
|
456
|
+
assert config["username"] == "firstuser"
|
|
457
|
+
|
|
458
|
+
# Second init without --force (should print message and not overwrite)
|
|
459
|
+
run_cli(monkeypatch, ["init", "--user", "seconduser", "--yes"])
|
|
460
|
+
output = capsys.readouterr().out
|
|
461
|
+
assert "Gaia is already initialized in this repository. Use --force to overwrite." in output
|
|
462
|
+
config = parse_config(tmp_path / ".gaia" / "config.toml")
|
|
463
|
+
assert config["username"] == "firstuser" # unchanged
|
|
464
|
+
|
|
465
|
+
# Third init with --force (should overwrite)
|
|
466
|
+
run_cli(monkeypatch, ["init", "--user", "seconduser", "--yes", "--force"])
|
|
467
|
+
config = parse_config(tmp_path / ".gaia" / "config.toml")
|
|
468
|
+
assert config["username"] == "seconduser" # overwritten
|
|
469
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
3
|
import subprocess
|
|
4
|
+
import sys
|
|
4
5
|
import tempfile
|
|
5
6
|
import unittest
|
|
6
7
|
|
|
@@ -15,7 +16,7 @@ def run_validate_intake(intake_dir, *extra_args):
|
|
|
15
16
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
16
17
|
result = subprocess.run(
|
|
17
18
|
[
|
|
18
|
-
|
|
19
|
+
sys.executable,
|
|
19
20
|
VALIDATE_INTAKE_SCRIPT,
|
|
20
21
|
"--intake-dir",
|
|
21
22
|
intake_dir,
|
|
@@ -236,23 +236,23 @@ class TestRenderUnlockPath:
|
|
|
236
236
|
def test_basic_leaf_renders(self, linear_graph):
|
|
237
237
|
text = render_unlock_path(linear_graph, "a", set())
|
|
238
238
|
assert "a" in text
|
|
239
|
-
# leaf has no children, summary should say 0 owned out of
|
|
240
|
-
assert "0 /
|
|
239
|
+
# leaf has no children, summary should say 0 owned out of 0
|
|
240
|
+
assert "0 / 0" in text
|
|
241
241
|
|
|
242
242
|
def test_footer_counts_correct(self, linear_graph):
|
|
243
243
|
text = render_unlock_path(linear_graph, "c", set())
|
|
244
|
-
#
|
|
245
|
-
assert "0 /
|
|
246
|
-
assert "
|
|
244
|
+
# 2 prerequisites total (a, b), 0 owned
|
|
245
|
+
assert "0 / 2" in text
|
|
246
|
+
assert "2 skill(s) needed" in text
|
|
247
247
|
|
|
248
248
|
def test_footer_with_owned(self, linear_graph):
|
|
249
249
|
# unlock_path stops recursing into owned nodes, so the visible tree
|
|
250
250
|
# for 'c' with owned={'a','b'} is: c(missing) + b(owned, no children).
|
|
251
251
|
# 'a' is not in the tree because b is already owned → recursion stops.
|
|
252
|
-
# Count:
|
|
252
|
+
# Count: 1 prerequisite total (b), 1 owned (b).
|
|
253
253
|
text = render_unlock_path(linear_graph, "c", {"a", "b"})
|
|
254
|
-
assert "1 /
|
|
255
|
-
assert "
|
|
254
|
+
assert "1 / 1" in text
|
|
255
|
+
assert "0 skill(s) needed" in text
|
|
256
256
|
|
|
257
257
|
def test_owned_only_prunes_owned_branches(self, linear_graph):
|
|
258
258
|
"""--owned-only prunes the display of owned 'b' from the output."""
|
|
@@ -37,7 +37,7 @@ class TestGaiaPush(unittest.TestCase):
|
|
|
37
37
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
38
38
|
result = subprocess.run(
|
|
39
39
|
[
|
|
40
|
-
|
|
40
|
+
sys.executable,
|
|
41
41
|
CLI_PATH,
|
|
42
42
|
"--registry",
|
|
43
43
|
REPO_ROOT,
|
|
@@ -83,7 +83,7 @@ class TestGaiaPush(unittest.TestCase):
|
|
|
83
83
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
84
84
|
result = subprocess.run(
|
|
85
85
|
[
|
|
86
|
-
|
|
86
|
+
sys.executable,
|
|
87
87
|
CLI_PATH,
|
|
88
88
|
"--registry",
|
|
89
89
|
registry,
|
|
@@ -114,3 +114,23 @@ def test_stats_cli_prints_summary(tmp_path, monkeypatch, capsys):
|
|
|
114
114
|
assert "Gaia Registry — 4 skills 1 edges" in output
|
|
115
115
|
assert "Class A" in output
|
|
116
116
|
assert "Effective level breakdown" in output
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_collect_stats_missing_level(tmp_path):
|
|
120
|
+
registry = tmp_path / "registry"
|
|
121
|
+
registry.mkdir(parents=True, exist_ok=True)
|
|
122
|
+
(registry / "gaia.json").write_text(
|
|
123
|
+
json.dumps(
|
|
124
|
+
{
|
|
125
|
+
"skills": [
|
|
126
|
+
{"id": "tokenize", "type": "basic", "evidence": []}, # No 'level' key
|
|
127
|
+
],
|
|
128
|
+
"edges": [],
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
encoding="utf-8",
|
|
132
|
+
)
|
|
133
|
+
stats = collect_stats(tmp_path)
|
|
134
|
+
assert "?" not in stats["level_counts"]
|
|
135
|
+
assert "level_counts" in stats
|
|
136
|
+
|
|
@@ -17,7 +17,7 @@ def run_validate(graph_path):
|
|
|
17
17
|
env = os.environ.copy()
|
|
18
18
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
19
19
|
result = subprocess.run(
|
|
20
|
-
[
|
|
20
|
+
[sys.executable, VALIDATE_SCRIPT, "--graph", graph_path],
|
|
21
21
|
capture_output=True,
|
|
22
22
|
text=True,
|
|
23
23
|
encoding="utf-8",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/named/devin-ai/autonomous-swe.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/pluginConfig.schema.json
RENAMED
|
File without changes
|
{gaia_cli-4.3.5 → gaia_cli-4.3.7}/src/gaia_cli/data/registry/schema/realSkillCatalog.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|