@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/pack.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 (const file of files) {
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",