SourceIndex 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sourceindex-0.1.0 → sourceindex-0.1.2}/.gitignore +4 -0
- sourceindex-0.1.2/GETTING_STARTED.md +83 -0
- sourceindex-0.1.2/PKG-INFO +103 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/pyproject.toml +1 -4
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/__init__.py +1 -1
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/indexer.py +15 -7
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/state.py +12 -1
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/cli/__init__.py +172 -62
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/cli/api_key.py +121 -20
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/cli/commands.py +124 -54
- sourceindex-0.1.2/sourceindex/cli/install.py +507 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/__init__.py +21 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/client.py +14 -2
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/protocol.py +1 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/server.py +180 -4
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/store.py +6 -1
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/backend.py +91 -39
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/cost.py +6 -1
- sourceindex-0.1.2/sourceindex/lib/errors.py +161 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/llm.py +126 -30
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/log.py +196 -4
- sourceindex-0.1.2/sourceindex/search/__init__.py +381 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/search/prompts.py +7 -9
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/search/roadmap.py +32 -3
- sourceindex-0.1.0/GETTING_STARTED.md +0 -51
- sourceindex-0.1.0/PKG-INFO +0 -73
- sourceindex-0.1.0/sourceindex/cli/install.py +0 -378
- sourceindex-0.1.0/sourceindex/search/__init__.py +0 -251
- sourceindex-0.1.0/sourceindex/server.py +0 -127
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/__init__.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/linerange/__init__.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/linerange/python_ast.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/linerange/treesitter.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/prompts.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/build/walker.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/claudecode/__init__.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/claudecode/savings.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/claudecode/savings_summary.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/claudecode/statusline.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/cli/__main__.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/crypto.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/keyring_store.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/daemon/lifecycle.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/__init__.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/env.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/git.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/languages.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/registry.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/lib/timing.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/search/experiments.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/search/imports.py +0 -0
- {sourceindex-0.1.0 → sourceindex-0.1.2}/sourceindex/search/passes.py +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Getting Started with SourceIndex
|
|
2
|
+
|
|
3
|
+
Hey — and thank you! You're the very first person outside the team to try
|
|
4
|
+
SourceIndex, and that genuinely means a lot. I'm really glad you're giving
|
|
5
|
+
it a go.
|
|
6
|
+
|
|
7
|
+
Anything you notice along the way — good, bad, broken, or just "huh, that's
|
|
8
|
+
weird" — would be hugely helpful to hear. No feedback is too small.
|
|
9
|
+
|
|
10
|
+
## What it is
|
|
11
|
+
|
|
12
|
+
When you ask a coding agent to fix or build something, it has to find the
|
|
13
|
+
relevant code first. By default Claude Code and opencode do that live, in
|
|
14
|
+
your session. SourceIndex does it ahead of time so the agent jumps straight
|
|
15
|
+
to the right files.
|
|
16
|
+
|
|
17
|
+
**Best on an existing repo you didn't fully write yourself.** Not very useful
|
|
18
|
+
on a brand-new empty project.
|
|
19
|
+
|
|
20
|
+
## Install and set up
|
|
21
|
+
|
|
22
|
+
You'll need Python 3.10+ and a SourceIndex API key (starts with `sk-si-`).
|
|
23
|
+
Apply for access at https://sourceindex.dev/access.
|
|
24
|
+
|
|
25
|
+
**Easiest path:** open this file in Claude Code or opencode and tell it "set
|
|
26
|
+
sourceindex up in this repo." It can run the steps for you.
|
|
27
|
+
|
|
28
|
+
If you'd rather do it by hand:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install sourceindex
|
|
32
|
+
cd /path/to/your/repo
|
|
33
|
+
sourceindex init # auto-detects your agent(s)
|
|
34
|
+
sourceindex init claude # set up Claude Code only
|
|
35
|
+
sourceindex init opencode # set up opencode only
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It'll prompt for the key, set up some git hooks plus a subagent for the
|
|
39
|
+
coding agent your repo already uses (a `CLAUDE.md` or `.claude/` means
|
|
40
|
+
Claude Code; an `AGENTS.md` or `.opencode/` means opencode; neither means
|
|
41
|
+
Claude Code), and scan your repo. A few minutes, once per repo. You can
|
|
42
|
+
also name both at once (`sourceindex init claude opencode`), and it's safe
|
|
43
|
+
to re-run init later to add the other agent.
|
|
44
|
+
If you don't have a `CLAUDE.md` (Claude Code) or `AGENTS.md` (opencode)
|
|
45
|
+
yet, run `/init` in your agent first.
|
|
46
|
+
|
|
47
|
+
To replace a rotated or expired key later:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
sourceindex api-key set
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That prompts for the new key and persists it as your user-level default. New
|
|
54
|
+
repos and repos without a local override will use it automatically. For
|
|
55
|
+
automation, use
|
|
56
|
+
`sourceindex api-key set --from-env` with `SOURCEINDEX_API_KEY` already set,
|
|
57
|
+
pass `--api-key sk-si-...`, or pass the key positionally:
|
|
58
|
+
`sourceindex api-key set sk-si-...`.
|
|
59
|
+
|
|
60
|
+
To set a repo-local override:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
sourceindex api-key set --local
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Explicit environment variables still win, and a repo-local key overrides the
|
|
67
|
+
global default.
|
|
68
|
+
|
|
69
|
+
## Day-to-day
|
|
70
|
+
|
|
71
|
+
Nothing. Open the repo in Claude Code or opencode as usual — it'll use
|
|
72
|
+
SourceIndex on its own.
|
|
73
|
+
|
|
74
|
+
## Feedback I'd love
|
|
75
|
+
|
|
76
|
+
- Did `sourceindex init` finish cleanly?
|
|
77
|
+
- Does the agent feel different? Even "I can't tell" is useful.
|
|
78
|
+
- Anything in this doc that didn't land.
|
|
79
|
+
|
|
80
|
+
More about the project lives at https://sourceindex.dev, and you can reach
|
|
81
|
+
us any time at hi@sourceindex.dev.
|
|
82
|
+
|
|
83
|
+
Thanks!
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: SourceIndex
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Codebase index for agentic coding
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: cryptography>=42
|
|
7
|
+
Requires-Dist: keyring>=24
|
|
8
|
+
Requires-Dist: litellm>=1.50
|
|
9
|
+
Requires-Dist: tree-sitter-c>=0.23
|
|
10
|
+
Requires-Dist: tree-sitter-cpp>=0.23
|
|
11
|
+
Requires-Dist: tree-sitter-go>=0.23
|
|
12
|
+
Requires-Dist: tree-sitter-java>=0.23
|
|
13
|
+
Requires-Dist: tree-sitter-javascript>=0.23
|
|
14
|
+
Requires-Dist: tree-sitter-kotlin>=1.0
|
|
15
|
+
Requires-Dist: tree-sitter-ruby>=0.23
|
|
16
|
+
Requires-Dist: tree-sitter-rust>=0.23
|
|
17
|
+
Requires-Dist: tree-sitter-typescript>=0.23
|
|
18
|
+
Requires-Dist: tree-sitter>=0.23
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Getting Started with SourceIndex
|
|
22
|
+
|
|
23
|
+
Hey — and thank you! You're the very first person outside the team to try
|
|
24
|
+
SourceIndex, and that genuinely means a lot. I'm really glad you're giving
|
|
25
|
+
it a go.
|
|
26
|
+
|
|
27
|
+
Anything you notice along the way — good, bad, broken, or just "huh, that's
|
|
28
|
+
weird" — would be hugely helpful to hear. No feedback is too small.
|
|
29
|
+
|
|
30
|
+
## What it is
|
|
31
|
+
|
|
32
|
+
When you ask a coding agent to fix or build something, it has to find the
|
|
33
|
+
relevant code first. By default Claude Code and opencode do that live, in
|
|
34
|
+
your session. SourceIndex does it ahead of time so the agent jumps straight
|
|
35
|
+
to the right files.
|
|
36
|
+
|
|
37
|
+
**Best on an existing repo you didn't fully write yourself.** Not very useful
|
|
38
|
+
on a brand-new empty project.
|
|
39
|
+
|
|
40
|
+
## Install and set up
|
|
41
|
+
|
|
42
|
+
You'll need Python 3.10+ and a SourceIndex API key (starts with `sk-si-`).
|
|
43
|
+
Apply for access at https://sourceindex.dev/access.
|
|
44
|
+
|
|
45
|
+
**Easiest path:** open this file in Claude Code or opencode and tell it "set
|
|
46
|
+
sourceindex up in this repo." It can run the steps for you.
|
|
47
|
+
|
|
48
|
+
If you'd rather do it by hand:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install sourceindex
|
|
52
|
+
cd /path/to/your/repo
|
|
53
|
+
sourceindex init # auto-detects your agent(s)
|
|
54
|
+
sourceindex init claude # set up Claude Code only
|
|
55
|
+
sourceindex init opencode # set up opencode only
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
It'll prompt for the key, set up some git hooks plus a subagent for the
|
|
59
|
+
coding agent your repo already uses (a `CLAUDE.md` or `.claude/` means
|
|
60
|
+
Claude Code; an `AGENTS.md` or `.opencode/` means opencode; neither means
|
|
61
|
+
Claude Code), and scan your repo. A few minutes, once per repo. You can
|
|
62
|
+
also name both at once (`sourceindex init claude opencode`), and it's safe
|
|
63
|
+
to re-run init later to add the other agent.
|
|
64
|
+
If you don't have a `CLAUDE.md` (Claude Code) or `AGENTS.md` (opencode)
|
|
65
|
+
yet, run `/init` in your agent first.
|
|
66
|
+
|
|
67
|
+
To replace a rotated or expired key later:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
sourceindex api-key set
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
That prompts for the new key and persists it as your user-level default. New
|
|
74
|
+
repos and repos without a local override will use it automatically. For
|
|
75
|
+
automation, use
|
|
76
|
+
`sourceindex api-key set --from-env` with `SOURCEINDEX_API_KEY` already set,
|
|
77
|
+
pass `--api-key sk-si-...`, or pass the key positionally:
|
|
78
|
+
`sourceindex api-key set sk-si-...`.
|
|
79
|
+
|
|
80
|
+
To set a repo-local override:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
sourceindex api-key set --local
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Explicit environment variables still win, and a repo-local key overrides the
|
|
87
|
+
global default.
|
|
88
|
+
|
|
89
|
+
## Day-to-day
|
|
90
|
+
|
|
91
|
+
Nothing. Open the repo in Claude Code or opencode as usual — it'll use
|
|
92
|
+
SourceIndex on its own.
|
|
93
|
+
|
|
94
|
+
## Feedback I'd love
|
|
95
|
+
|
|
96
|
+
- Did `sourceindex init` finish cleanly?
|
|
97
|
+
- Does the agent feel different? Even "I can't tell" is useful.
|
|
98
|
+
- Anything in this doc that didn't land.
|
|
99
|
+
|
|
100
|
+
More about the project lives at https://sourceindex.dev, and you can reach
|
|
101
|
+
us any time at hi@sourceindex.dev.
|
|
102
|
+
|
|
103
|
+
Thanks!
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "SourceIndex"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "Codebase index for agentic coding"
|
|
9
9
|
readme = "GETTING_STARTED.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -32,9 +32,6 @@ dependencies = [
|
|
|
32
32
|
"tree-sitter-typescript>=0.23",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
|
-
[project.optional-dependencies]
|
|
36
|
-
mcp = ["mcp>=1.0.0,<2"]
|
|
37
|
-
|
|
38
35
|
[project.scripts]
|
|
39
36
|
sourceindex = "sourceindex.cli:main"
|
|
40
37
|
|
|
@@ -36,13 +36,20 @@ REALTIME_MAX_RETRIES = 5
|
|
|
36
36
|
# file, but pays for itself at 2+.
|
|
37
37
|
BATCH_MIN_FILES = 2
|
|
38
38
|
RETRY_DELAY = 1.0
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
39
|
+
# The BUILD (indexing) default. Indexing is one LLM call per source file, so
|
|
40
|
+
# this is the high-volume, cost-dominant model — hence the small cheap one.
|
|
41
|
+
# Search keeps its own default (search.DEFAULT_SEARCH_MODEL): 1a/1b selection
|
|
42
|
+
# quality is a different tradeoff from per-file summarization, and the backend
|
|
43
|
+
# routes the two dimensions independently, so they default independently too.
|
|
44
|
+
# Previous default: openrouter/openai/gpt-5.4-nano, picked as the best
|
|
45
|
+
# price/latency/quality balance across DS-V4-Flash, Haiku 4.5, Mistral-Small,
|
|
46
|
+
# Gemini-Flash-Lite and the gpt-5 nano family (Opus-judged description quality
|
|
47
|
+
# + AST-grounded recall + line-range accuracy).
|
|
42
48
|
# Reached via SOURCEINDEX_API_KEY: an sk-si bearer routes through the hosted
|
|
43
|
-
# backend,
|
|
44
|
-
#
|
|
45
|
-
|
|
49
|
+
# backend, which serves this model from AWS Bedrock (backend migration 0009);
|
|
50
|
+
# an sk-or-/sk-ant-/etc. provider key auto-opts-out and hits the provider
|
|
51
|
+
# directly. SOURCEINDEX_BACKEND_URL pins/disables the routing.
|
|
52
|
+
DEFAULT_MODEL = "openrouter/google/gemma-4-e2b"
|
|
46
53
|
BATCH_POLL_INTERVAL = 30
|
|
47
54
|
BATCH_MAX_WAIT = 3600
|
|
48
55
|
BATCH_MAX_TOKENS = 16384
|
|
@@ -102,7 +109,7 @@ def index_file(
|
|
|
102
109
|
total_usage = LLMUsage()
|
|
103
110
|
for attempt in range(2):
|
|
104
111
|
try:
|
|
105
|
-
response, usage = call_llm(prompt, model=model, api_key=api_key)
|
|
112
|
+
response, usage = call_llm(prompt, model=model, api_key=api_key, pass_tag="build")
|
|
106
113
|
total_usage.add(usage)
|
|
107
114
|
if response:
|
|
108
115
|
oneliner, functions = parse_response(response)
|
|
@@ -305,6 +312,7 @@ def submit_and_wait_batch(
|
|
|
305
312
|
model=req["model"],
|
|
306
313
|
api_key=api_key,
|
|
307
314
|
max_tokens=req["max_tokens"],
|
|
315
|
+
pass_tag="build",
|
|
308
316
|
)
|
|
309
317
|
attempt_usage.add(usage)
|
|
310
318
|
return cid, text or "", attempt_usage
|
|
@@ -31,6 +31,10 @@ SUMMARY_CACHE_FILENAME = "_summary_cache.json"
|
|
|
31
31
|
FILE_INDEX_FILENAME = "_file_index.json"
|
|
32
32
|
BUILD_META_FILENAME = "build_meta.json"
|
|
33
33
|
|
|
34
|
+
# Written as the details body when tier-2 indexing produced nothing; search
|
|
35
|
+
# matches against this exact string to classify a file as un-indexed.
|
|
36
|
+
INDEXING_FAILED_PLACEHOLDER = "(LLM indexing failed)"
|
|
37
|
+
|
|
34
38
|
|
|
35
39
|
# ── Summary cache ──────────────────────────────────────────────────────────
|
|
36
40
|
|
|
@@ -117,10 +121,17 @@ def save_file_index(store, paths: dict[str, dict]) -> None:
|
|
|
117
121
|
|
|
118
122
|
def write_details(store, rel_path: str, functions_text: str) -> None:
|
|
119
123
|
"""Write tier-2 function index to details/<rel_path>.md."""
|
|
120
|
-
body = functions_text.strip() or
|
|
124
|
+
body = functions_text.strip() or INDEXING_FAILED_PLACEHOLDER
|
|
121
125
|
store.write_text(f"details/{rel_path}.md", f"# {rel_path}\n\n{body}\n")
|
|
122
126
|
|
|
123
127
|
|
|
128
|
+
def details_failed(text: str) -> bool:
|
|
129
|
+
"""True when a details file (as composed by write_details) holds only
|
|
130
|
+
the tier-2 failure placeholder."""
|
|
131
|
+
_, _, body = text.partition("\n\n")
|
|
132
|
+
return body.strip() == INDEXING_FAILED_PLACEHOLDER
|
|
133
|
+
|
|
134
|
+
|
|
124
135
|
def details_exists(store, rel_path: str) -> bool:
|
|
125
136
|
return store.exists(f"details/{rel_path}.md")
|
|
126
137
|
|