Skip to content

Commit 937fc7e

Browse files
committed
Fix workspace auto-indexing and bump to v0.1.3
1 parent 765cb28 commit 937fc7e

4 files changed

Lines changed: 181 additions & 17 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
default-run = "acb"
33
name = "agentic-codebase"
4-
version = "0.1.2"
4+
version = "0.1.3"
55
edition = "2021"
66
license = "MIT"
77
repository = "https://github.com/agentralabs/codebase"

docs/public/runtime-install-sync.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ Install complete: AgenticCodebase (<profile>)
3636
}
3737
```
3838

39+
## Workspace auto-indexing behavior
40+
41+
- Installer writes `acb-mcp-agentra` launcher as MCP entrypoint.
42+
- On every start, launcher resolves active workspace and graph in this order:
43+
1. Explicit override: `AGENTRA_ACB_PATH` / `AGENTRA_GRAPH_PATH`.
44+
2. Active workspace root (`AGENTRA_WORKSPACE_ROOT` / `AGENTRA_PROJECT_ROOT` / current project dir).
45+
3. Cached per-workspace graph: `${CODEX_HOME:-~/.codex}/graphs/<workspace-slug>.acb`.
46+
4. Latest cached fallback graph if workspace resolution is unavailable.
47+
- If the per-workspace graph is missing or stale, launcher rebuilds it automatically with a lock to avoid parallel rebuild races.
48+
- If your MCP client starts outside the project directory, set:
49+
50+
```bash
51+
export AGENTRA_WORKSPACE_ROOT="/absolute/path/to/project"
52+
```
53+
3954
## Server auth + sync
4055

4156
```bash

scripts/install.sh

Lines changed: 164 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -283,30 +283,179 @@ install_mcp_entrypoint() {
283283
fi
284284

285285
mkdir -p "${INSTALL_DIR}"
286-
cat >"${MCP_ENTRYPOINT}" <<EOF
286+
cat >"${MCP_ENTRYPOINT}" <<EOF
287287
#!/usr/bin/env bash
288288
set -eo pipefail
289289
290290
BIN="${INSTALL_DIR}/${BINARY_NAME}"
291+
ACB_BIN="${INSTALL_DIR}/acb"
292+
293+
pwd_is_project() {
294+
[ -d "\$PWD/.git" ] || \
295+
[ -f "\$PWD/Cargo.toml" ] || \
296+
[ -f "\$PWD/package.json" ] || \
297+
[ -f "\$PWD/pyproject.toml" ] || \
298+
[ -f "\$PWD/go.mod" ] || \
299+
[ -d "\$PWD/src" ]
300+
}
301+
302+
pwd_contains_projects() {
303+
find "\$PWD" -maxdepth 2 -type f \
304+
\\( -name 'Cargo.toml' -o -name 'package.json' -o -name 'pyproject.toml' -o -name 'go.mod' \\) \
305+
-print -quit 2>/dev/null | grep -q .
306+
}
307+
308+
resolve_repo_root() {
309+
if [ -n "\${AGENTRA_WORKSPACE_ROOT:-}" ] && [ -d "\${AGENTRA_WORKSPACE_ROOT}" ]; then
310+
printf '%s' "\${AGENTRA_WORKSPACE_ROOT}"
311+
return
312+
fi
313+
if [ -n "\${AGENTRA_PROJECT_ROOT:-}" ] && [ -d "\${AGENTRA_PROJECT_ROOT}" ]; then
314+
printf '%s' "\${AGENTRA_PROJECT_ROOT}"
315+
return
316+
fi
317+
if pwd_is_project || pwd_contains_projects; then
318+
printf '%s' "\$PWD"
319+
return
320+
fi
321+
if command -v git >/dev/null 2>&1; then
322+
local root
323+
root="\$(git rev-parse --show-toplevel 2>/dev/null || true)"
324+
if [ -n "\$root" ] && [ -d "\$root" ]; then
325+
if [ "\$root" = "\$HOME" ] || [ "\$root" = "\$HOME/Documents" ] || [ "\$root" = "\$HOME/Desktop" ]; then
326+
printf '%s' "\$PWD"
327+
return
328+
fi
329+
printf '%s' "\$root"
330+
return
331+
fi
332+
fi
333+
printf '%s' "\$PWD"
334+
}
335+
336+
slugify() {
337+
local raw="\$1"
338+
local base
339+
base="\$(basename "\$raw")"
340+
base="\$(printf '%s' "\$base" | tr '[:upper:]' '[:lower:]')"
341+
base="\$(printf '%s' "\$base" | sed -E 's/[^a-z0-9._-]+/-/g; s/^-+//; s/-+\$//')"
342+
if [ -z "\$base" ]; then
343+
base="workspace"
344+
fi
345+
printf '%s' "\$base"
346+
}
347+
348+
can_index_repo() {
349+
local repo_root="\$1"
350+
if [ "\$repo_root" = "\$HOME" ]; then
351+
return 1
352+
fi
353+
if command -v git >/dev/null 2>&1 && git -C "\$repo_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
354+
return 0
355+
fi
356+
find "\$repo_root" -maxdepth 2 -type f \
357+
\\( -name '*.rs' -o -name '*.py' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' \
358+
-o -name '*.go' -o -name '*.java' -o -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \\) \
359+
-print -quit 2>/dev/null | grep -q .
360+
}
361+
362+
graph_is_stale() {
363+
local repo_root="\$1"
364+
local graph_path="\$2"
365+
[ ! -f "\$graph_path" ] && return 0
366+
find "\$repo_root" \
367+
\\( -name .git -o -name target -o -name node_modules -o -name .venv -o -name venv -o -name dist -o -name build -o -name .next \\) -prune -o \
368+
-type f \
369+
\\( -name '*.rs' -o -name '*.py' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' \
370+
-o -name '*.go' -o -name '*.java' -o -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \\) \
371+
-newer "\$graph_path" -print -quit 2>/dev/null | grep -q .
372+
}
373+
374+
compile_graph_if_needed() {
375+
local repo_root="\$1"
376+
local graph_path="\$2"
377+
if ! can_index_repo "\$repo_root"; then
378+
return 0
379+
fi
380+
if [ -f "\$graph_path" ] && ! graph_is_stale "\$repo_root" "\$graph_path"; then
381+
return 0
382+
fi
383+
384+
local lock_dir="\${graph_path}.lock"
385+
local wait_count=0
386+
while ! mkdir "\$lock_dir" 2>/dev/null; do
387+
wait_count=\$((wait_count + 1))
388+
if [ "\$wait_count" -ge 90 ]; then
389+
echo "Warning: graph build lock timeout for \$graph_path" >&2
390+
return 0
391+
fi
392+
sleep 1
393+
done
394+
trap 'rmdir "'"'\$lock_dir'"'" >/dev/null 2>&1 || true' RETURN
395+
396+
if [ -f "\$graph_path" ] && ! graph_is_stale "\$repo_root" "\$graph_path"; then
397+
return 0
398+
fi
399+
mkdir -p "\$(dirname "\$graph_path")"
400+
if [ -x "\$ACB_BIN" ]; then
401+
"\$ACB_BIN" compile "\$repo_root" -o "\$graph_path" >/dev/null 2>&1 || true
402+
elif command -v acb >/dev/null 2>&1; then
403+
acb compile "\$repo_root" -o "\$graph_path" >/dev/null 2>&1 || true
404+
fi
405+
if [ ! -f "\$graph_path" ]; then
406+
echo "Error: unable to build code graph for \$repo_root" >&2
407+
return 1
408+
fi
409+
}
410+
411+
latest_cached_graph() {
412+
local graph_dir="\$1"
413+
if [ -d "\$graph_dir" ]; then
414+
find "\$graph_dir" -maxdepth 1 -type f -name '*.acb' -print0 2>/dev/null \
415+
| xargs -0 ls -1t 2>/dev/null | head -n 1
416+
fi
417+
}
291418
292-
find_graph() {
419+
resolve_graph() {
293420
local candidate
294-
local found=""
295-
296-
for candidate in \
297-
"\${AGENTRA_ACB_PATH:-}" \
298-
"\${AGENTRA_GRAPH_PATH:-}" \
299-
"\${CODEX_HOME:-\$HOME/.codex}/graphs/agentralabs-tech.acb" \
300-
"\$HOME/.agentra/graphs/default.acb" \
301-
"\$PWD/agentralabs-tech.acb" \
302-
"\$PWD/graph.acb"; do
421+
local explicit
422+
explicit=""
423+
for candidate in "\${AGENTRA_ACB_PATH:-}" "\${AGENTRA_GRAPH_PATH:-}"; do
303424
if [ -n "\$candidate" ] && [ -f "\$candidate" ]; then
304-
found="\$candidate"
425+
explicit="\$candidate"
305426
break
306427
fi
307428
done
429+
if [ -n "\$explicit" ]; then
430+
printf '%s' "\$explicit"
431+
return
432+
fi
433+
434+
local repo_root repo_slug graph_dir graph_path fallback
435+
repo_root="\$(resolve_repo_root)"
436+
repo_slug="\$(slugify "\$repo_root")"
437+
graph_dir="\${AGENTRA_GRAPH_CACHE_DIR:-\${CODEX_HOME:-\$HOME/.codex}/graphs}"
438+
graph_path="\${graph_dir}/\${repo_slug}.acb"
439+
440+
if compile_graph_if_needed "\$repo_root" "\$graph_path"; then
441+
if [ -f "\$graph_path" ]; then
442+
printf '%s' "\$graph_path"
443+
return
444+
fi
445+
fi
308446
309-
[ -n "\$found" ] && printf '%s' "\$found"
447+
fallback="\$(latest_cached_graph "\$graph_dir")"
448+
if [ -n "\$fallback" ] && [ -f "\$fallback" ]; then
449+
printf '%s' "\$fallback"
450+
return
451+
fi
452+
453+
for candidate in "\$HOME/.agentra/graphs/default.acb" "\$PWD/graph.acb"; do
454+
if [ -f "\$candidate" ]; then
455+
printf '%s' "\$candidate"
456+
break
457+
fi
458+
done
310459
}
311460
312461
args=("\$@")
@@ -326,11 +475,11 @@ for arg in "\${args[@]}"; do
326475
done
327476
328477
if [ "\$has_graph" -eq 0 ]; then
329-
graph_path="\$(find_graph || true)"
478+
graph_path="\$(resolve_graph || true)"
330479
if [ -n "\$graph_path" ]; then
331480
args=(--graph "\$graph_path" "\${args[@]}")
332481
if [ "\$has_name" -eq 0 ]; then
333-
graph_name="\$(basename "\$graph_path" .acb)"
482+
graph_name="\$(basename "\$graph_path" .acb | sed -E 's/[^a-zA-Z0-9._-]+/-/g')"
334483
args=(--name "\$graph_name" "\${args[@]}")
335484
fi
336485
fi

0 commit comments

Comments
 (0)