Skip to content

Commit cfea91c

Browse files
feat: Official pi fff extension (#374)
* feat: add pi extension for FFF file search Add @ff-labs/pi-fff package providing pi coding agent integration: - Overrides built-in find/grep tools with FFF-powered versions - Adds multi_grep tool for SIMD-accelerated multi-pattern search - Replaces @-mention autocomplete with FFF frecency-ranked suggestions - Commands: /fff-health, /fff-rescan, /fff-mode (with immediate switch) - Streamlined implementation: 26% code reduction (800→590 lines) Published as pi package: npm:@ff-labs/pi-fff * docs: fix install instructions - Remove git install option (doesn't work for monorepo subfolders) - Remove config file from mode precedence (no longer used) - Keep npm as only recommended install method * feat: add root pi manifest for git installs Add pi configuration to root package.json pointing to packages/pi-fff. This enables: pi install git:github.com/dmtrKovalenko/fff.nvim The root stays private (not published to npm), but pi can now discover the extension from the git repo structure. * docs: add git install instructions Now that root package.json has pi manifest, git installs work: pi install git:github.com/dmtrKovalenko/fff.nvim * fix: address PR review feedback - Add config file persistence for /fff-mode (fixes 'persist' claim) - Add readConfigMode() and writeConfigMode() helpers - Use applyEditorMode() in /fff-mode command (DRY) - Add publishConfig.access: 'public' for npm publishing - Fix @types/node to ^22.0.0 (align with repo) - Remove ignoreCase parameter (FFF doesn't support force case-insensitive) - Run Biome formatter (fix tab indentation) * update toolnames and add to release pipeline * do not override default tools * Make an option to override the default tools * fix: macos tests * better toolnames mangement --------- Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
1 parent cc9ce25 commit cfea91c

8 files changed

Lines changed: 5372 additions & 531 deletions

File tree

.github/workflows/release.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,16 @@ jobs:
571571
npm install
572572
npm run build
573573
npm publish --tag "$TAG" --access public || echo "Failed to publish @ff-labs/fff-node (may already exist)"
574+
575+
- name: Publish pi-fff package
576+
env:
577+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
578+
run: |
579+
VERSION="${{ steps.version.outputs.version }}"
580+
TAG="${{ steps.version.outputs.npm_tag }}"
581+
582+
echo "Publishing @ff-labs/pi-fff@${VERSION} with tag ${TAG}..."
583+
make set-npm-version PKG=packages/pi-fff VERSION="$VERSION"
584+
585+
cd packages/pi-fff
586+
npm publish --tag "$TAG" --access public || echo "Failed to publish @ff-labs/pi-fff (may already exist)"

crates/fff-mcp/src/main.rs

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -161,43 +161,10 @@ pub(crate) struct Args {
161161
pub(crate) healthcheck: bool,
162162
}
163163

164-
/// Resolve default paths for frecency db, history db, and log file.
165-
/// Shares Neovim's standard data locations when they exist so the MCP
166-
/// server and fff.nvim plugin use the same databases.
164+
/// Resolve default paths for the log file.
165+
/// Database paths (frecency, history) must be explicitly provided via flags.
167166
fn resolve_defaults(args: &mut Args) {
168-
let home = dirs_home();
169-
let is_windows = cfg!(target_os = "windows");
170-
171-
let nvim_cache_dir = if is_windows {
172-
format!("{}\\AppData\\Local\\nvim-data", home)
173-
} else {
174-
format!("{}/.cache/nvim", home)
175-
};
176-
let nvim_data_dir = if is_windows {
177-
format!("{}\\AppData\\Local\\nvim-data", home)
178-
} else {
179-
format!("{}/.local/share/nvim", home)
180-
};
181-
182-
let use_nvim_paths = std::path::Path::new(&nvim_cache_dir).exists()
183-
|| std::path::Path::new(&nvim_data_dir).exists();
184-
185-
if args.frecency_db_path.is_none() {
186-
args.frecency_db_path = Some(if use_nvim_paths {
187-
format!("{}/fff_nvim", nvim_cache_dir)
188-
} else {
189-
format!("{}/.fff/frecency.mdb", home)
190-
});
191-
}
192-
if args.history_db_path.is_none() {
193-
args.history_db_path = Some(if use_nvim_paths {
194-
format!("{}/fff_queries", nvim_data_dir)
195-
} else {
196-
format!("{}/.fff/history.mdb", home)
197-
});
198-
}
199-
200-
// Ensure parent directories exist for database paths
167+
// Ensure parent directories exist for database paths when provided
201168
for path in [&args.frecency_db_path, &args.history_db_path]
202169
.into_iter()
203170
.flatten()
@@ -208,6 +175,8 @@ fn resolve_defaults(args: &mut Args) {
208175
}
209176

210177
if args.log_file.is_none() {
178+
let home = dirs_home();
179+
let is_windows = cfg!(target_os = "windows");
211180
args.log_file = Some(if is_windows {
212181
format!("{}\\AppData\\Local\\fff_mcp.log", home)
213182
} else {
@@ -263,17 +232,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
263232
}
264233
};
265234

266-
let frecency_db_path = args.frecency_db_path.unwrap_or_default();
267-
268235
let shared_picker = SharedPicker::default();
269236
let shared_frecency = SharedFrecency::default();
270-
match FrecencyTracker::new(&frecency_db_path, false) {
271-
Ok(tracker) => {
272-
let _ = shared_frecency.init(tracker);
273-
let _ = shared_frecency.spawn_gc(frecency_db_path, false);
274-
}
275-
Err(e) => {
276-
eprintln!("Warning: Failed to init frecency db: {}", e);
237+
if let Some(frecency_db_path) = args.frecency_db_path {
238+
match FrecencyTracker::new(&frecency_db_path, false) {
239+
Ok(tracker) => {
240+
let _ = shared_frecency.init(tracker);
241+
let _ = shared_frecency.spawn_gc(frecency_db_path, false);
242+
}
243+
Err(e) => {
244+
eprintln!("Warning: Failed to init frecency db: {}", e);
245+
}
277246
}
278247
}
279248

0 commit comments

Comments
 (0)