mirror of
https://github.com/github/spec-kit.git
synced 2026-03-16 18:33:07 +00:00
Pavel/add tabnine cli support (#1503)
* feat: add Tabnine CLI agent support Tabnine CLI is a Gemini fork that uses TOML commands with the .tabnine/agent/ directory structure and TABNINE.md context files. Changes: - Add 'tabnine' to AGENT_CONFIG in __init__.py - Update release scripts (bash + PowerShell) for TOML command generation - Update agent context scripts (bash + PowerShell) - Add to GitHub release packages - Update README.md and AGENTS.md documentation - Bump version to 0.1.14 - Add 8 new tests for cross-file consistency * fix: add missing generic to agent-context script usage string
This commit is contained in:
@@ -46,6 +46,8 @@ gh release create "$VERSION" \
|
|||||||
.genreleases/spec-kit-template-amp-ps-"$VERSION".zip \
|
.genreleases/spec-kit-template-amp-ps-"$VERSION".zip \
|
||||||
.genreleases/spec-kit-template-shai-sh-"$VERSION".zip \
|
.genreleases/spec-kit-template-shai-sh-"$VERSION".zip \
|
||||||
.genreleases/spec-kit-template-shai-ps-"$VERSION".zip \
|
.genreleases/spec-kit-template-shai-ps-"$VERSION".zip \
|
||||||
|
.genreleases/spec-kit-template-tabnine-sh-"$VERSION".zip \
|
||||||
|
.genreleases/spec-kit-template-tabnine-ps-"$VERSION".zip \
|
||||||
.genreleases/spec-kit-template-kiro-cli-sh-"$VERSION".zip \
|
.genreleases/spec-kit-template-kiro-cli-sh-"$VERSION".zip \
|
||||||
.genreleases/spec-kit-template-kiro-cli-ps-"$VERSION".zip \
|
.genreleases/spec-kit-template-kiro-cli-ps-"$VERSION".zip \
|
||||||
.genreleases/spec-kit-template-agy-sh-"$VERSION".zip \
|
.genreleases/spec-kit-template-agy-sh-"$VERSION".zip \
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
.PARAMETER Agents
|
.PARAMETER Agents
|
||||||
Comma or space separated subset of agents to build (default: all)
|
Comma or space separated subset of agents to build (default: all)
|
||||||
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, agy, generic
|
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, generic
|
||||||
|
|
||||||
.PARAMETER Scripts
|
.PARAMETER Scripts
|
||||||
Comma or space separated subset of script types to build (default: both)
|
Comma or space separated subset of script types to build (default: both)
|
||||||
@@ -351,6 +351,12 @@ function Build-Variant {
|
|||||||
$cmdDir = Join-Path $baseDir ".shai/commands"
|
$cmdDir = Join-Path $baseDir ".shai/commands"
|
||||||
Generate-Commands -Agent 'shai' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
Generate-Commands -Agent 'shai' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
||||||
}
|
}
|
||||||
|
'tabnine' {
|
||||||
|
$cmdDir = Join-Path $baseDir ".tabnine/agent/commands"
|
||||||
|
Generate-Commands -Agent 'tabnine' -Extension 'toml' -ArgFormat '{{args}}' -OutputDir $cmdDir -ScriptVariant $Script
|
||||||
|
$tabnineTemplate = Join-Path 'agent_templates' 'tabnine/TABNINE.md'
|
||||||
|
if (Test-Path $tabnineTemplate) { Copy-Item $tabnineTemplate (Join-Path $baseDir 'TABNINE.md') }
|
||||||
|
}
|
||||||
'agy' {
|
'agy' {
|
||||||
$cmdDir = Join-Path $baseDir ".agent/workflows"
|
$cmdDir = Join-Path $baseDir ".agent/workflows"
|
||||||
Generate-Commands -Agent 'agy' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
Generate-Commands -Agent 'agy' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
|
||||||
@@ -375,7 +381,7 @@ function Build-Variant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Define all agents and scripts
|
# Define all agents and scripts
|
||||||
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'agy', 'vibe', 'generic')
|
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'generic')
|
||||||
$AllScripts = @('sh', 'ps')
|
$AllScripts = @('sh', 'ps')
|
||||||
|
|
||||||
function Normalize-List {
|
function Normalize-List {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ set -euo pipefail
|
|||||||
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
|
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
|
||||||
# Version argument should include leading 'v'.
|
# Version argument should include leading 'v'.
|
||||||
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
|
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
|
||||||
# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai kiro-cli agy bob qodercli generic (default: all)
|
# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli generic (default: all)
|
||||||
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
|
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
|
||||||
# Examples:
|
# Examples:
|
||||||
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
|
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
|
||||||
@@ -155,7 +155,7 @@ build_variant() {
|
|||||||
|
|
||||||
# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
|
# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
|
||||||
# * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
|
# * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
|
||||||
# * TOML (gemini, qwen): {{args}}
|
# * TOML (gemini, qwen, tabnine): {{args}}
|
||||||
# This keeps formats readable without extra abstraction.
|
# This keeps formats readable without extra abstraction.
|
||||||
|
|
||||||
case $agent in
|
case $agent in
|
||||||
@@ -212,6 +212,10 @@ build_variant() {
|
|||||||
shai)
|
shai)
|
||||||
mkdir -p "$base_dir/.shai/commands"
|
mkdir -p "$base_dir/.shai/commands"
|
||||||
generate_commands shai md "\$ARGUMENTS" "$base_dir/.shai/commands" "$script" ;;
|
generate_commands shai md "\$ARGUMENTS" "$base_dir/.shai/commands" "$script" ;;
|
||||||
|
tabnine)
|
||||||
|
mkdir -p "$base_dir/.tabnine/agent/commands"
|
||||||
|
generate_commands tabnine toml "{{args}}" "$base_dir/.tabnine/agent/commands" "$script"
|
||||||
|
[[ -f agent_templates/tabnine/TABNINE.md ]] && cp agent_templates/tabnine/TABNINE.md "$base_dir/TABNINE.md" ;;
|
||||||
kiro-cli)
|
kiro-cli)
|
||||||
mkdir -p "$base_dir/.kiro/prompts"
|
mkdir -p "$base_dir/.kiro/prompts"
|
||||||
generate_commands kiro-cli md "\$ARGUMENTS" "$base_dir/.kiro/prompts" "$script" ;;
|
generate_commands kiro-cli md "\$ARGUMENTS" "$base_dir/.kiro/prompts" "$script" ;;
|
||||||
@@ -233,7 +237,7 @@ build_variant() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Determine agent list
|
# Determine agent list
|
||||||
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai kiro-cli agy bob vibe qodercli generic)
|
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli generic)
|
||||||
ALL_SCRIPTS=(sh ps)
|
ALL_SCRIPTS=(sh ps)
|
||||||
|
|
||||||
norm_list() {
|
norm_list() {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ Specify supports multiple AI agents by generating agent-specific command files a
|
|||||||
| **Kiro CLI** | `.kiro/prompts/` | Markdown | `kiro-cli` | Kiro CLI |
|
| **Kiro CLI** | `.kiro/prompts/` | Markdown | `kiro-cli` | Kiro CLI |
|
||||||
| **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI |
|
| **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI |
|
||||||
| **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI |
|
| **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI |
|
||||||
|
| **Tabnine CLI** | `.tabnine/agent/commands/` | TOML | `tabnine` | Tabnine CLI |
|
||||||
| **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE |
|
| **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE |
|
||||||
| **Generic** | User-specified via `--ai-commands-dir` | Markdown | N/A | Bring your own agent |
|
| **Generic** | User-specified via `--ai-commands-dir` | Markdown | N/A | Bring your own agent |
|
||||||
|
|
||||||
@@ -322,6 +323,7 @@ Require a command-line tool to be installed:
|
|||||||
- **Qoder CLI**: `qodercli` CLI
|
- **Qoder CLI**: `qodercli` CLI
|
||||||
- **Amp**: `amp` CLI
|
- **Amp**: `amp` CLI
|
||||||
- **SHAI**: `shai` CLI
|
- **SHAI**: `shai` CLI
|
||||||
|
- **Tabnine CLI**: `tabnine` CLI
|
||||||
|
|
||||||
### IDE-Based Agents
|
### IDE-Based Agents
|
||||||
|
|
||||||
@@ -360,7 +362,7 @@ Command content with {SCRIPT} and $ARGUMENTS placeholders.
|
|||||||
|
|
||||||
### TOML Format
|
### TOML Format
|
||||||
|
|
||||||
Used by: Gemini, Qwen
|
Used by: Gemini, Qwen, Tabnine
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
description = "Command description"
|
description = "Command description"
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ Recent changes to the Specify CLI and templates are documented here.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.1.14] - 2026-03-09
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- feat: add Tabnine CLI agent support
|
||||||
|
|
||||||
## [0.1.13] - 2026-03-03
|
## [0.1.13] - 2026-03-03
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ See Spec-Driven Development in action across different scenarios with these comm
|
|||||||
| [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | |
|
| [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | |
|
||||||
| [Roo Code](https://roocode.com/) | ✅ | |
|
| [Roo Code](https://roocode.com/) | ✅ | |
|
||||||
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | |
|
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | |
|
||||||
|
| [Tabnine CLI](https://docs.tabnine.com/main/getting-started/tabnine-cli) | ✅ | |
|
||||||
| [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | ✅ | |
|
| [Mistral Vibe](https://github.com/mistralai/mistral-vibe) | ✅ | |
|
||||||
| [Windsurf](https://windsurf.com/) | ✅ | |
|
| [Windsurf](https://windsurf.com/) | ✅ | |
|
||||||
| [Antigravity (agy)](https://antigravity.google/) | ✅ | |
|
| [Antigravity (agy)](https://antigravity.google/) | ✅ | |
|
||||||
@@ -420,7 +421,7 @@ specify init . --force --ai claude
|
|||||||
specify init --here --force --ai claude
|
specify init --here --force --ai claude
|
||||||
```
|
```
|
||||||
|
|
||||||
The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, or Kiro CLI installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, or Kiro CLI installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
specify init <project_name> --ai claude --ignore-agent-tools
|
specify init <project_name> --ai claude --ignore-agent-tools
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "specify-cli"
|
name = "specify-cli"
|
||||||
version = "0.1.13"
|
version = "0.1.14"
|
||||||
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
|
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -30,12 +30,12 @@
|
|||||||
#
|
#
|
||||||
# 5. Multi-Agent Support
|
# 5. Multi-Agent Support
|
||||||
# - Handles agent-specific file paths and naming conventions
|
# - Handles agent-specific file paths and naming conventions
|
||||||
# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Kiro CLI, Mistral Vibe or Antigravity
|
# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Tabnine CLI, Kiro CLI, Mistral Vibe or Antigravity
|
||||||
# - Can update single agents or all existing agent files
|
# - Can update single agents or all existing agent files
|
||||||
# - Creates default Claude file if no agent files exist
|
# - Creates default Claude file if no agent files exist
|
||||||
#
|
#
|
||||||
# Usage: ./update-agent-context.sh [agent_type]
|
# Usage: ./update-agent-context.sh [agent_type]
|
||||||
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli
|
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|generic
|
||||||
# Leave empty to update all existing agent files
|
# Leave empty to update all existing agent files
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@@ -73,6 +73,7 @@ CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md"
|
|||||||
QODER_FILE="$REPO_ROOT/QODER.md"
|
QODER_FILE="$REPO_ROOT/QODER.md"
|
||||||
AMP_FILE="$REPO_ROOT/AGENTS.md"
|
AMP_FILE="$REPO_ROOT/AGENTS.md"
|
||||||
SHAI_FILE="$REPO_ROOT/SHAI.md"
|
SHAI_FILE="$REPO_ROOT/SHAI.md"
|
||||||
|
TABNINE_FILE="$REPO_ROOT/TABNINE.md"
|
||||||
KIRO_FILE="$REPO_ROOT/AGENTS.md"
|
KIRO_FILE="$REPO_ROOT/AGENTS.md"
|
||||||
AGY_FILE="$REPO_ROOT/.agent/rules/specify-rules.md"
|
AGY_FILE="$REPO_ROOT/.agent/rules/specify-rules.md"
|
||||||
BOB_FILE="$REPO_ROOT/AGENTS.md"
|
BOB_FILE="$REPO_ROOT/AGENTS.md"
|
||||||
@@ -649,6 +650,9 @@ update_specific_agent() {
|
|||||||
shai)
|
shai)
|
||||||
update_agent_file "$SHAI_FILE" "SHAI"
|
update_agent_file "$SHAI_FILE" "SHAI"
|
||||||
;;
|
;;
|
||||||
|
tabnine)
|
||||||
|
update_agent_file "$TABNINE_FILE" "Tabnine CLI"
|
||||||
|
;;
|
||||||
kiro-cli)
|
kiro-cli)
|
||||||
update_agent_file "$KIRO_FILE" "Kiro CLI"
|
update_agent_file "$KIRO_FILE" "Kiro CLI"
|
||||||
;;
|
;;
|
||||||
@@ -666,7 +670,7 @@ update_specific_agent() {
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log_error "Unknown agent type '$agent_type'"
|
log_error "Unknown agent type '$agent_type'"
|
||||||
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|vibe|qodercli|generic"
|
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|generic"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -736,6 +740,11 @@ update_all_existing_agents() {
|
|||||||
found_agent=true
|
found_agent=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$TABNINE_FILE" ]]; then
|
||||||
|
update_agent_file "$TABNINE_FILE" "Tabnine CLI"
|
||||||
|
found_agent=true
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -f "$QODER_FILE" ]]; then
|
if [[ -f "$QODER_FILE" ]]; then
|
||||||
update_agent_file "$QODER_FILE" "Qoder CLI"
|
update_agent_file "$QODER_FILE" "Qoder CLI"
|
||||||
found_agent=true
|
found_agent=true
|
||||||
@@ -783,7 +792,7 @@ print_summary() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli|vibe]"
|
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|generic]"
|
||||||
}
|
}
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Mirrors the behavior of scripts/bash/update-agent-context.sh:
|
|||||||
2. Plan Data Extraction
|
2. Plan Data Extraction
|
||||||
3. Agent File Management (create from template or update existing)
|
3. Agent File Management (create from template or update existing)
|
||||||
4. Content Generation (technology stack, recent changes, timestamp)
|
4. Content Generation (technology stack, recent changes, timestamp)
|
||||||
5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, kiro-cli, agy, bob, qodercli, vibe)
|
5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, tabnine, kiro-cli, agy, bob, vibe, qodercli)
|
||||||
|
|
||||||
.PARAMETER AgentType
|
.PARAMETER AgentType
|
||||||
Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
|
Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
|
||||||
@@ -25,7 +25,7 @@ Relies on common helper functions in common.ps1
|
|||||||
#>
|
#>
|
||||||
param(
|
param(
|
||||||
[Parameter(Position=0)]
|
[Parameter(Position=0)]
|
||||||
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','kiro-cli','agy','bob','qodercli','vibe','generic')]
|
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','tabnine','kiro-cli','agy','bob','qodercli','vibe','generic')]
|
||||||
[string]$AgentType
|
[string]$AgentType
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,6 +58,7 @@ $CODEBUDDY_FILE = Join-Path $REPO_ROOT 'CODEBUDDY.md'
|
|||||||
$QODER_FILE = Join-Path $REPO_ROOT 'QODER.md'
|
$QODER_FILE = Join-Path $REPO_ROOT 'QODER.md'
|
||||||
$AMP_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
$AMP_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
||||||
$SHAI_FILE = Join-Path $REPO_ROOT 'SHAI.md'
|
$SHAI_FILE = Join-Path $REPO_ROOT 'SHAI.md'
|
||||||
|
$TABNINE_FILE = Join-Path $REPO_ROOT 'TABNINE.md'
|
||||||
$KIRO_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
$KIRO_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
||||||
$AGY_FILE = Join-Path $REPO_ROOT '.agent/rules/specify-rules.md'
|
$AGY_FILE = Join-Path $REPO_ROOT '.agent/rules/specify-rules.md'
|
||||||
$BOB_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
$BOB_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
|
||||||
@@ -400,12 +401,13 @@ function Update-SpecificAgent {
|
|||||||
'qodercli' { Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI' }
|
'qodercli' { Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI' }
|
||||||
'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' }
|
'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' }
|
||||||
'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' }
|
'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' }
|
||||||
|
'tabnine' { Update-AgentFile -TargetFile $TABNINE_FILE -AgentName 'Tabnine CLI' }
|
||||||
'kiro-cli' { Update-AgentFile -TargetFile $KIRO_FILE -AgentName 'Kiro CLI' }
|
'kiro-cli' { Update-AgentFile -TargetFile $KIRO_FILE -AgentName 'Kiro CLI' }
|
||||||
'agy' { Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity' }
|
'agy' { Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity' }
|
||||||
'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' }
|
'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' }
|
||||||
'vibe' { Update-AgentFile -TargetFile $VIBE_FILE -AgentName 'Mistral Vibe' }
|
'vibe' { Update-AgentFile -TargetFile $VIBE_FILE -AgentName 'Mistral Vibe' }
|
||||||
'generic' { Write-Info 'Generic agent: no predefined context file. Use the agent-specific update script for your agent.' }
|
'generic' { Write-Info 'Generic agent: no predefined context file. Use the agent-specific update script for your agent.' }
|
||||||
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli|vibe|generic'; return $false }
|
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|generic'; return $false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +427,7 @@ function Update-AllExistingAgents {
|
|||||||
if (Test-Path $CODEBUDDY_FILE) { if (-not (Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI')) { $ok = $false }; $found = $true }
|
if (Test-Path $CODEBUDDY_FILE) { if (-not (Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI')) { $ok = $false }; $found = $true }
|
||||||
if (Test-Path $QODER_FILE) { if (-not (Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI')) { $ok = $false }; $found = $true }
|
if (Test-Path $QODER_FILE) { if (-not (Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI')) { $ok = $false }; $found = $true }
|
||||||
if (Test-Path $SHAI_FILE) { if (-not (Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI')) { $ok = $false }; $found = $true }
|
if (Test-Path $SHAI_FILE) { if (-not (Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI')) { $ok = $false }; $found = $true }
|
||||||
|
if (Test-Path $TABNINE_FILE) { if (-not (Update-AgentFile -TargetFile $TABNINE_FILE -AgentName 'Tabnine CLI')) { $ok = $false }; $found = $true }
|
||||||
if (Test-Path $KIRO_FILE) { if (-not (Update-AgentFile -TargetFile $KIRO_FILE -AgentName 'Kiro CLI')) { $ok = $false }; $found = $true }
|
if (Test-Path $KIRO_FILE) { if (-not (Update-AgentFile -TargetFile $KIRO_FILE -AgentName 'Kiro CLI')) { $ok = $false }; $found = $true }
|
||||||
if (Test-Path $AGY_FILE) { if (-not (Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity')) { $ok = $false }; $found = $true }
|
if (Test-Path $AGY_FILE) { if (-not (Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity')) { $ok = $false }; $found = $true }
|
||||||
if (Test-Path $BOB_FILE) { if (-not (Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob')) { $ok = $false }; $found = $true }
|
if (Test-Path $BOB_FILE) { if (-not (Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob')) { $ok = $false }; $found = $true }
|
||||||
@@ -443,7 +446,7 @@ function Print-Summary {
|
|||||||
if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
|
if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
|
||||||
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
|
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|kiro-cli|agy|bob|qodercli|vibe|generic]'
|
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|generic]'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Main {
|
function Main {
|
||||||
|
|||||||
@@ -237,6 +237,13 @@ AGENT_CONFIG = {
|
|||||||
"install_url": "https://github.com/ovh/shai",
|
"install_url": "https://github.com/ovh/shai",
|
||||||
"requires_cli": True,
|
"requires_cli": True,
|
||||||
},
|
},
|
||||||
|
"tabnine": {
|
||||||
|
"name": "Tabnine CLI",
|
||||||
|
"folder": ".tabnine/agent/",
|
||||||
|
"commands_subdir": "commands",
|
||||||
|
"install_url": "https://docs.tabnine.com/main/getting-started/tabnine-cli",
|
||||||
|
"requires_cli": True,
|
||||||
|
},
|
||||||
"agy": {
|
"agy": {
|
||||||
"name": "Antigravity",
|
"name": "Antigravity",
|
||||||
"folder": ".agent/",
|
"folder": ".agent/",
|
||||||
@@ -1124,7 +1131,7 @@ def install_ai_skills(project_path: Path, selected_ai: str, tracker: StepTracker
|
|||||||
if not templates_dir.exists() or not any(templates_dir.glob("*.md")):
|
if not templates_dir.exists() or not any(templates_dir.glob("*.md")):
|
||||||
# Fallback: try the repo-relative path (for running from source checkout)
|
# Fallback: try the repo-relative path (for running from source checkout)
|
||||||
# This also covers agents whose extracted commands are in a different
|
# This also covers agents whose extracted commands are in a different
|
||||||
# format (e.g. gemini uses .toml, not .md).
|
# format (e.g. gemini/tabnine use .toml, not .md).
|
||||||
script_dir = Path(__file__).parent.parent.parent # up from src/specify_cli/
|
script_dir = Path(__file__).parent.parent.parent # up from src/specify_cli/
|
||||||
fallback_dir = script_dir / "templates" / "commands"
|
fallback_dir = script_dir / "templates" / "commands"
|
||||||
if fallback_dir.exists() and any(fallback_dir.glob("*.md")):
|
if fallback_dir.exists() and any(fallback_dir.glob("*.md")):
|
||||||
|
|||||||
@@ -677,6 +677,12 @@ class CommandRegistrar:
|
|||||||
"args": "$ARGUMENTS",
|
"args": "$ARGUMENTS",
|
||||||
"extension": ".md"
|
"extension": ".md"
|
||||||
},
|
},
|
||||||
|
"tabnine": {
|
||||||
|
"dir": ".tabnine/agent/commands",
|
||||||
|
"format": "toml",
|
||||||
|
"args": "{{args}}",
|
||||||
|
"extension": ".toml"
|
||||||
|
},
|
||||||
"bob": {
|
"bob": {
|
||||||
"dir": ".bob/commands",
|
"dir": ".bob/commands",
|
||||||
"format": "markdown",
|
"format": "markdown",
|
||||||
|
|||||||
@@ -97,3 +97,70 @@ class TestAgentConfigConsistency:
|
|||||||
assert "kiro-cli" in pwsh_text
|
assert "kiro-cli" in pwsh_text
|
||||||
assert "Amazon Q Developer CLI" not in bash_text
|
assert "Amazon Q Developer CLI" not in bash_text
|
||||||
assert "Amazon Q Developer CLI" not in pwsh_text
|
assert "Amazon Q Developer CLI" not in pwsh_text
|
||||||
|
|
||||||
|
# --- Tabnine CLI consistency checks ---
|
||||||
|
|
||||||
|
def test_runtime_config_includes_tabnine(self):
|
||||||
|
"""AGENT_CONFIG should include tabnine with correct folder and subdir."""
|
||||||
|
assert "tabnine" in AGENT_CONFIG
|
||||||
|
assert AGENT_CONFIG["tabnine"]["folder"] == ".tabnine/agent/"
|
||||||
|
assert AGENT_CONFIG["tabnine"]["commands_subdir"] == "commands"
|
||||||
|
assert AGENT_CONFIG["tabnine"]["requires_cli"] is True
|
||||||
|
assert AGENT_CONFIG["tabnine"]["install_url"] is not None
|
||||||
|
|
||||||
|
def test_extension_registrar_includes_tabnine(self):
|
||||||
|
"""CommandRegistrar.AGENT_CONFIGS should include tabnine with correct TOML config."""
|
||||||
|
from specify_cli.extensions import CommandRegistrar
|
||||||
|
|
||||||
|
assert "tabnine" in CommandRegistrar.AGENT_CONFIGS
|
||||||
|
cfg = CommandRegistrar.AGENT_CONFIGS["tabnine"]
|
||||||
|
assert cfg["dir"] == ".tabnine/agent/commands"
|
||||||
|
assert cfg["format"] == "toml"
|
||||||
|
assert cfg["args"] == "{{args}}"
|
||||||
|
assert cfg["extension"] == ".toml"
|
||||||
|
|
||||||
|
def test_release_agent_lists_include_tabnine(self):
|
||||||
|
"""Bash and PowerShell release scripts should include tabnine in agent lists."""
|
||||||
|
sh_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.sh").read_text(encoding="utf-8")
|
||||||
|
ps_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.ps1").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
sh_match = re.search(r"ALL_AGENTS=\(([^)]*)\)", sh_text)
|
||||||
|
assert sh_match is not None
|
||||||
|
sh_agents = sh_match.group(1).split()
|
||||||
|
|
||||||
|
ps_match = re.search(r"\$AllAgents = @\(([^)]*)\)", ps_text)
|
||||||
|
assert ps_match is not None
|
||||||
|
ps_agents = re.findall(r"'([^']+)'", ps_match.group(1))
|
||||||
|
|
||||||
|
assert "tabnine" in sh_agents
|
||||||
|
assert "tabnine" in ps_agents
|
||||||
|
|
||||||
|
def test_release_scripts_generate_tabnine_toml_commands(self):
|
||||||
|
"""Release scripts should generate TOML commands for tabnine in .tabnine/agent/commands."""
|
||||||
|
sh_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.sh").read_text(encoding="utf-8")
|
||||||
|
ps_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.ps1").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert ".tabnine/agent/commands" in sh_text
|
||||||
|
assert ".tabnine/agent/commands" in ps_text
|
||||||
|
assert re.search(r"'tabnine'\s*\{.*?\.tabnine/agent/commands", ps_text, re.S) is not None
|
||||||
|
|
||||||
|
def test_github_release_includes_tabnine_packages(self):
|
||||||
|
"""GitHub release script should include tabnine template packages."""
|
||||||
|
gh_release_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-github-release.sh").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert "spec-kit-template-tabnine-sh-" in gh_release_text
|
||||||
|
assert "spec-kit-template-tabnine-ps-" in gh_release_text
|
||||||
|
|
||||||
|
def test_agent_context_scripts_include_tabnine(self):
|
||||||
|
"""Agent context scripts should support tabnine agent type."""
|
||||||
|
bash_text = (REPO_ROOT / "scripts" / "bash" / "update-agent-context.sh").read_text(encoding="utf-8")
|
||||||
|
pwsh_text = (REPO_ROOT / "scripts" / "powershell" / "update-agent-context.ps1").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert "tabnine" in bash_text
|
||||||
|
assert "TABNINE_FILE" in bash_text
|
||||||
|
assert "tabnine" in pwsh_text
|
||||||
|
assert "TABNINE_FILE" in pwsh_text
|
||||||
|
|
||||||
|
def test_ai_help_includes_tabnine(self):
|
||||||
|
"""CLI help text for --ai should include tabnine."""
|
||||||
|
assert "tabnine" in AI_ASSISTANT_HELP
|
||||||
|
|||||||
@@ -147,6 +147,11 @@ class TestGetSkillsDir:
|
|||||||
result = _get_skills_dir(project_dir, "gemini")
|
result = _get_skills_dir(project_dir, "gemini")
|
||||||
assert result == project_dir / ".gemini" / "skills"
|
assert result == project_dir / ".gemini" / "skills"
|
||||||
|
|
||||||
|
def test_tabnine_skills_dir(self, project_dir):
|
||||||
|
"""Tabnine should use .tabnine/agent/skills/."""
|
||||||
|
result = _get_skills_dir(project_dir, "tabnine")
|
||||||
|
assert result == project_dir / ".tabnine" / "agent" / "skills"
|
||||||
|
|
||||||
def test_copilot_skills_dir(self, project_dir):
|
def test_copilot_skills_dir(self, project_dir):
|
||||||
"""Copilot should use .github/skills/."""
|
"""Copilot should use .github/skills/."""
|
||||||
result = _get_skills_dir(project_dir, "copilot")
|
result = _get_skills_dir(project_dir, "copilot")
|
||||||
|
|||||||
Reference in New Issue
Block a user