Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ ID=$(scripts/agy-job.sh start --tier pro --dir . "big task"); scripts/agy-job.sh

| tier | model | use for |
|------|-------|---------|
| `flash` (default) | Gemini 3.5 Flash (High) | most bulk work |
| `flash-lo` | Gemini 3.5 Flash (Low) | cheapest, trivial tasks |
| `flash` (default) | Gemini 3.6 Flash (High) | most bulk work |
| `flash-lo` | Gemini 3.6 Flash (Low) | cheapest, trivial tasks |
| `pro` | Gemini 3.1 Pro (High) | harder reasoning / cross-checks |

**agy is multi-model.** Tiers default to Gemini, but you can use any model `agy models` lists
Expand Down
2 changes: 1 addition & 1 deletion agents/antigravity-delegate.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ hooks:
- matcher: Bash
hooks:
- type: command
command: "\"${CLAUDE_PLUGIN_ROOT}/hooks/validate-delegate-bash.sh\""
command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/validate-delegate-bash.js\""
model: inherit
color: blue
---
Expand Down
32 changes: 32 additions & 0 deletions bin/agy-cost-compare.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\agy-cost-compare.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
32 changes: 32 additions & 0 deletions bin/agy-delegate.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\agy-delegate.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
32 changes: 32 additions & 0 deletions bin/agy-doctor.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\doctor.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
32 changes: 32 additions & 0 deletions bin/agy-job.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\agy-job.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
32 changes: 32 additions & 0 deletions bin/agy-trace.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\agy-trace.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
32 changes: 32 additions & 0 deletions bin/cloud-debug.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@echo off
setlocal
set "SCRIPT_DIR=%~dp0"
set "TARGET_SCRIPT=%SCRIPT_DIR%..\scripts\cloud-debug.sh"

where bash >nul 2>&1
if %ERRORLEVEL% equ 0 (
bash "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

where sh >nul 2>&1
if %ERRORLEVEL% equ 0 (
sh "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

if exist "%ProgramFiles%\Git\bin\bash.exe" (
"%ProgramFiles%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%ProgramFiles(x86)%\Git\bin\bash.exe" (
"%ProgramFiles(x86)%\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)
if exist "%LocalAppData%\Programs\Git\bin\bash.exe" (
"%LocalAppData%\Programs\Git\bin\bash.exe" "%TARGET_SCRIPT%" %*
exit /b %ERRORLEVEL%
)

echo error: bash or sh is required to run this command, but neither was found on PATH or in standard Git installation paths. >&2
exit /b 1
23 changes: 23 additions & 0 deletions hooks/check-agy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const { execSync } = require('child_process');

let hasAgy = false;
try {
const checkCmd = process.platform === 'win32' ? 'where agy' : 'which agy';
execSync(checkCmd, { stdio: 'ignore' });
hasAgy = true;
} catch (e) {
hasAgy = false;
}

if (!hasAgy) {
console.error("[antigravity] agy not on PATH — install the Antigravity CLI to enable delegation:");
console.error("[antigravity] https://antigravity.google/docs/cli-using");
process.exit(0);
}

try {
execSync('agy --version', { shell: true, stdio: 'ignore', timeout: 5000 });
} catch (e) {
console.error("[antigravity] agy is on PATH but '--version' failed — it may need authentication (run `agy` once).");
}
process.exit(0);
17 changes: 17 additions & 0 deletions hooks/inject-policy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const fs = require('fs');
const path = require('path');

const codingPolicy = (process.env.CLAUDE_PLUGIN_OPTION_CODING_POLICY || 'on').toLowerCase().trim();
if (['off', 'false', '0', 'no', 'disabled'].includes(codingPolicy)) {
process.exit(0);
}

try {
const policyPath = path.join(__dirname, 'policy-context.json');
const policy = fs.readFileSync(policyPath, 'utf8');
process.stdout.write(policy);
} catch (e) {
console.error("Error reading policy-context.json:", e);
process.exit(1);
}
process.exit(0);
54 changes: 54 additions & 0 deletions hooks/nudge-delegation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const fs = require('fs');

const nudge = (process.env.CLAUDE_PLUGIN_OPTION_DELEGATION_NUDGE || 'on').toLowerCase().trim();
if (['off', 'false', '0', 'no', 'disabled'].includes(nudge)) {
process.exit(0);
}

let input = '';
try {
input = fs.readFileSync(0, 'utf8');
} catch (e) {
process.exit(0);
}

if (!input) {
process.exit(0);
}

let prompt = '';
try {
const data = JSON.parse(input);
prompt = data.prompt || '';
} catch (e) {
process.exit(0);
}

if (!prompt) {
process.exit(0);
}

if (/antigravity|agy-delegate|agy-job/i.test(prompt)) {
process.exit(0);
}

const keywords = [
"all files", "every file", "across the codebase", "entire codebase", "whole repo",
"migrate", "migration", "generate tests", "test coverage", "exhaustive test",
"scaffold", "boilerplate", "deep research", "web search",
"一括", "全ファイル", "すべてのファイル", "網羅", "移行", "大量", "横断", "リポジトリ全体"
];

const promptLower = prompt.toLowerCase();
const hit = keywords.some(kw => promptLower.includes(kw.toLowerCase()));

if (hit) {
const output = {
hookSpecificOutput: {
hookEventName: "UserPromptSubmit",
additionalContext: "[antigravity plugin] This prompt looks like BULK work (mass edits / migration / exhaustive tests / fan-out search) — possibly above the delegation break-even. CONSIDER routing the bulk part to the antigravity-delegate subagent (or agy-delegate --digest) so it runs on the cheap executor, then verify its digest. THE JUDGMENT IS YOURS: if the task is actually small, self-contained, or judgement-heavy, do it yourself — delegating below the break-even is a measured net loss. Decide silently; don't mention this notice."
}
};
console.log(JSON.stringify(output));
}
process.exit(0);
6 changes: 5 additions & 1 deletion hooks/nudge-delegation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ IN="$(cat 2>/dev/null || true)"

# Extract ONLY the prompt field (matching on the whole payload would false-positive
# on cwd/paths). python3 is already a plugin dependency (measure-session, agy-trace).
PROMPT="$(printf '%s' "$IN" | python3 -c 'import json,sys
py_cmd="python3"
if ! command -v python3 >/dev/null 2>&1 && command -v python >/dev/null 2>&1; then
py_cmd="python"
fi
PROMPT="$(printf '%s' "$IN" | "$py_cmd" -c 'import json,sys
try: print(json.load(sys.stdin).get("prompt",""))
except Exception: pass' 2>/dev/null || true)"
[ -n "$PROMPT" ] || exit 0
Expand Down
23 changes: 23 additions & 0 deletions hooks/validate-delegate-bash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const fs = require('fs');

let input = '';
try {
input = fs.readFileSync(0, 'utf8');
} catch (e) {
process.exit(2);
}

let cmd = input;
try {
const data = JSON.parse(input);
cmd = data.tool_input?.command || '';
} catch (e) {
// If parsing fails, fall back to matching on raw input string
}

if (/agy-delegate|agy-job/.test(cmd)) {
process.exit(0);
}

console.error("[antigravity-delegate] blocked: this subagent may only run agy-delegate / agy-job via Bash. Delegate file work to agy; verification is the caller's job.");
process.exit(2);
13 changes: 9 additions & 4 deletions hooks/validate-delegate-bash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ set -uo pipefail

input="$(cat)"

# Extract the command field. Prefer python3 (correct JSON parse); fall back to the
# raw payload so the gate still works if python3 is unavailable.
if command -v python3 >/dev/null 2>&1; then
cmd="$(printf '%s' "$input" | python3 -c \
# Extract the command field. Prefer python3/python (correct JSON parse); fall back to the
# raw payload so the gate still works if python is unavailable.
py_cmd="python3"
if ! command -v python3 >/dev/null 2>&1 && command -v python >/dev/null 2>&1; then
py_cmd="python"
fi

if command -v "$py_cmd" >/dev/null 2>&1; then
cmd="$(printf '%s' "$input" | "$py_cmd" -c \
'import json,sys
try:
print(json.load(sys.stdin).get("tool_input",{}).get("command",""))
Expand Down
9 changes: 7 additions & 2 deletions scripts/agy-cost-compare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ PROMPT="${*:-}"

# Default prices from prices.json (env vars still override); Gemini rate by tier.
PRICES="$HERE/../prices.json"
if [ -f "$PRICES" ] && command -v python3 >/dev/null 2>&1; then
eval "$(python3 - "$PRICES" "$TIER" 2>/dev/null <<'PY'
PYTHON_CMD=""
if command -v python3 >/dev/null 2>&1; then PYTHON_CMD=python3;
elif command -v python >/dev/null 2>&1; then PYTHON_CMD=python;
fi

if [ -f "$PRICES" ] && [ -n "$PYTHON_CMD" ]; then
eval "$("$PYTHON_CMD" - "$PRICES" "$TIER" 2>/dev/null <<'PY'
import json,sys
try:
d=json.load(open(sys.argv[1])); t=sys.argv[2]
Expand Down
4 changes: 2 additions & 2 deletions scripts/agy-delegate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ usage() { sed -n '/^# Usage:/,/^# Exit codes:/p' "$0" | sed 's/^# \{0,1\}//'; ex
# (env), so non-Vertex/non-Gemini plans (Claude/GPT) work without code changes.
model_for_tier() {
case "$1" in
flash) echo "${CLAUDE_PLUGIN_OPTION_TIER_FLASH:-Gemini 3.5 Flash (High)}" ;;
flash-lo) echo "${CLAUDE_PLUGIN_OPTION_TIER_FLASH_LO:-Gemini 3.5 Flash (Low)}" ;;
flash) echo "${CLAUDE_PLUGIN_OPTION_TIER_FLASH:-Gemini 3.6 Flash (High)}" ;;
flash-lo) echo "${CLAUDE_PLUGIN_OPTION_TIER_FLASH_LO:-Gemini 3.6 Flash (Low)}" ;;
pro) echo "${CLAUDE_PLUGIN_OPTION_TIER_PRO:-Gemini 3.1 Pro (High)}" ;;
*) die "unknown tier '$1' (use flash | flash-lo | pro)" ;;
esac
Expand Down
Loading
Loading