(args, ctx)
| 34 | ref: tool.schema.string().optional().describe("Branch or tag to clone (defaults to repo default branch)"), |
| 35 | }, |
| 36 | async execute(args, ctx) { |
| 37 | const blocked = await client.requireCliAvailable() |
| 38 | if (blocked) return blocked |
| 39 | |
| 40 | // Check if already indexed. Skip the dedup probe when we know the |
| 41 | // workspace has no DB yet — the listRepos call would just hit exit 3. |
| 42 | // `id` is the canonical key (matches `--repo` filters); `name` is the |
| 43 | // display label and only equals `id` when the user didn't pass |
| 44 | // `--repo-id` at index time. We accept either since the LLM can |
| 45 | // reasonably pass either form. |
| 46 | if (client.dbReadyHint() !== false) { |
| 47 | const repos = await client.listRepos() |
| 48 | const existing = repos.find((r) => |
| 49 | r.id === args.repo_id || |
| 50 | r.name === args.repo_id || |
| 51 | r.properties?.sourceUri === args.path_or_url, |
| 52 | ) |
| 53 | if (existing) { |
| 54 | const props = existing.properties |
| 55 | return `Repository "${existing.name}" is already indexed.\n` + |
| 56 | ` Source: ${props.sourceUri ?? "local"}\n` + |
| 57 | ` Branch: ${props.branch ?? "unknown"}\n` + |
| 58 | ` Commit: ${props.commitSha ?? "unknown"}\n\n` + |
| 59 | `Use opentrace_source_search to search its code, or re-run this tool to re-index.` |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | // Re-gate before spawning: the dedup listRepos call may have surfaced |
| 64 | // an unresolvable workspace, in which case the contract message is |
| 65 | // a cleaner thing to return than letting indexRepo also fail. |
| 66 | const reblocked = await client.requireCliAvailable() |
| 67 | if (reblocked) return reblocked |
| 68 | |
| 69 | // Strip trailing slashes so "/path/to/repo/" yields "repo". |
| 70 | const name = args.path_or_url.replace(/\/+$/, "").split("/").pop()?.replace(".git", "") || "repo" |
| 71 | ctx.metadata({ title: `Indexing ${name}...` }) |
| 72 | |
| 73 | // Resolve token internally — picks the right token for the host |
| 74 | const token = await resolveToken(args.path_or_url) |
| 75 | |
| 76 | const result = await client.indexRepo(args.path_or_url, args.repo_id, { |
| 77 | token: token ?? undefined, |
| 78 | ref: args.ref, |
| 79 | }) |
| 80 | |
| 81 | if (!result.ok) { |
| 82 | if (result.inProgress) { |
| 83 | ctx.metadata({ title: "Waiting on another index..." }) |
| 84 | return result.message |
| 85 | } |
| 86 | ctx.metadata({ title: `Indexing ${name} failed` }) |
| 87 | return `Indexing failed:\n${result.message}` |
| 88 | } |
| 89 | |
| 90 | ctx.metadata({ title: `Indexed ${name}` }) |
| 91 | return `Indexing result:\n${result.message}\n\nThe repository should now be searchable via opentrace_source_search and readable via opentrace_source_read.` |
| 92 | }, |
| 93 | }) |
no test coverage detected