質問例: miyabi-gni-ask "このリポの構造を教えて" miyabi-gni-ask "protocol.rs は何に依存してる?" miyabi-gni-ask "テストはいくつある?" miyabi-gni-ask "ロックの状態を教えて" miyabi-gni-ask "gate.rs の関数一覧" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
218 lines
8.4 KiB
Bash
Executable file
218 lines
8.4 KiB
Bash
Executable file
#!/bin/bash
|
||
# miyabi gni ask — 自然言語で GNI に質問して自然言語で返す
|
||
#
|
||
# Usage:
|
||
# miyabi gni ask "このリポの構造を教えて"
|
||
# miyabi gni ask "protocol.rs の依存関係は?"
|
||
# miyabi gni ask "テストはいくつある?"
|
||
|
||
set -euo pipefail
|
||
|
||
REPO="miyabi-cli-standalone"
|
||
QUESTION="${1:-}"
|
||
|
||
if [ -z "$QUESTION" ]; then
|
||
echo "使い方: miyabi gni ask \"質問\""
|
||
echo ""
|
||
echo "例:"
|
||
echo " miyabi gni ask \"このリポの構造を教えて\""
|
||
echo " miyabi gni ask \"protocol.rs は何に依存してる?\""
|
||
echo " miyabi gni ask \"DTP の関数一覧\""
|
||
echo " miyabi gni ask \"ロック関連のフロー\""
|
||
echo " miyabi gni ask \"一番大きいクラスターは?\""
|
||
exit 0
|
||
fi
|
||
|
||
Q=$(echo "$QUESTION" | tr '[:upper:]' '[:lower:]')
|
||
|
||
# キーワードで分類して適切なクエリを実行
|
||
if echo "$Q" | grep -qE "構造|概要|全体|overview"; then
|
||
echo "このリポジトリの概要です。"
|
||
echo ""
|
||
npx gitnexus status 2>/dev/null
|
||
echo ""
|
||
echo "主要なクラスター(機能領域):"
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (c:Community) WHERE c.symbolCount > 15 RETURN c.label AS name, c.symbolCount AS size ORDER BY size DESC LIMIT 10" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
for row in data.get('rows',json.loads(data.get('markdown','[]').replace('|','\t').strip()) if 'markdown' in data else []):
|
||
pass
|
||
# fallback: parse markdown table
|
||
import re
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
print(f' {cols[0]}: {cols[1]}シンボル')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "依存|depend|使って|呼んで|import"; then
|
||
# ファイル名を抽出
|
||
FILE=$(echo "$QUESTION" | grep -oE '[a-z_]+\.rs' | head -1)
|
||
if [ -z "$FILE" ]; then
|
||
echo "どのファイルの依存関係を見ますか?ファイル名を含めて質問してください。"
|
||
exit 1
|
||
fi
|
||
echo "${FILE} が依存しているモジュール:"
|
||
echo ""
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (caller:Function)-[r]->(callee:Function) WHERE caller.filePath CONTAINS '$FILE' AND NOT callee.filePath CONTAINS '$FILE' RETURN DISTINCT callee.filePath AS module, count(*) AS calls ORDER BY calls DESC LIMIT 10" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
print(f' → {cols[0]} ({cols[1]}箇所から呼び出し)')
|
||
else:
|
||
print(' 依存関係が見つかりませんでした。')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "関数|function|一覧|list|api"; then
|
||
FILE=$(echo "$QUESTION" | grep -oE '[a-z_]+\.rs' | head -1)
|
||
FILTER=""
|
||
if [ -n "$FILE" ]; then
|
||
FILTER="WHERE f.filePath CONTAINS '$FILE'"
|
||
echo "${FILE} の関数一覧:"
|
||
else
|
||
FILTER="WHERE f.filePath CONTAINS 'gate.rs' OR f.filePath CONTAINS 'lock.rs' OR f.filePath CONTAINS 'store.rs' OR f.filePath CONTAINS 'protocol.rs'"
|
||
echo "DTP モジュールの関数一覧:"
|
||
fi
|
||
echo ""
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (f:Function) $FILTER RETURN f.name AS name, f.filePath AS file ORDER BY f.filePath, f.name LIMIT 30" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
current_file = ''
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
f = cols[1].split('/')[-1]
|
||
if f != current_file:
|
||
current_file = f
|
||
print(f'\n [{f}]')
|
||
print(f' {cols[0]}()')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "フロー|flow|実行|process|パス"; then
|
||
KEYWORD=$(echo "$QUESTION" | grep -oE '[A-Za-z_]+' | head -1)
|
||
echo "実行フロー(${KEYWORD:-全体}):"
|
||
echo ""
|
||
if [ -n "$KEYWORD" ]; then
|
||
FILTER="WHERE p.label CONTAINS '$KEYWORD'"
|
||
else
|
||
FILTER=""
|
||
fi
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (p:Process) $FILTER RETURN p.label AS flow, p.stepCount AS steps ORDER BY p.stepCount DESC LIMIT 10" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
print(f' {cols[0]} ({cols[1]}ステップ)')
|
||
else:
|
||
print(' 該当するフローが見つかりませんでした。')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "クラスター|cluster|領域|area|モジュール"; then
|
||
echo "機能クラスター(シンボル数順):"
|
||
echo ""
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (c:Community) WHERE c.symbolCount > 5 RETURN c.label AS name, c.symbolCount AS size ORDER BY size DESC LIMIT 15" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for i,line in enumerate(lines[1:],1):
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
bar = '█' * min(int(int(cols[1])/3), 20)
|
||
print(f' {i:2d}. {cols[0]:30s} {cols[1]:>3s} {bar}')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "テスト|test|カバレッジ|coverage"; then
|
||
echo "テスト状況:"
|
||
echo ""
|
||
cargo test --all 2>&1 | grep "test result" | while read line; do
|
||
echo " $line"
|
||
done
|
||
echo ""
|
||
echo "DTP モジュール別テスト数:"
|
||
for f in gate.rs lock.rs store.rs protocol.rs; do
|
||
count=$(grep -c "#\[test\]" crates/miyabi-core/src/$f 2>/dev/null || echo "0")
|
||
echo " $f: ${count}件"
|
||
done
|
||
|
||
elif echo "$Q" | grep -qE "ロック|lock|競合|conflict"; then
|
||
echo "現在のファイルロック状態:"
|
||
echo ""
|
||
target/release/miyabi gate locks 2>/dev/null || echo " (miyabi バイナリが見つかりません)"
|
||
echo ""
|
||
echo "ロック関連の実行フロー:"
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (p:Process) WHERE p.label CONTAINS 'Lock' OR p.label CONTAINS 'lock' OR p.label CONTAINS 'Acquire' OR p.label CONTAINS 'Release' RETURN p.label AS flow, p.stepCount AS steps ORDER BY p.stepCount DESC LIMIT 5" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if len(cols)>=2:
|
||
print(f' {cols[0]} ({cols[1]}ステップ)')
|
||
" 2>/dev/null
|
||
|
||
elif echo "$Q" | grep -qE "ファイル|file|探|search|どこ"; then
|
||
KEYWORD=$(echo "$QUESTION" | grep -oE '[a-zA-Z_.-]+\.[a-z]+' | head -1)
|
||
if [ -z "$KEYWORD" ]; then
|
||
KEYWORD=$(echo "$QUESTION" | sed 's/.*[「」]\(.*\)[「」].*/\1/' | head -1)
|
||
fi
|
||
echo "「${KEYWORD}」を含むファイル:"
|
||
echo ""
|
||
npx gitnexus cypher --repo $REPO \
|
||
"MATCH (f:File) WHERE f.filePath CONTAINS '$KEYWORD' RETURN f.filePath ORDER BY f.filePath LIMIT 20" 2>/dev/null \
|
||
| python3 -c "
|
||
import sys,json
|
||
data=json.loads(sys.stdin.read())
|
||
md = data.get('markdown','')
|
||
lines = [l.strip() for l in md.split('\n') if l.strip() and not l.strip().startswith('---')]
|
||
if len(lines)>1:
|
||
for line in lines[1:]:
|
||
cols = [c.strip() for c in line.split('|') if c.strip()]
|
||
if cols:
|
||
print(f' {cols[0]}')
|
||
else:
|
||
print(' 見つかりませんでした。')
|
||
" 2>/dev/null
|
||
|
||
else
|
||
echo "すみません、質問の意図を特定できませんでした。"
|
||
echo ""
|
||
echo "以下のような質問ができます:"
|
||
echo " 「このリポの構造を教えて」"
|
||
echo " 「protocol.rs は何に依存してる?」"
|
||
echo " 「DTP の関数一覧」"
|
||
echo " 「ロック関連のフロー」"
|
||
echo " 「一番大きいクラスターは?」"
|
||
echo " 「テストはいくつある?」"
|
||
echo " 「gate.rs を探して」"
|
||
fi
|