pi-rolecast 0.2.0 → 0.2.2
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/scripts/install.sh +14 -6
- package/scripts/sync_settings.py +4 -2
- package/scripts/uninstall.sh +150 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-rolecast",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Multi-agent role framework for Pi. Groups of specialist agents (coding, video, etc.) bound to per-role models, dispatched via pi-subagents. Profile-driven, gate-verified, language-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/scripts/install.sh
CHANGED
|
@@ -31,11 +31,9 @@ if [[ -n "$DRY_RUN" ]]; then
|
|
|
31
31
|
fi
|
|
32
32
|
mkdir -p "$PREFIX"
|
|
33
33
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
echo "linked $PREFIX/pi-rolecast to $FRAMEWORK_ROOT"
|
|
38
|
-
fi
|
|
34
|
+
# Remove legacy pi-agent-workflow framework symlink if it exists.
|
|
35
|
+
# v0.2.3: no longer creates ~/.pi/agent/pi-rolecast symlink — npm install
|
|
36
|
+
# path (~/.pi/agent/npm/node_modules/pi-rolecast) is canonical.
|
|
39
37
|
if [[ -e "$PREFIX/pi-agent-workflow" ]]; then
|
|
40
38
|
echo "removing legacy $PREFIX/pi-agent-workflow symlink"
|
|
41
39
|
rm -f "$PREFIX/pi-agent-workflow"
|
|
@@ -58,9 +56,19 @@ fi
|
|
|
58
56
|
# Global role symlinks for every role-packs/<group>/<role>.md.
|
|
59
57
|
agents_dir="$PREFIX/agents"
|
|
60
58
|
mkdir -p "$agents_dir"
|
|
59
|
+
# Clean up ANY pre-existing symlinks pointing at the legacy framework root.
|
|
60
|
+
# Old symlinks would dangle after `pi-agent-workflow` is removed; clean first.
|
|
61
|
+
if [[ -d "$agents_dir" ]]; then
|
|
62
|
+
while IFS= read -r stale; do
|
|
63
|
+
target="$(readlink "$stale" 2>/dev/null || true)"
|
|
64
|
+
if [[ -n "$target" && "$target" == *pi-agent-workflow* ]]; then
|
|
65
|
+
rm -f "$stale"
|
|
66
|
+
fi
|
|
67
|
+
done < <(find "$agents_dir" -maxdepth 1 -type l -name '*.md')
|
|
68
|
+
fi
|
|
61
69
|
linked=0
|
|
62
70
|
while IFS= read -r md; do
|
|
63
|
-
role=$(basename "$md" .md)
|
|
71
|
+
role=$(basename "$md" .md) # e.g. "coding-architect" (full prefixed name)
|
|
64
72
|
link_path="$agents_dir/$role.md"
|
|
65
73
|
if [[ -L "$link_path" ]]; then
|
|
66
74
|
rm -f "$link_path"
|
package/scripts/sync_settings.py
CHANGED
|
@@ -252,7 +252,8 @@ def _write_agents(agents_dir: Path, framework_root: Path,
|
|
|
252
252
|
dry_run: bool, registry) -> int:
|
|
253
253
|
"""Write project-local copies of role-packs/<group>/<role>.md for every
|
|
254
254
|
bound role. Uses full role name (`<group>-<role>`) as the filename so
|
|
255
|
-
pi-subagents can find it via @<full-name> mention syntax.
|
|
255
|
+
pi-subagents can find it via @<full-name> mention syntax.
|
|
256
|
+
"""
|
|
256
257
|
roles = available_roles(framework_root, groups=enabled_groups or None)
|
|
257
258
|
if dry_run:
|
|
258
259
|
for role_full_name, rd in sorted(roles.items()):
|
|
@@ -274,12 +275,13 @@ def _write_agents(agents_dir: Path, framework_root: Path,
|
|
|
274
275
|
print("warning: role-packs file not found: " + str(rd.file_path),
|
|
275
276
|
file=sys.stderr)
|
|
276
277
|
continue
|
|
277
|
-
dst = agents_dir / (role_full_name + ".md")
|
|
278
278
|
body = src.read_text()
|
|
279
279
|
model_id = new_overrides[role_full_name]["model"]
|
|
280
280
|
provider = _provider_for_model(model_id, registry)
|
|
281
281
|
full = (provider + "/" + model_id) if provider else model_id
|
|
282
282
|
updated = _set_frontmatter_field(body, "model", full)
|
|
283
|
+
# v0.2.0+ canonical filename
|
|
284
|
+
dst = agents_dir / (role_full_name + ".md")
|
|
283
285
|
dst.write_text(updated)
|
|
284
286
|
written += 1
|
|
285
287
|
print("wrote " + str(written) + " project-local agent files to " + str(agents_dir))
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pi-rolecast uninstaller. Removes all framework artifacts created by
|
|
3
|
+
# install.sh and sync_settings.py. Safe to run multiple times (idempotent).
|
|
4
|
+
#
|
|
5
|
+
# Removes:
|
|
6
|
+
# - ~/.pi/agent/pi-rolecast framework symlink
|
|
7
|
+
# - ~/.pi/agent/agents/*.md symlinks whose target is inside a pi-rolecast
|
|
8
|
+
# framework
|
|
9
|
+
# - .pi/agents/<framework-role>.md files matching framework role names
|
|
10
|
+
# (in cwd)
|
|
11
|
+
# - subagents.agentOverrides entries for framework roles in settings.json
|
|
12
|
+
# - empty agent directories if nothing else remains
|
|
13
|
+
#
|
|
14
|
+
# Does NOT remove:
|
|
15
|
+
# - ~/.pi/agent/npm/node_modules/pi-rolecast/ (run `pi uninstall npm:pi-rolecast` first)
|
|
16
|
+
# - user-created agent files in .pi/agents/ (e.g. custom-role.md)
|
|
17
|
+
# - user-created symlinks in ~/.pi/agent/agents/ (e.g. targeting other frameworks)
|
|
18
|
+
# - settings.json entries for non-framework roles
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
PREFIX="${HOME}/.pi/agent"
|
|
22
|
+
DRY_RUN=""
|
|
23
|
+
KEEP_PROJECT_AGENTS=""
|
|
24
|
+
SETTINGS_JSON=""
|
|
25
|
+
GLOBAL_AGENTS_DIR=""
|
|
26
|
+
PROJECT_AGENTS_DIR=""
|
|
27
|
+
FRAMEWORK_ROOT=""
|
|
28
|
+
|
|
29
|
+
while [[ $# -gt 0 ]]; do
|
|
30
|
+
case "$1" in
|
|
31
|
+
--prefix) PREFIX="$2"; shift 2 ;;
|
|
32
|
+
--framework-root) FRAMEWORK_ROOT="$2"; shift 2 ;;
|
|
33
|
+
--dry-run) DRY_RUN="1"; shift ;;
|
|
34
|
+
--settings) SETTINGS_JSON="$2"; shift 2 ;;
|
|
35
|
+
--global-agents-dir) GLOBAL_AGENTS_DIR="$2"; shift 2 ;;
|
|
36
|
+
--project-agents-dir) PROJECT_AGENTS_DIR="$2"; shift 2 ;;
|
|
37
|
+
--keep-project-agents) KEEP_PROJECT_AGENTS="1"; shift ;;
|
|
38
|
+
*) echo "unknown argument: $1" >&2; exit 1 ;;
|
|
39
|
+
esac
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
[[ -z "$SETTINGS_JSON" ]] && SETTINGS_JSON="$PREFIX/settings.json"
|
|
43
|
+
[[ -z "$GLOBAL_AGENTS_DIR" ]] && GLOBAL_AGENTS_DIR="$PREFIX/agents"
|
|
44
|
+
[[ -z "$PROJECT_AGENTS_DIR" ]] && PROJECT_AGENTS_DIR="$(pwd)/.pi/agents"
|
|
45
|
+
|
|
46
|
+
# Find framework root to enumerate framework role names. Without this we
|
|
47
|
+
# cannot tell framework-written project-local files from user customizations.
|
|
48
|
+
if [[ -z "$FRAMEWORK_ROOT" ]]; then
|
|
49
|
+
if [[ -d "./role-packs" ]]; then
|
|
50
|
+
FRAMEWORK_ROOT="$(cd . && pwd)"
|
|
51
|
+
elif [[ -d "$PREFIX/npm/node_modules/pi-rolecast/role-packs" ]]; then
|
|
52
|
+
FRAMEWORK_ROOT="$PREFIX/npm/node_modules/pi-rolecast"
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
framework_roles=()
|
|
57
|
+
if [[ -n "$FRAMEWORK_ROOT" ]]; then
|
|
58
|
+
while IFS= read -r role; do
|
|
59
|
+
framework_roles+=("$role")
|
|
60
|
+
done < <(find "$FRAMEWORK_ROOT/role-packs" -type f -name '*.md' \
|
|
61
|
+
-exec basename {} .md \; 2>/dev/null | sort -u)
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
removed=0
|
|
65
|
+
_action() {
|
|
66
|
+
# $1 = action (rm), $2 = path, $3 = reason
|
|
67
|
+
if [[ -n "$DRY_RUN" ]]; then
|
|
68
|
+
echo "would $1 $2 ($3)"
|
|
69
|
+
else
|
|
70
|
+
if "$1" "$2" 2>/dev/null; then
|
|
71
|
+
echo "$1 $2 ($3)"
|
|
72
|
+
removed=$((removed + 1))
|
|
73
|
+
fi
|
|
74
|
+
fi
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# 1. Framework symlink ~/.pi/agent/pi-rolecast
|
|
78
|
+
link="$PREFIX/pi-rolecast"
|
|
79
|
+
if [[ -L "$link" ]]; then
|
|
80
|
+
target="$(readlink "$link")"
|
|
81
|
+
case "$target" in
|
|
82
|
+
*pi-rolecast*) _action rm "$link" "framework symlink" ;;
|
|
83
|
+
esac
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# 2. Global agent symlinks ~/.pi/agent/agents/*.md
|
|
87
|
+
# Only remove symlinks whose target is inside a pi-rolecast framework.
|
|
88
|
+
if [[ -d "$GLOBAL_AGENTS_DIR" ]]; then
|
|
89
|
+
while IFS= read -r l; do
|
|
90
|
+
target="$(readlink "$l")"
|
|
91
|
+
case "$target" in
|
|
92
|
+
*pi-rolecast*) _action rm "$l" "global agent symlink" ;;
|
|
93
|
+
esac
|
|
94
|
+
done < <(find "$GLOBAL_AGENTS_DIR" -maxdepth 1 -type l -name '*.md' 2>/dev/null)
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# 3. Project-local agent files .pi/agents/<role>.md
|
|
98
|
+
# Only remove files matching framework role names. Skip symlinks (user-created).
|
|
99
|
+
if [[ -z "$KEEP_PROJECT_AGENTS" && -d "$PROJECT_AGENTS_DIR" && ${#framework_roles[@]} -gt 0 ]]; then
|
|
100
|
+
for role in "${framework_roles[@]}"; do
|
|
101
|
+
f="$PROJECT_AGENTS_DIR/$role.md"
|
|
102
|
+
[[ -e "$f" || -L "$f" ]] || continue
|
|
103
|
+
[[ -L "$f" ]] && continue
|
|
104
|
+
_action rm "$f" "project-local agent file"
|
|
105
|
+
done
|
|
106
|
+
elif [[ -z "$KEEP_PROJECT_AGENTS" && -d "$PROJECT_AGENTS_DIR" ]]; then
|
|
107
|
+
echo "warning: framework root not found, skipping project-local agent cleanup" >&2
|
|
108
|
+
echo " hint: cd into a project with .pi/rolecast.yaml, or run from pi-rolecast repo" >&2
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 4. Clean settings.json subagents.agentOverrides for framework roles
|
|
112
|
+
if [[ -f "$SETTINGS_JSON" && ${#framework_roles[@]} -gt 0 ]]; then
|
|
113
|
+
python3 - "$SETTINGS_JSON" "${framework_roles[@]}" <<'PYEOF'
|
|
114
|
+
import json, sys
|
|
115
|
+
path = sys.argv[1]
|
|
116
|
+
roles = set(sys.argv[2:])
|
|
117
|
+
try:
|
|
118
|
+
with open(path) as f:
|
|
119
|
+
s = json.load(f)
|
|
120
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
121
|
+
sys.exit(0)
|
|
122
|
+
sub = s.setdefault("subagents", {})
|
|
123
|
+
ov = sub.get("agentOverrides", {}) or {}
|
|
124
|
+
cleared = [k for k in list(ov) if k in roles]
|
|
125
|
+
for k in cleared:
|
|
126
|
+
del ov[k]
|
|
127
|
+
sub["agentOverrides"] = ov
|
|
128
|
+
s["subagents"] = sub
|
|
129
|
+
with open(path, "w") as f:
|
|
130
|
+
json.dump(s, f, indent=2, sort_keys=True)
|
|
131
|
+
f.write("\n")
|
|
132
|
+
print(f"removed {len(cleared)} framework overrides from {path}")
|
|
133
|
+
PYEOF
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# 5. Remove empty agent directories (after all cleanup)
|
|
137
|
+
for d in "$GLOBAL_AGENTS_DIR" "$PROJECT_AGENTS_DIR"; do
|
|
138
|
+
if [[ -d "$d" && -z "$(ls -A "$d" 2>/dev/null)" ]]; then
|
|
139
|
+
if [[ -n "$DRY_RUN" ]]; then
|
|
140
|
+
echo "would remove empty dir $d"
|
|
141
|
+
else
|
|
142
|
+
if rmdir "$d" 2>/dev/null; then
|
|
143
|
+
echo "rmdir $d (empty dir)"
|
|
144
|
+
removed=$((removed + 1))
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
done
|
|
149
|
+
|
|
150
|
+
echo "uninstall complete: removed $removed items"
|