Fix agent format in opencode adapter

This commit is contained in:
nunziati
2026-04-10 12:43:51 +02:00
parent e2767a7399
commit 9673bca7c2
18 changed files with 204 additions and 113 deletions

View File

@@ -7,7 +7,7 @@
# Claude Code expects in the user's vault.
# =============================================================================
FRAMEWORK="claude-code"
CC_FRAMEWORK="claude-code"
# Capability → CC tools mapping. Each capability expands into one or more
# Claude Code tool names. The expansion is order-preserving.
@@ -146,7 +146,7 @@ adapter_translate_hooks() {
while IFS= read -r yaml; do
[[ -z "$yaml" ]] && continue
should_include "$yaml" "$FRAMEWORK" || continue
should_include "$yaml" "$CC_FRAMEWORK" || continue
local meta; meta="$(parse_hook_yaml "$yaml")"
local name; name="$(echo "$meta" | grep '^name=' | head -1 | cut -d= -f2- || true)"
local script; script="$(echo "$meta" | grep '^script=' | head -1 | cut -d= -f2- || true)"
@@ -205,7 +205,7 @@ adapter_translate_agents() {
while IFS= read -r agent; do
[[ -z "$agent" ]] && continue
should_include "$agent" "$FRAMEWORK" || continue
should_include "$agent" "$CC_FRAMEWORK" || continue
local name; name="$(parse_frontmatter "$agent" name)"
local model; model="$(parse_frontmatter "$agent" model)"
local caps; caps="$(parse_capabilities "$agent")"
@@ -250,7 +250,7 @@ adapter_translate_skills() {
[[ -d "$src" ]] || return 0
for skill_dir in "$src"/*/; do
[[ -f "${skill_dir}SKILL.md" ]] || continue
should_include "${skill_dir}SKILL.md" "$FRAMEWORK" || continue
should_include "${skill_dir}SKILL.md" "$CC_FRAMEWORK" || continue
local name; name="$(basename "$skill_dir")"
local out="$dst/.claude/skills/$name"
mkdir -p "$out"
@@ -267,7 +267,7 @@ adapter_translate_references() {
mkdir -p "$out"
for f in "$src"/*.md; do
[[ -f "$f" ]] || continue
should_include "$f" "$FRAMEWORK" || continue
should_include "$f" "$CC_FRAMEWORK" || continue
cp "$f" "$out/"
done
}

View File

@@ -15,10 +15,24 @@ CAPABILITY_VOCAB="read write edit bash webfetch websearch notebook task todo"
# The closed set of hook event names the source .hook.yaml may declare.
EVENT_VOCAB="before-tool-use after-tool-use on-notification on-session-start on-prompt-submit"
# ── Path rewriting ───────────────────────────────────────────────────────────
# rewrite_framework_paths <file> <target_fw_dir> <target_dispatcher>
# Rewrites source-canonical framework path references in a text file in-place.
# Source files use .claude/ and CLAUDE.md as the canonical form.
# Call this after copying any text file from source to dist for non-CC frameworks.
# No-op when target_fw_dir is "claude" (i.e. building for claude-code, whose
# canonical output paths already match the source form — no rewrite needed).
rewrite_framework_paths() {
local file="$1" tgt_dir="$2" tgt_dispatcher="$3"
[[ "$tgt_dir" == "claude" && "$tgt_dispatcher" == "CLAUDE.md" ]] && return 0
sed -i \
-e "s|\.claude/|.${tgt_dir}/|g" \
-e "s|CLAUDE\.md|${tgt_dispatcher}|g" \
"$file"
}
# ── Parsing helpers ──────────────────────────────────────────────────────────
# Defined in subsequent tasks: parse_frontmatter, parse_capabilities,
# parse_hook_yaml, agent_body, should_include, enumerate_agents,
# enumerate_hooks, json_object.
# parse_frontmatter <file> <key>
# Echoes the value of a top-level YAML key from the file's --- ... --- block.

View File

@@ -8,6 +8,8 @@
# =============================================================================
OC_FRAMEWORK="opencode"
OC_FW_DIR="opencode"
OC_DISPATCHER="AGENTS.md"
# Capability → opencode permission key. Returns the permission key to set to
# "allow" for each capability, or empty string for capabilities that have no
@@ -68,16 +70,17 @@ oc_model_to_provider() {
# adapter_translate_dispatcher <source_dispatcher_md> <dest_dir>
# Copies the source DISPATCHER.md to dest_dir/AGENTS.md (opencode's vault-root
# dispatcher filename). No content translation.
# dispatcher filename). Rewrites .claude/ and CLAUDE.md references in the body.
adapter_translate_dispatcher() {
local src="$1" dst="$2"
[[ -f "$src" ]] || return 0
mkdir -p "$dst"
cp "$src" "$dst/AGENTS.md"
rewrite_framework_paths "$dst/AGENTS.md" "$OC_FW_DIR" "$OC_DISPATCHER"
}
# adapter_translate_references <source_refs_dir> <dest_root>
# Verbatim copy of *.md into dest_root/.opencode/references/.
# Copies *.md into dest_root/.opencode/references/, rewriting framework paths.
adapter_translate_references() {
local src="$1" dst="$2"
[[ -d "$src" ]] || return 0
@@ -87,11 +90,13 @@ adapter_translate_references() {
[[ -f "$f" ]] || continue
should_include "$f" "$OC_FRAMEWORK" || continue
cp "$f" "$out/"
rewrite_framework_paths "$out/$(basename "$f")" "$OC_FW_DIR" "$OC_DISPATCHER"
done
}
# adapter_translate_skills <source_skills_dir> <dest_root>
# Copies each skill directory's SKILL.md into dest_root/.opencode/skills/<name>/.
# Copies each skill directory's SKILL.md into dest_root/.opencode/skills/<name>/,
# rewriting framework paths in the body.
adapter_translate_skills() {
local src="$1" dst="$2"
[[ -d "$src" ]] || return 0
@@ -102,40 +107,10 @@ adapter_translate_skills() {
local out="$dst/.opencode/skills/$name"
mkdir -p "$out"
cp "${skill_dir}SKILL.md" "$out/SKILL.md"
rewrite_framework_paths "$out/SKILL.md" "$OC_FW_DIR" "$OC_DISPATCHER"
done
}
# _oc_flatten_description <agent_file>
# Reads the description field from the source agent, collapsing any YAML
# folded continuation lines into a single line with whitespace normalised.
# Echoes the bare description text with no leading/trailing quotes.
_oc_flatten_description() {
local file="$1"
awk '
/^---$/ { fm++; next }
fm == 1 && /^description:/ {
sub(/^description:[[:space:]]*/, "")
desc = $0
in_desc = 1
next
}
fm == 1 && in_desc && /^[[:space:]]/ {
sub(/^[[:space:]]+/, "")
desc = desc " " $0
next
}
fm == 1 && in_desc { in_desc = 0 }
fm >= 2 { exit }
END {
# Collapse runs of whitespace
gsub(/[[:space:]]+/, " ", desc)
sub(/^[[:space:]]+/, "", desc)
sub(/[[:space:]]+$/, "", desc)
print desc
}
' "$file"
}
# adapter_translate_agents <source_agents_dir> <dest_root>
# For each *.md in source_agents_dir, translate the capabilities frontmatter
# into an opencode permission block, map the model, and write to
@@ -153,7 +128,6 @@ adapter_translate_agents() {
local model_raw; model_raw="$(parse_frontmatter "$agent" model)"
local mode_raw; mode_raw="$(parse_frontmatter "$agent" mode)"
local caps; caps="$(parse_capabilities "$agent")"
local desc; desc="$(_oc_flatten_description "$agent")"
local model_out; model_out="$(oc_model_to_provider "$model_raw")"
local mode_out="${mode_raw:-subagent}"
@@ -174,7 +148,8 @@ adapter_translate_agents() {
local out_file="$out_dir/$(basename "$agent")"
{
echo "---"
echo "description: \"$desc\""
# Copy description block verbatim (may be folded YAML with continuation lines)
awk '/^---$/{n++; next} n==1 && /^description:/{print; in_desc=1; next} n==1 && in_desc && /^[[:space:]]/{print; next} n==1 && in_desc && !/^[[:space:]]/{in_desc=0} n>=2{exit}' "$agent"
echo "mode: $mode_out"
echo "model: $model_out"
if [[ -z "$perms" ]]; then
@@ -189,6 +164,7 @@ adapter_translate_agents() {
echo ""
agent_body "$agent"
} > "$out_file"
rewrite_framework_paths "$out_file" "$OC_FW_DIR" "$OC_DISPATCHER"
done < <(enumerate_agents "$src")
}
@@ -252,6 +228,7 @@ adapter_translate_hooks() {
[[ -f "$src/$script" ]] || continue
cp "$src/$script" "$hooks_out/$script"
chmod +x "$hooks_out/$script"
rewrite_framework_paths "$hooks_out/$script" "$OC_FW_DIR" "$OC_DISPATCHER"
have_any=1
done < <(enumerate_hooks "$src")

View File

@@ -63,13 +63,17 @@ fi
# ── Check for existing installation ──────────────────────────────────────────
EXISTING=0
[[ -d "$VAULT_DIR/.claude" ]] && EXISTING=1
[[ -f "$VAULT_DIR/CLAUDE.md" ]] && EXISTING=1
[[ -d "$VAULT_DIR/.claude" ]] && EXISTING=1
[[ -f "$VAULT_DIR/CLAUDE.md" ]] && EXISTING=1
[[ -d "$VAULT_DIR/.opencode" ]] && EXISTING=1
[[ -f "$VAULT_DIR/AGENTS.md" ]] && EXISTING=1
if [[ $EXISTING -eq 1 ]]; then
warn "An existing installation was detected:"
[[ -d "$VAULT_DIR/.claude" ]] && warn " .claude/ directory exists"
[[ -d "$VAULT_DIR/.claude" ]] && warn " .claude/ directory exists"
[[ -f "$VAULT_DIR/CLAUDE.md" ]] && warn " CLAUDE.md exists"
[[ -d "$VAULT_DIR/.opencode" ]] && warn " .opencode/ directory exists"
[[ -f "$VAULT_DIR/AGENTS.md" ]] && warn " AGENTS.md exists"
echo ""
echo -e " ${BOLD}The installer will overwrite core files. Custom agents are never deleted.${NC}"
echo -e " ${DIM}Your vault notes are never touched.${NC}"
@@ -114,6 +118,7 @@ case "$FRAMEWORK" in
die "Unknown framework: $FRAMEWORK (install layout not defined)"
;;
esac
FRAMEWORK_VAULT_DIR="$VAULT_COMPONENTS_DIR"
# ── Migrate legacy manifests (if any) ────────────────────────────────────────
manifest_migrate
@@ -207,25 +212,36 @@ echo ""
echo -e "${GREEN}${BOLD} Setup complete!${NC}"
echo ""
echo -e " ${VAULT_DIR}/"
echo -e " ├── .claude/"
FW_DIR_NAME="$(basename "$VAULT_COMPONENTS_DIR")"
DISPATCHER_NAME="$(basename "$DISPATCHER_DST")"
echo -e " ├── .${FW_DIR_NAME}/"
echo -e " │ ├── agents/ ${DIM}← agents${NC}"
echo -e " │ ├── skills/ ${DIM}← skills${NC}"
echo -e " │ ├── hooks/ ${DIM}← hooks${NC}"
echo -e " │ ├── settings.json ${DIM}← hooks configuration${NC}"
if [[ $HAS_PLUGINS -eq 1 ]]; then
echo -e " │ ├── plugins/ ${DIM}← hook plugins${NC}"
else
echo -e " │ ├── settings.json ${DIM}← hooks configuration${NC}"
fi
echo -e " │ └── references/ ${DIM}← shared docs${NC}"
echo -e " ├── Meta/"
echo -e " │ └── scripts/ ${DIM}${ORCH_COUNT:-0} orchestra scripts${NC}"
echo -e " ── CLAUDE.md ${DIM}← project instructions${NC}"
echo -e " ── ${DISPATCHER_NAME} ${DIM}← project instructions${NC}"
if [[ "$MCP_ANSWER" =~ ^[Yy]$ ]]; then
echo -e " └── .mcp.json ${DIM}← Gmail + Calendar${NC}"
fi
if [[ $DEP_COUNT -gt 0 ]]; then
echo ""
warn "$DEP_COUNT file(s) were deprecated (moved to .claude/deprecated/)"
warn "$DEP_COUNT file(s) were deprecated (moved to .${FW_DIR_NAME}/deprecated/)"
fi
echo ""
echo -e " ${BOLD}Next steps:${NC}"
echo -e " 1. Open Claude Code in your vault folder"
if [[ "$FRAMEWORK" == "opencode" ]]; then
echo -e " 1. Open opencode in your vault folder"
else
echo -e " 1. Open Claude Code in your vault folder"
fi
echo -e " 2. Say: ${BOLD}\"Initialize my vault\"${NC}"
echo -e " 3. The Architect will guide you through setup"
echo ""

View File

@@ -158,12 +158,16 @@ merge_marked_file() {
}
# ── Manifest helpers ──────────────────────────────────────────────────────────
# Single unified manifest at $VAULT_DIR/.claude/.mbifc-manifest
# Single unified manifest at $VAULT_DIR/.{framework}/.mbifc-manifest
# Format: INI-style with [section] headers, one entry per line.
#
# FRAMEWORK_VAULT_DIR must be set before calling these functions (e.g.
# $VAULT_DIR/.claude for claude-code, $VAULT_DIR/.opencode for opencode).
# Defaults to $VAULT_DIR/.claude for backwards compatibility.
manifest_read() {
local section="$1"
local file="$VAULT_DIR/.claude/.mbifc-manifest"
local file="${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}/.mbifc-manifest"
[[ -f "$file" ]] || return 0
awk -v sec="[$section]" '
$0 == sec { found=1; next }
@@ -175,7 +179,7 @@ manifest_read() {
manifest_write() {
local section="$1"; shift
local entries=("$@")
local file="$VAULT_DIR/.claude/.mbifc-manifest"
local file="${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}/.mbifc-manifest"
mkdir -p "$(dirname "$file")"
local tmpfile; tmpfile="$(mktemp)"
local in_section=0 section_written=0
@@ -211,7 +215,7 @@ manifest_write() {
manifest_remove() {
local section="$1" name="$2"
local file="$VAULT_DIR/.claude/.mbifc-manifest"
local file="${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}/.mbifc-manifest"
[[ -f "$file" ]] || return 0
local tmpfile; tmpfile="$(mktemp)"
local in_section=0
@@ -227,8 +231,9 @@ manifest_remove() {
# Converts legacy per-directory .core-manifest files to the unified format.
# Runs only when legacy files are present; idempotent thereafter.
manifest_migrate() {
local agents_mf="$VAULT_DIR/.claude/agents/.core-manifest"
local refs_mf="$VAULT_DIR/.claude/references/.core-manifest"
local _fw_dir="${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}"
local agents_mf="$_fw_dir/agents/.core-manifest"
local refs_mf="$_fw_dir/references/.core-manifest"
[[ -f "$agents_mf" ]] || [[ -f "$refs_mf" ]] || return 0
warn "Migrating legacy manifests to unified .mbifc-manifest..."
@@ -247,14 +252,14 @@ manifest_migrate() {
rm "$refs_mf"
fi
success "Manifest migrated to .claude/.mbifc-manifest"
success "Manifest migrated to $(basename "$_fw_dir")/.mbifc-manifest"
}
# ── Deprecation ───────────────────────────────────────────────────────────────
# deprecate_removed <section> <src_dir> <dst_dir>
# Moves files listed in the manifest for <section> that no longer exist in
# <src_dir> to $VAULT_DIR/.claude/deprecated/, prepending a DEPRECATED header.
# <src_dir> to $FRAMEWORK_VAULT_DIR/deprecated/, prepending a DEPRECATED header.
# Prints the count of deprecated files to stdout.
deprecate_removed() {
local section="$1" src_dir="$2" dst_dir="$3"
@@ -268,7 +273,7 @@ deprecate_removed() {
[[ "$name" == *"-DEPRECATED"* ]] && continue # already deprecated
local dep_name="${name%.md}-DEPRECATED.md"
local dep_dir="$VAULT_DIR/.claude/deprecated"
local dep_dir="${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}/deprecated"
mkdir -p "$dep_dir"
[[ -f "$dep_dir/$dep_name" ]] && continue # already done in a prior run
@@ -279,7 +284,7 @@ deprecate_removed() {
mv "$dep_dir/$dep_name.tmp" "$dep_dir/$dep_name"
manifest_remove "$section" "$name"
warn "Deprecated: $name.claude/deprecated/$dep_name"
warn "Deprecated: $name$(basename "${FRAMEWORK_VAULT_DIR:-$VAULT_DIR/.claude}")/deprecated/$dep_name"
count=$((count + 1))
done < <(manifest_read "$section")

View File

@@ -46,8 +46,12 @@ esac
|| die "No agents/ found in $VAULT_DIR for framework '$FRAMEWORK' — run launchme.sh first"
# ── Confirm ───────────────────────────────────────────────────────────────────
echo -e "${BOLD}This will update core agents, skills, references, hooks, and CLAUDE.md.${NC}"
echo -e " ${DIM}Custom agents in .claude/agents/ are never overwritten or deleted.${NC}"
case "$FRAMEWORK" in
opencode) _DISP_NAME="AGENTS.md"; _FW_DIR_NAME="opencode" ;;
*) _DISP_NAME="CLAUDE.md"; _FW_DIR_NAME="claude" ;;
esac
echo -e "${BOLD}This will update core agents, skills, references, hooks, and ${_DISP_NAME}.${NC}"
echo -e " ${DIM}Custom agents in .${_FW_DIR_NAME}/agents/ are never overwritten or deleted.${NC}"
echo -e " ${DIM}Custom content between MBIFC markers in references is preserved.${NC}"
echo -e " ${DIM}Your vault notes are never touched.${NC}"
echo ""
@@ -89,6 +93,7 @@ case "$FRAMEWORK" in
die "Unknown framework: $FRAMEWORK (install layout not defined)"
;;
esac
FRAMEWORK_VAULT_DIR="$VAULT_COMPONENTS_DIR"
# ── Migrate legacy manifests (if any) ────────────────────────────────────────
manifest_migrate

View File

@@ -205,3 +205,36 @@ test_enumerate_hooks() {
rm -rf "$dir"
[[ "$count" == "2" ]] || { echo "expected 2, got $count"; return 1; }
}
test_rewrite_framework_paths_opencode() {
local file; file="$(mktemp)"
printf 'See .claude/agents/ and .claude/references/foo.md\nAlso CLAUDE.md here.\n' > "$file"
rewrite_framework_paths "$file" "opencode" "AGENTS.md"
local result; result="$(cat "$file")"
rm "$file"
[[ "$result" == *".opencode/agents/"* ]] || { echo "agents/ not rewritten: $result"; return 1; }
[[ "$result" == *".opencode/references/"* ]] || { echo "references/ not rewritten: $result"; return 1; }
[[ "$result" == *"AGENTS.md"* ]] || { echo "AGENTS.md not present: $result"; return 1; }
[[ "$result" != *".claude/"* ]] || { echo ".claude/ still present: $result"; return 1; }
[[ "$result" != *"CLAUDE.md"* ]] || { echo "CLAUDE.md still present: $result"; return 1; }
}
test_rewrite_framework_paths_noop_for_claude_code() {
local file; file="$(mktemp)"
local content='.claude/agents/ and CLAUDE.md'
printf '%s\n' "$content" > "$file"
rewrite_framework_paths "$file" "claude" "CLAUDE.md"
local result; result="$(cat "$file")"
rm "$file"
[[ "$result" == "$content" ]] || { echo "content was changed unexpectedly: $result"; return 1; }
}
test_rewrite_framework_paths_preserves_product_name() {
local file; file="$(mktemp)"
printf 'Claude Code auto-loads agents from .claude/agents/\n' > "$file"
rewrite_framework_paths "$file" "opencode" "AGENTS.md"
local result; result="$(cat "$file")"
rm "$file"
[[ "$result" == *"Claude Code auto-loads"* ]] || { echo "product name was altered: $result"; return 1; }
[[ "$result" == *".opencode/agents/"* ]] || { echo "path not rewritten: $result"; return 1; }
}

View File

@@ -9,13 +9,17 @@ test_oc_translate_dispatcher_renames_to_agents_md() {
local dst; dst="$(mktemp -d)"
cat > "$src/DISPATCHER.md" <<'EOF'
# Dispatcher
Some content
See .claude/agents/ for agents. Consult CLAUDE.md for rules.
EOF
adapter_translate_dispatcher "$src/DISPATCHER.md" "$dst"
local result=0
[[ -f "$dst/AGENTS.md" ]] || { echo "AGENTS.md not created"; result=1; }
[[ -f "$dst/AGENTS.md" ]] || { echo "AGENTS.md not created"; result=1; }
[[ ! -f "$dst/CLAUDE.md" ]] || { echo "CLAUDE.md should not exist"; result=1; }
[[ "$(cat "$dst/AGENTS.md")" == "$(cat "$src/DISPATCHER.md")" ]] || { echo "content mismatch"; result=1; }
local content; content="$(cat "$dst/AGENTS.md")"
[[ "$content" == *".opencode/agents/"* ]] || { echo ".opencode/agents/ not found: $content"; result=1; }
[[ "$content" == *"AGENTS.md"* ]] || { echo "AGENTS.md ref not rewritten: $content"; result=1; }
[[ "$content" != *".claude/"* ]] || { echo ".claude/ still present: $content"; result=1; }
[[ "$content" != *"CLAUDE.md"* ]] || { echo "CLAUDE.md still present: $content"; result=1; }
rm -rf "$src" "$dst"
return $result
}
@@ -34,6 +38,21 @@ test_oc_translate_references_copies_md_files() {
return $result
}
test_oc_translate_references_rewrites_paths() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"
mkdir -p "$src/references"
printf 'See .claude/agents/ and CLAUDE.md for details.\n' > "$src/references/guide.md"
adapter_translate_references "$src/references" "$dst"
local content; content="$(cat "$dst/.opencode/references/guide.md")"
local result=0
[[ "$content" == *".opencode/agents/"* ]] || { echo ".opencode/agents/ not found: $content"; result=1; }
[[ "$content" == *"AGENTS.md"* ]] || { echo "AGENTS.md not found: $content"; result=1; }
[[ "$content" != *".claude/"* ]] || { echo ".claude/ still present: $content"; result=1; }
rm -rf "$src" "$dst"
return $result
}
test_oc_translate_skills_copies_skill_md() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"
@@ -60,6 +79,27 @@ SKILLEOF
return $result
}
test_oc_translate_skills_rewrites_paths() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"
mkdir -p "$src/skills/create-agent"
cat > "$src/skills/create-agent/SKILL.md" <<'SKILLEOF'
---
name: create-agent
description: Create a new agent
---
Save to .claude/agents/ and update CLAUDE.md.
SKILLEOF
adapter_translate_skills "$src/skills" "$dst"
local content; content="$(cat "$dst/.opencode/skills/create-agent/SKILL.md")"
local result=0
[[ "$content" == *".opencode/agents/"* ]] || { echo ".opencode/agents/ not found: $content"; result=1; }
[[ "$content" == *"AGENTS.md"* ]] || { echo "AGENTS.md not found: $content"; result=1; }
[[ "$content" != *".claude/"* ]] || { echo ".claude/ still present: $content"; result=1; }
rm -rf "$src" "$dst"
return $result
}
test_oc_translate_skills_honors_exclude() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"
@@ -97,7 +137,7 @@ EOF
local out="$dst/.opencode/agents/scribe.md"
local result=0
[[ -f "$out" ]] || { echo "agent file missing"; result=1; }
grep -q '^description: "Test scribe"' "$out" || { echo "description missing or wrong quoting"; cat "$out"; result=1; }
grep -q '^description: Test scribe' "$out" || { echo "description missing or wrong format"; cat "$out"; result=1; }
grep -q '^mode: subagent' "$out" || { echo "mode missing"; result=1; }
grep -q '^model: anthropic/claude-sonnet-4-5' "$out" || { echo "model not mapped"; result=1; }
grep -q '^permission:' "$out" || { echo "permission block missing"; result=1; }
@@ -109,6 +149,31 @@ EOF
return $result
}
test_oc_translate_agents_rewrites_body_paths() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"
mkdir -p "$src/agents"
cat > "$src/agents/scribe.md" <<'EOF'
---
name: scribe
description: Test scribe
model: sonnet
capabilities: [read, write]
---
See .claude/references/agents.md and CLAUDE.md for context.
EOF
adapter_translate_agents "$src/agents" "$dst"
local out="$dst/.opencode/agents/scribe.md"
local result=0
local content; content="$(cat "$out")"
[[ "$content" == *".opencode/references/agents.md"* ]] || { echo ".opencode/references/ not found: $content"; result=1; }
[[ "$content" == *"AGENTS.md"* ]] || { echo "AGENTS.md not found: $content"; result=1; }
[[ "$content" != *".claude/"* ]] || { echo ".claude/ still present: $content"; result=1; }
rm -rf "$src" "$dst"
return $result
}
test_oc_translate_agents_bash_capability() {
local src; src="$(mktemp -d)"
local dst; dst="$(mktemp -d)"

View File

@@ -1,36 +0,0 @@
[agents]
[hooks]
[references]
[skills]
agent-orchestration.md
agent-template.md
agents-registry.md
agents.md
architect.md
connector.md
create-agent
deadline-radar
deep-clean
defrag
email-triage
inbox-triage
librarian.md
manage-agent
meeting-prep
notify.sh
onboarding
postman.md
protect-system-files.sh
scribe.md
seeker.md
sorter.md
tag-garden
transcribe
transcriber.md
validate-frontmatter.sh
vault-audit
weekly-agenda

View File

@@ -17,7 +17,7 @@ description: >
JA: "新しいプロジェクト".
Also trigger when a new topic/project/area emerges that needs a home, or when
another agent reports a missing structure.
tools: Read, Write, Edit, Bash, Glob, Grep
tools: Read, Glob, Grep, Write, Edit, Bash
model: opus
---

View File

@@ -14,7 +14,7 @@ description: >
"verbinde die Notizen", "finde Verbindungen", "Graphanalyse", "fehlende Links",
"conecta as notas", "encontra conexões", "análise do grafo", "links em falta",
or after a large batch of notes has been filed and needs cross-linking.
tools: Read, Edit, Glob, Grep
tools: Read, Glob, Grep, Edit
model: sonnet
---

View File

@@ -15,7 +15,7 @@ description: >
"wöchentliche Überprüfung", "Vault prüfen", "Wartung", "Vault aufräumen",
"revisão semanal", "verifica o vault", "manutenção", "limpeza do vault",
or when the user suspects broken links, misplaced files, or structural problems.
tools: Read, Write, Edit, Bash, Glob, Grep
tools: Read, Glob, Grep, Write, Edit, Bash
model: opus
---

View File

@@ -25,7 +25,7 @@ description: >
PT: "verificar meus emails", "o que tem na caixa de entrada", "importar eventos",
"criar evento", "o que tem no calendário", "triagem de email",
"preparar a reunião", "agenda semanal", "rascunho de resposta".
tools: Read, Write, Edit, Bash, Glob, Grep
tools: Read, Glob, Grep, Write, Edit, Bash
model: sonnet
---

View File

@@ -12,7 +12,7 @@ description: >
"salva isso", "nota rápida", "escreve isso", "lembra-me que",
or when the user pastes messy, unformatted text, speech-to-text output, or a chain
of related thoughts that need to be turned into proper notes.
tools: Read, Write, Edit, Glob, Grep
tools: Read, Glob, Grep, Write, Edit
model: sonnet
---

View File

@@ -10,7 +10,7 @@ description: >
"sortiere den Eingang", "Notizen sortieren",
"organiza a caixa de entrada", "triagem",
or when the Inbox has accumulated notes that need filing.
tools: Read, Write, Edit, Bash, Glob, Grep
tools: Read, Glob, Grep, Write, Edit, Bash
model: sonnet
---

View File

@@ -17,7 +17,7 @@ description: >
PT: "transcrever", "notas de reunião", "resumo do podcast", "notas de aula",
"diário de voz", "resumo da chamada".
Also triggers when the user uploads an audio file (mp3, m4a, wav) or pastes a raw transcript.
tools: Read, Write, Glob, Grep
tools: Read, Glob, Grep, Write
model: sonnet
---

View File

@@ -0,0 +1,12 @@
{
"mcpServers": {
"Gmail": {
"type": "http",
"url": "https://gmail.mcp.claude.com/mcp"
},
"Google Calendar": {
"type": "http",
"url": "https://gcal.mcp.claude.com/mcp"
}
}
}

View File

@@ -12,7 +12,7 @@ PASS=0
FAIL=0
FAILED_TESTS=()
for test_file in $(find "$SCRIPT_DIR" -name '*.test.sh' | sort); do
while IFS= read -r test_file; do
echo "── $(basename "$test_file") ──────────────────────"
# Source the test file to get its functions
source "$test_file"
@@ -28,7 +28,7 @@ for test_file in $(find "$SCRIPT_DIR" -name '*.test.sh' | sort); do
fi
unset -f "$fn"
done
done
done < <(find "$SCRIPT_DIR" -name '*.test.sh' | sort)
echo ""
echo "==========================="