garc-gws-agent-runtime/lib/kg.sh
林 駿甫 (Shunsuke Hayashi) a69b9d9160 feat: initial release — GARC v0.1.0
Permission-first AI agent runtime for Google Workspace.
Ports the LARC/OpenClaw governance model (disclosure chain,
execution gates, queue/ingress) to Gmail, Calendar, Drive,
Sheets, Tasks, and People APIs with Claude Code as the
execution engine.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 08:59:12 +09:00

123 lines
3 KiB
Bash

#!/usr/bin/env bash
# GARC kg.sh — Knowledge graph via Google Docs
# Google Docs replaces Lark Wiki as the knowledge graph surface
GARC_KG_CACHE="${GARC_CACHE_DIR:-${HOME}/.garc/cache}/knowledge-graph.json"
garc_kg() {
local subcommand="${1:-help}"
shift || true
case "${subcommand}" in
build) garc_kg_build "$@" ;;
query) garc_kg_query "$@" ;;
show) garc_kg_show "$@" ;;
*)
echo "Usage: garc kg <build|query|show>"
return 1
;;
esac
}
# garc kg build
# Crawls Google Drive folder and builds knowledge graph from Docs
garc_kg_build() {
local folder_id="${GARC_DRIVE_FOLDER_ID:-}"
if [[ -z "${folder_id}" ]]; then
echo "Error: GARC_DRIVE_FOLDER_ID not set" >&2
return 1
fi
echo "Building knowledge graph from Google Drive folder: ${folder_id}"
python3 "${GARC_DIR}/scripts/garc-drive-helper.py" kg-build \
--folder-id "${folder_id}" \
--output "${GARC_KG_CACHE}"
echo "✅ Knowledge graph built: ${GARC_KG_CACHE}"
}
# garc kg query "<concept>"
garc_kg_query() {
local query="$*"
if [[ -z "${query}" ]]; then
echo "Usage: garc kg query \"<concept>\""
return 1
fi
if [[ ! -f "${GARC_KG_CACHE}" ]]; then
echo "Knowledge graph not built. Run: garc kg build"
return 1
fi
python3 -c "
import json, sys
query = '${query}'.lower()
with open('${GARC_KG_CACHE}') as f:
kg = json.load(f)
matches = []
for node in kg.get('nodes', []):
name = node.get('title', '').lower()
content = node.get('content_preview', '').lower()
if query in name or query in content:
matches.append(node)
if not matches:
print(f'No results for: ${query}')
sys.exit(0)
print(f'Results for \"{query}\" ({len(matches)} matches):')
for m in matches[:10]:
print(f' - [{m.get(\"doc_id\",\"\")}] {m.get(\"title\",\"\")}')
if m.get('content_preview'):
preview = m['content_preview'][:100].replace('\n', ' ')
print(f' {preview}...')
links = m.get('links', [])
if links:
print(f' Links: {len(links)} documents')
"
}
# garc kg show <doc_id>
garc_kg_show() {
local doc_id="${1:-}"
if [[ -z "${doc_id}" ]]; then
echo "Usage: garc kg show <doc_id>"
return 1
fi
if [[ ! -f "${GARC_KG_CACHE}" ]]; then
echo "Knowledge graph not built. Run: garc kg build"
return 1
fi
python3 -c "
import json
doc_id = '${doc_id}'
with open('${GARC_KG_CACHE}') as f:
kg = json.load(f)
for node in kg.get('nodes', []):
if node.get('doc_id') == doc_id:
print(f'Title: {node.get(\"title\", \"\")}')
print(f'Doc ID: {doc_id}')
print(f'Type: {node.get(\"mime_type\", \"\")}')
print(f'Modified: {node.get(\"modified_time\", \"\")}')
print()
print('Content preview:')
print(node.get('content_preview', '(none)'))
print()
links = node.get('links', [])
if links:
print(f'Links ({len(links)}):')
for link in links:
print(f' -> {link}')
break
else:
print(f'Document {doc_id} not found in knowledge graph')
"
}