@wrongstack/tools 0.73.1 → 0.77.0
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.
- package/dist/{background-indexer-sbsseCCC.d.ts → background-indexer-C70RD7LU.d.ts} +33 -1
- package/dist/builtin.js +94 -2
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.d.ts +2 -2
- package/dist/codebase-index/index.js +192 -66
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +194 -67
- package/dist/index.js.map +1 -1
- package/dist/pack.js +94 -2
- package/dist/pack.js.map +1 -1
- package/dist/todo.js +2 -1
- package/dist/todo.js.map +1 -1
- package/package.json +2 -2
|
@@ -11,6 +11,8 @@ interface CodebaseIndexOutput {
|
|
|
11
11
|
langStats: Record<string, number>;
|
|
12
12
|
durationMs: number;
|
|
13
13
|
errors: string[];
|
|
14
|
+
/** Advisory note when the indexer was skipped (e.g. another index in progress). */
|
|
15
|
+
note?: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/** Language a symbol belongs to. */
|
|
@@ -122,6 +124,8 @@ interface CodebaseSearchOutput {
|
|
|
122
124
|
results: SearchResult[];
|
|
123
125
|
total: number;
|
|
124
126
|
query: string;
|
|
127
|
+
/** Non-empty when the index blocked the search (not ready, indexing, failed). */
|
|
128
|
+
indexStatus?: string;
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
/**
|
|
@@ -142,6 +146,8 @@ interface CodebaseStatsOutput {
|
|
|
142
146
|
sizeBytes: number;
|
|
143
147
|
indexPath: string;
|
|
144
148
|
version: number;
|
|
149
|
+
/** Non-empty when the index is not ready or is still building. */
|
|
150
|
+
indexStatus?: string;
|
|
145
151
|
}
|
|
146
152
|
|
|
147
153
|
/**
|
|
@@ -159,17 +165,43 @@ interface CodebaseStatsOutput {
|
|
|
159
165
|
* 2. **Debounce** — rapid successive edits to the same file (editor autosave,
|
|
160
166
|
* multi-edit) coalesce into a single reindex, keyed per `(indexDir, file)`.
|
|
161
167
|
*
|
|
168
|
+
* 3. **State tracking** — exposes whether the initial index has completed (`ready`)
|
|
169
|
+
* and whether a build is in progress (`indexing`), so downstream tools
|
|
170
|
+
* (codebase-search, codebase-stats) can gate on it and UIs can show progress.
|
|
171
|
+
*
|
|
162
172
|
* `runIndexer` only reads `opts` (and ignores its `_ctx` parameter), so callers
|
|
163
173
|
* outside the agent loop pass a minimal stub cast to the expected shape — no
|
|
164
174
|
* live agent `Context` is required.
|
|
165
175
|
*/
|
|
166
176
|
|
|
177
|
+
/** True once the first full-project index has completed (success or failure). */
|
|
178
|
+
declare function isIndexReady(): boolean;
|
|
179
|
+
/** True while an index build is actively running. */
|
|
180
|
+
declare function isIndexing(): boolean;
|
|
181
|
+
/** Current indexing progress: { currentFile, totalFiles, ready, indexing }. */
|
|
182
|
+
declare function getIndexState(): {
|
|
183
|
+
ready: boolean;
|
|
184
|
+
indexing: boolean;
|
|
185
|
+
currentFile: number;
|
|
186
|
+
totalFiles: number;
|
|
187
|
+
lastError: string | null;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Optional callback fired on every lifecycle transition (started, progress,
|
|
191
|
+
* completed, failed). Plug into the event bus or a TUI dispatcher to surface
|
|
192
|
+
* the indexing state in real time.
|
|
193
|
+
*/
|
|
194
|
+
type IndexStateListener = (state: ReturnType<typeof getIndexState>) => void;
|
|
195
|
+
declare function onIndexStateChange(listener: IndexStateListener): () => void;
|
|
167
196
|
/** True when the file's extension maps to a language the indexer can parse. */
|
|
168
197
|
declare function isIndexableFile(filePath: string): boolean;
|
|
169
198
|
/**
|
|
170
199
|
* Run a full-project scan and await it. Used at session start and by the manual
|
|
171
200
|
* `/codebase-reindex` command. Incremental by default (unchanged files skipped
|
|
172
201
|
* via mtime, so repeat runs are cheap); pass `force` to clear and rebuild.
|
|
202
|
+
*
|
|
203
|
+
* Sets the global `_ready` flag on completion so downstream tools know the
|
|
204
|
+
* index is usable.
|
|
173
205
|
*/
|
|
174
206
|
declare function runStartupIndex(opts: {
|
|
175
207
|
projectRoot: string;
|
|
@@ -192,4 +224,4 @@ declare function enqueueReindex(opts: {
|
|
|
192
224
|
/** Cancel all pending debounced reindexes. For teardown / tests. */
|
|
193
225
|
declare function cancelPendingReindexes(): void;
|
|
194
226
|
|
|
195
|
-
export { type FileMeta as F, type IndexResult as I, type Ref as R, SCHEMA_VERSION as S, type FileSymbols as a, type IndexStats as b, type SearchResult as c, type Symbol as d, type SymbolKind as e, type SymbolLang as f, cancelPendingReindexes as g, codebaseIndexTool as h, codebaseSearchTool as i, codebaseStatsTool as j, enqueueReindex as k,
|
|
227
|
+
export { type FileMeta as F, type IndexResult as I, type Ref as R, SCHEMA_VERSION as S, type FileSymbols as a, type IndexStats as b, type SearchResult as c, type Symbol as d, type SymbolKind as e, type SymbolLang as f, cancelPendingReindexes as g, codebaseIndexTool as h, codebaseSearchTool as i, codebaseStatsTool as j, enqueueReindex as k, getIndexState as l, isIndexReady as m, isIndexableFile as n, isIndexing as o, onIndexStateChange as p, runStartupIndex as r };
|
package/dist/builtin.js
CHANGED
|
@@ -2676,7 +2676,41 @@ async function loadGitignoreMatcher(projectRoot) {
|
|
|
2676
2676
|
return compileGitignore(lines);
|
|
2677
2677
|
}
|
|
2678
2678
|
|
|
2679
|
+
// src/codebase-index/background-indexer.ts
|
|
2680
|
+
var _ready = false;
|
|
2681
|
+
var _indexing = false;
|
|
2682
|
+
var _currentFile = 0;
|
|
2683
|
+
var _totalFiles = 0;
|
|
2684
|
+
var _lastError = null;
|
|
2685
|
+
function setIndexReady() {
|
|
2686
|
+
_ready = true;
|
|
2687
|
+
}
|
|
2688
|
+
function getIndexState() {
|
|
2689
|
+
return {
|
|
2690
|
+
ready: _ready,
|
|
2691
|
+
indexing: _indexing,
|
|
2692
|
+
currentFile: _currentFile,
|
|
2693
|
+
totalFiles: _totalFiles,
|
|
2694
|
+
lastError: _lastError
|
|
2695
|
+
};
|
|
2696
|
+
}
|
|
2697
|
+
var _listeners = [];
|
|
2698
|
+
function emitState() {
|
|
2699
|
+
const state = getIndexState();
|
|
2700
|
+
for (const l of _listeners) l(state);
|
|
2701
|
+
}
|
|
2702
|
+
function _setIndexProgress(current, total) {
|
|
2703
|
+
_currentFile = current;
|
|
2704
|
+
_totalFiles = total;
|
|
2705
|
+
emitState();
|
|
2706
|
+
}
|
|
2707
|
+
Promise.resolve();
|
|
2708
|
+
|
|
2679
2709
|
// src/codebase-index/indexer.ts
|
|
2710
|
+
var YIELD_EVERY_N = 50;
|
|
2711
|
+
function yieldEventLoop() {
|
|
2712
|
+
return new Promise((resolve7) => setImmediate(resolve7));
|
|
2713
|
+
}
|
|
2680
2714
|
var DEFAULT_IGNORE = [
|
|
2681
2715
|
"node_modules",
|
|
2682
2716
|
".git",
|
|
@@ -2780,7 +2814,12 @@ async function runIndexer(_ctx, opts) {
|
|
|
2780
2814
|
if (!force) {
|
|
2781
2815
|
for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
|
|
2782
2816
|
}
|
|
2783
|
-
for (
|
|
2817
|
+
for (let fi = 0; fi < files.length; fi++) {
|
|
2818
|
+
const file = files[fi];
|
|
2819
|
+
_setIndexProgress(fi + 1, files.length);
|
|
2820
|
+
if (fi > 0 && fi % YIELD_EVERY_N === 0) {
|
|
2821
|
+
await yieldEventLoop();
|
|
2822
|
+
}
|
|
2784
2823
|
let stat10;
|
|
2785
2824
|
try {
|
|
2786
2825
|
stat10 = await fs12.stat(file);
|
|
@@ -2900,6 +2939,7 @@ var codebaseIndexTool = {
|
|
|
2900
2939
|
langs: input.langs,
|
|
2901
2940
|
indexDir: codebaseIndexDirOverride(ctx)
|
|
2902
2941
|
});
|
|
2942
|
+
setIndexReady();
|
|
2903
2943
|
return result;
|
|
2904
2944
|
}
|
|
2905
2945
|
};
|
|
@@ -3035,6 +3075,31 @@ var codebaseSearchTool = {
|
|
|
3035
3075
|
required: ["query"]
|
|
3036
3076
|
},
|
|
3037
3077
|
async execute(input, ctx) {
|
|
3078
|
+
const state = getIndexState();
|
|
3079
|
+
if (!state.ready) {
|
|
3080
|
+
return {
|
|
3081
|
+
results: [],
|
|
3082
|
+
total: 0,
|
|
3083
|
+
query: input.query,
|
|
3084
|
+
indexStatus: state.indexing ? `Indexing in progress (${state.currentFile}/${state.totalFiles} files) \u2014 retry in a moment.` : "Index not yet built. The codebase is being indexed at startup \u2014 search will be available shortly."
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
if (state.indexing) {
|
|
3088
|
+
return {
|
|
3089
|
+
results: [],
|
|
3090
|
+
total: 0,
|
|
3091
|
+
query: input.query,
|
|
3092
|
+
indexStatus: `Index refresh in progress (${state.currentFile}/${state.totalFiles} files). Results may be incomplete.`
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
if (state.lastError) {
|
|
3096
|
+
return {
|
|
3097
|
+
results: [],
|
|
3098
|
+
total: 0,
|
|
3099
|
+
query: input.query,
|
|
3100
|
+
indexStatus: `Index build failed: ${state.lastError}. Try /codebase-reindex.`
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
3038
3103
|
const store = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
3039
3104
|
try {
|
|
3040
3105
|
const limit = Math.min(input.limit ?? 20, 100);
|
|
@@ -3092,6 +3157,32 @@ var codebaseStatsTool = {
|
|
|
3092
3157
|
additionalProperties: false
|
|
3093
3158
|
},
|
|
3094
3159
|
async execute(_input, ctx) {
|
|
3160
|
+
const idxState = getIndexState();
|
|
3161
|
+
if (!idxState.ready) {
|
|
3162
|
+
return {
|
|
3163
|
+
totalSymbols: 0,
|
|
3164
|
+
totalFiles: 0,
|
|
3165
|
+
byLang: {},
|
|
3166
|
+
byKind: {},
|
|
3167
|
+
lastIndexed: null,
|
|
3168
|
+
sizeBytes: 0,
|
|
3169
|
+
indexPath: "",
|
|
3170
|
+
version: SCHEMA_VERSION,
|
|
3171
|
+
indexStatus: idxState.indexing ? `Indexing in progress (${idxState.currentFile}/${idxState.totalFiles} files).` : "Index not yet built."
|
|
3172
|
+
};
|
|
3173
|
+
}
|
|
3174
|
+
if (idxState.indexing) {
|
|
3175
|
+
const store2 = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
3176
|
+
try {
|
|
3177
|
+
const stats = store2.getStats();
|
|
3178
|
+
return {
|
|
3179
|
+
...stats,
|
|
3180
|
+
indexStatus: `Index refresh in progress (${idxState.currentFile}/${idxState.totalFiles} files). Stats may be incomplete.`
|
|
3181
|
+
};
|
|
3182
|
+
} finally {
|
|
3183
|
+
store2.close();
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3095
3186
|
const store = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
3096
3187
|
try {
|
|
3097
3188
|
const stats = store.getStats();
|
|
@@ -6589,9 +6680,10 @@ var todoTool = {
|
|
|
6589
6680
|
name: "todo",
|
|
6590
6681
|
category: "Session",
|
|
6591
6682
|
description: "Manage the session-level todo list. This is the primary mechanism for tracking multi-step work. The list is fully replaced on every call (not appended).",
|
|
6592
|
-
usageHint: "BEST PRACTICE for complex tasks:\n- At the beginning of a non-trivial task, create a clear todo list with specific, actionable items.\n- Only **one** item should be `in_progress` at any time.\n- Update the list frequently as work progresses (mark items done, add new ones, change status).\n- The system and user can see this list, so keep it honest and up-to-date.\nThis tool is extremely valuable for maintaining focus and giving the user visibility into your plan.",
|
|
6683
|
+
usageHint: "BEST PRACTICE for complex tasks:\n- At the beginning of a non-trivial task, create a clear todo list with specific, actionable items.\n- Only **one** item should be `in_progress` at any time.\n- Update the list frequently as work progresses (mark items done, add new ones, change status).\n- **Re-order items** to reflect current priorities \u2014 the full list is replaced each call, so item order is entirely under your control.\n- When all items are completed the board auto-clears \u2014 you do NOT need to send an empty list.\n- The system and user can see this list, so keep it honest and up-to-date.\nThis tool is extremely valuable for maintaining focus and giving the user visibility into your plan.",
|
|
6593
6684
|
permission: "auto",
|
|
6594
6685
|
mutating: false,
|
|
6686
|
+
// mutates only conversation state (ctx.todos), not external state — no confirmation needed
|
|
6595
6687
|
timeoutMs: 1e3,
|
|
6596
6688
|
inputSchema: {
|
|
6597
6689
|
type: "object",
|