@lucas-bur/pix 0.3.0 → 0.5.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/README.md +36 -20
- package/dist/index.mjs +102 -86
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
# @lucas-bur/pix
|
|
2
2
|
|
|
3
|
-
[](https://github.com/Lucas-Bur/pix/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/Lucas-Bur/pix)
|
|
5
5
|
[](https://www.npmjs.com/package/@lucas-bur/pix)
|
|
6
6
|
[](https://www.npmjs.com/package/@lucas-bur/pix)
|
|
7
|
-
[](https://github.com/fallow-rs/fallow)
|
|
8
7
|
|
|
9
|
-
Lightweight local semantic project indexer
|
|
10
|
-
|
|
11
|
-
Zero external services, 100% local + offline. Installs as a devDependency and provides agent-ready structured JSON output.
|
|
12
|
-
|
|
13
|
-
## Status
|
|
14
|
-
|
|
15
|
-
MVP in development. See [CONTEXT.md](./CONTEXT.md) for architecture decisions and [.scratch/pix-mvp/PRD.md](./.scratch/pix-mvp/PRD.md) for the product requirements.
|
|
8
|
+
Lightweight local semantic project indexer. Zero external services, 100% local and offline. Installs as a devDependency and provides agent-ready structured JSON output.
|
|
16
9
|
|
|
17
10
|
## Quick Start
|
|
18
11
|
|
|
@@ -23,23 +16,46 @@ pix index
|
|
|
23
16
|
pix query "authentication middleware"
|
|
24
17
|
```
|
|
25
18
|
|
|
26
|
-
##
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
| Command | Description | JSON flag |
|
|
22
|
+
| -------------------- | ------------------------------------------- | --------- |
|
|
23
|
+
| `pix init` | Create `.pix/config.json` with defaults | `--json` |
|
|
24
|
+
| `pix index` | Scan, chunk, embed, and store project files | `--json` |
|
|
25
|
+
| `pix query "<text>"` | Semantic search via cosine similarity | `--json` |
|
|
26
|
+
| `pix status` | Show index statistics | `--json` |
|
|
27
|
+
| `pix reset` | Delete index files (chunks + vectors) | `--json` |
|
|
28
|
+
|
|
29
|
+
All commands support `--json` for structured output on stdout — ideal for piping to AI agents.
|
|
30
|
+
|
|
31
|
+
## Agent-Ready Output
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
```bash
|
|
34
|
+
$ pix status --json
|
|
35
|
+
{"chunks":59,"files":37,"model":"Xenova/all-MiniLM-L6-v2","lastIndex":1715030400000,"totalLines":1260,"byteSize":16128}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Errors use the same structured format:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{ "error": true, "code": "CONFIG_MISSING", "message": "No .pix/config.json found" }
|
|
42
|
+
```
|
|
29
43
|
|
|
30
|
-
|
|
44
|
+
## Architecture
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
- `fallow audit --summary` — Check only changed files (used in pre-commit hook)
|
|
46
|
+
pix follows hexagonal architecture (ports and adapters) with three layers:
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
- **Domain** (`src/domain/`) — Pure types, entities, port declarations
|
|
49
|
+
- **Application** (`src/application/`) — Use cases orchestrating business logic
|
|
50
|
+
- **Infrastructure** (`src/services/`) — Concrete adapters (ONNX, filesystem, ffmpeg scanning)
|
|
36
51
|
|
|
37
|
-
|
|
52
|
+
See [CONTEXT.md](./CONTEXT.md) for architecture decisions and [docs/adr/](./docs/adr/) for decision records.
|
|
38
53
|
|
|
39
|
-
|
|
40
|
-
2. `fallow audit --summary` — Audits changed files for quality issues
|
|
54
|
+
## Quality
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
- `vp check` — Format, lint, type-check
|
|
57
|
+
- `vp test` — Unit and integration tests
|
|
58
|
+
- `vp run lint:fallow` — Dead code, duplication, complexity analysis
|
|
43
59
|
|
|
44
60
|
## License
|
|
45
61
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { NodeContext, NodeRuntime } from "@effect/platform-node";
|
|
4
|
-
import { Clock, Context, Data, Effect, Layer, Option } from "effect";
|
|
5
|
-
import { Args, Command, Options } from "@effect/cli";
|
|
4
|
+
import { Clock, Console, Context, Data, Effect, Layer, Option } from "effect";
|
|
5
|
+
import { Args, CliConfig, Command, Options } from "@effect/cli";
|
|
6
6
|
import crypto from "node:crypto";
|
|
7
7
|
import { FileSystem } from "@effect/platform";
|
|
8
8
|
import { env } from "@huggingface/transformers";
|
|
9
|
-
import fg from "fast-glob";
|
|
10
9
|
import ignore from "ignore";
|
|
11
10
|
//#region src/domain/ports.ts
|
|
12
11
|
var ConfigStore = class extends Context.Tag("ConfigStore")() {};
|
|
@@ -68,15 +67,13 @@ var IndexProject = class extends Effect.Service()("IndexProject", {
|
|
|
68
67
|
const embeddings = yield* embedder.batch(texts);
|
|
69
68
|
yield* vectorStore.store(allChunks, embeddings);
|
|
70
69
|
const dims = embeddings[0]?.dims ?? 384;
|
|
71
|
-
const byteSize = embeddings.length * dims * 4;
|
|
72
|
-
yield* Effect.logInfo(`Indexed ${totalChunks} chunks from ${totalFiles} files.`);
|
|
73
70
|
return {
|
|
74
71
|
success: true,
|
|
75
72
|
stats: {
|
|
76
73
|
chunks: totalChunks,
|
|
77
74
|
files: totalFiles,
|
|
78
75
|
totalLines,
|
|
79
|
-
byteSize
|
|
76
|
+
byteSize: embeddings.length * dims * 4
|
|
80
77
|
}
|
|
81
78
|
};
|
|
82
79
|
});
|
|
@@ -135,6 +132,26 @@ var ResetIndex = class extends Effect.Service()("ResetIndex", {
|
|
|
135
132
|
})
|
|
136
133
|
}) {};
|
|
137
134
|
//#endregion
|
|
135
|
+
//#region src/lib/error-format.ts
|
|
136
|
+
const errorCodes = {
|
|
137
|
+
ConfigError: "CONFIG_MISSING",
|
|
138
|
+
PlatformError: "PLATFORM_ERROR"
|
|
139
|
+
};
|
|
140
|
+
const messageFromError = (error) => {
|
|
141
|
+
if (typeof error === "string") return error;
|
|
142
|
+
if (error && typeof error === "object" && "message" in error) return String(error.message);
|
|
143
|
+
return "Unknown error";
|
|
144
|
+
};
|
|
145
|
+
const codeFromError = (error) => {
|
|
146
|
+
if (error && typeof error === "object" && "_tag" in error) return errorCodes[String(error._tag)] ?? "UNKNOWN";
|
|
147
|
+
return "UNKNOWN";
|
|
148
|
+
};
|
|
149
|
+
const formatError = (error) => JSON.stringify({
|
|
150
|
+
error: true,
|
|
151
|
+
code: codeFromError(error),
|
|
152
|
+
message: messageFromError(error)
|
|
153
|
+
});
|
|
154
|
+
//#endregion
|
|
138
155
|
//#region src/commands/index-cmd.ts
|
|
139
156
|
/** CLI command: pix index [--force] [--verbose] [--json] */
|
|
140
157
|
const indexCommand = Command.make("index", {
|
|
@@ -142,39 +159,28 @@ const indexCommand = Command.make("index", {
|
|
|
142
159
|
verbose: Options.boolean("verbose").pipe(Options.withDefault(false)),
|
|
143
160
|
json: Options.boolean("json").pipe(Options.withDefault(false))
|
|
144
161
|
}, ({ force, verbose, json }) => Effect.gen(function* () {
|
|
145
|
-
if (force) yield* Effect.logInfo(
|
|
146
|
-
if (verbose) yield* Effect.logInfo(
|
|
162
|
+
if (force && !json) yield* Effect.logInfo("--force is currently not implemented and only a placeholder.");
|
|
163
|
+
if (verbose && !json) yield* Effect.logInfo("--verbose is currently not implemented and only a placeholder.");
|
|
147
164
|
const startTime = Date.now();
|
|
148
165
|
const result = yield* IndexProject.index().pipe(Effect.either);
|
|
149
|
-
if (result._tag === "Left")
|
|
150
|
-
const error = result.left;
|
|
151
|
-
const message = error.message ?? String(error);
|
|
152
|
-
yield* Effect.sync(() => {
|
|
153
|
-
console.log(JSON.stringify({ error: message }));
|
|
154
|
-
});
|
|
155
|
-
return yield* Effect.fail(error);
|
|
156
|
-
}
|
|
166
|
+
if (result._tag === "Left") return yield* Effect.fail(result.left);
|
|
157
167
|
const duration = `${((Date.now() - startTime) / 1e3).toFixed(1)}s`;
|
|
158
|
-
if (json) return yield*
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}));
|
|
164
|
-
});
|
|
168
|
+
if (json) return yield* Console.log(JSON.stringify({
|
|
169
|
+
chunks: result.right.stats.chunks,
|
|
170
|
+
files: result.right.stats.files,
|
|
171
|
+
duration
|
|
172
|
+
}));
|
|
165
173
|
yield* Effect.logInfo(`Indexed ${result.right.stats.chunks} chunks from ${result.right.stats.files} files in ${duration}.`);
|
|
166
|
-
}));
|
|
174
|
+
}).pipe(Effect.tapError((error) => Console.log(formatError(error)))));
|
|
167
175
|
//#endregion
|
|
168
176
|
//#region src/commands/init.ts
|
|
169
177
|
/** CLI command: pix init [--json] */
|
|
170
178
|
const initCommand = Command.make("init", { json: Options.boolean("json").pipe(Options.withDefault(false)) }, ({ json }) => Effect.gen(function* () {
|
|
171
179
|
const result = yield* InitProject.init();
|
|
172
|
-
if (json) return yield*
|
|
173
|
-
console.log(JSON.stringify(result, null, 2));
|
|
174
|
-
});
|
|
180
|
+
if (json) return yield* Console.log(JSON.stringify(result, null, 2));
|
|
175
181
|
yield* Effect.logInfo("Created .pix/config.json with default settings.");
|
|
176
182
|
yield* Effect.logInfo("Reminder: Add `.pix` to your `.gitignore` file to avoid committing the index.");
|
|
177
|
-
}));
|
|
183
|
+
}).pipe(Effect.tapError((error) => Console.log(formatError(error)))));
|
|
178
184
|
//#endregion
|
|
179
185
|
//#region src/commands/query.ts
|
|
180
186
|
const DEFAULT_TOP_K = 5;
|
|
@@ -214,7 +220,7 @@ const queryCommand = Command.make("query", {
|
|
|
214
220
|
const clamped = clampTopK(topK);
|
|
215
221
|
if (clamped.clamped) yield* Effect.logDebug(`topK clamped from ${topK} to ${clamped.value}`);
|
|
216
222
|
const results = yield* QueryProject.queryProject(queryText, clamped.value);
|
|
217
|
-
if (json)
|
|
223
|
+
if (json) {
|
|
218
224
|
const output = results.map((r) => ({
|
|
219
225
|
score: r.score,
|
|
220
226
|
file: r.file,
|
|
@@ -224,17 +230,31 @@ const queryCommand = Command.make("query", {
|
|
|
224
230
|
...ctxLines > 0 && r.contextBefore && { contextBefore: r.contextBefore },
|
|
225
231
|
...ctxLines > 0 && r.contextAfter && { contextAfter: r.contextAfter }
|
|
226
232
|
}));
|
|
227
|
-
|
|
228
|
-
}
|
|
233
|
+
return yield* Console.log(JSON.stringify(output, null, 2));
|
|
234
|
+
}
|
|
229
235
|
if (results.length === 0) {
|
|
230
236
|
yield* Effect.logInfo("No results found");
|
|
231
237
|
return;
|
|
232
238
|
}
|
|
233
|
-
for (const result of results)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
}));
|
|
239
|
+
for (const result of results) {
|
|
240
|
+
yield* Console.log(formatResult(result));
|
|
241
|
+
yield* Console.log("---");
|
|
242
|
+
}
|
|
243
|
+
}).pipe(Effect.tapError((error) => Console.log(formatError(error)))));
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/lib/format.ts
|
|
246
|
+
/** Format byte count as human-readable string (e.g. "1.5 MB") */
|
|
247
|
+
const formatBytes = (bytes) => {
|
|
248
|
+
if (bytes === 0) return "0 B";
|
|
249
|
+
const units = [
|
|
250
|
+
"B",
|
|
251
|
+
"KB",
|
|
252
|
+
"MB",
|
|
253
|
+
"GB"
|
|
254
|
+
];
|
|
255
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
256
|
+
return `${(bytes / 1024 ** i).toFixed(1)} ${units[i]}`;
|
|
257
|
+
};
|
|
238
258
|
//#endregion
|
|
239
259
|
//#region src/commands/reset.ts
|
|
240
260
|
/** CLI command: pix reset [--json] */
|
|
@@ -242,15 +262,13 @@ const resetCommand = Command.make("reset", { json: Options.boolean("json").pipe(
|
|
|
242
262
|
const start = yield* Clock.currentTimeMillis;
|
|
243
263
|
const result = yield* ResetIndex.reset();
|
|
244
264
|
const elapsedMs = (yield* Clock.currentTimeMillis) - start;
|
|
245
|
-
if (json) return yield*
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}));
|
|
253
|
-
});
|
|
265
|
+
if (json) return yield* Console.log(JSON.stringify({
|
|
266
|
+
status: "ok",
|
|
267
|
+
deletedChunks: result.deletedChunks,
|
|
268
|
+
deletedVectors: result.deletedVectors,
|
|
269
|
+
freedBytes: result.freedBytes,
|
|
270
|
+
elapsedMs
|
|
271
|
+
}));
|
|
254
272
|
if (!result.deletedChunks && !result.deletedVectors) {
|
|
255
273
|
yield* Effect.logInfo("Nothing to reset.");
|
|
256
274
|
return;
|
|
@@ -259,48 +277,22 @@ const resetCommand = Command.make("reset", { json: Options.boolean("json").pipe(
|
|
|
259
277
|
if (result.deletedChunks) parts.push("chunks.jsonl");
|
|
260
278
|
if (result.deletedVectors) parts.push("vectors.bin");
|
|
261
279
|
yield* Effect.logInfo(`Deleted: ${parts.join(", ")}`);
|
|
262
|
-
yield* Effect.logInfo(`Freed: ${formatBytes
|
|
280
|
+
yield* Effect.logInfo(`Freed: ${formatBytes(result.freedBytes)}`);
|
|
263
281
|
yield* Effect.logInfo(`Time: ${elapsedMs}ms`);
|
|
264
|
-
}));
|
|
265
|
-
/** Format byte count as human-readable string (e.g. "1.5 MB") */
|
|
266
|
-
const formatBytes$1 = (bytes) => {
|
|
267
|
-
if (bytes === 0) return "0 B";
|
|
268
|
-
const units = [
|
|
269
|
-
"B",
|
|
270
|
-
"KB",
|
|
271
|
-
"MB",
|
|
272
|
-
"GB"
|
|
273
|
-
];
|
|
274
|
-
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
275
|
-
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${units[i]}`;
|
|
276
|
-
};
|
|
282
|
+
}).pipe(Effect.tapError((error) => Console.log(formatError(error)))));
|
|
277
283
|
//#endregion
|
|
278
284
|
//#region src/commands/status.ts
|
|
279
285
|
/** CLI command: pix status [--json] */
|
|
280
286
|
const statusCommand = Command.make("status", { json: Options.boolean("json").pipe(Options.withDefault(false)) }, ({ json }) => Effect.gen(function* () {
|
|
281
287
|
const result = yield* GetStatus.getStatus();
|
|
282
|
-
if (json) return yield*
|
|
283
|
-
console.log(JSON.stringify(result, null, 2));
|
|
284
|
-
});
|
|
288
|
+
if (json) return yield* Console.log(JSON.stringify(result, null, 2));
|
|
285
289
|
const lastIndexStr = result.lastIndex > 0 ? new Date(result.lastIndex).toISOString() : "never";
|
|
286
290
|
yield* Effect.logInfo(`Indexed: ${result.chunks} chunks across ${result.files} files`);
|
|
287
291
|
yield* Effect.logInfo(`Model: ${result.model || "none"}`);
|
|
288
292
|
yield* Effect.logInfo(`Total lines: ${result.totalLines.toLocaleString()}`);
|
|
289
293
|
yield* Effect.logInfo(`Index size: ${formatBytes(result.byteSize)}`);
|
|
290
294
|
yield* Effect.logInfo(`Last indexed: ${lastIndexStr}`);
|
|
291
|
-
}));
|
|
292
|
-
/** Format byte count as human-readable string (e.g. "1.5 MB") */
|
|
293
|
-
const formatBytes = (bytes) => {
|
|
294
|
-
if (bytes === 0) return "0 B";
|
|
295
|
-
const units = [
|
|
296
|
-
"B",
|
|
297
|
-
"KB",
|
|
298
|
-
"MB",
|
|
299
|
-
"GB"
|
|
300
|
-
];
|
|
301
|
-
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
302
|
-
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${units[i]}`;
|
|
303
|
-
};
|
|
295
|
+
}).pipe(Effect.tapError((error) => Console.log(formatError(error)))));
|
|
304
296
|
//#endregion
|
|
305
297
|
//#region src/cli.ts
|
|
306
298
|
const VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
@@ -314,10 +306,10 @@ const pix = Command.make("pix", {}, () => Effect.gen(function* () {
|
|
|
314
306
|
queryCommand,
|
|
315
307
|
resetCommand
|
|
316
308
|
]));
|
|
317
|
-
const cli = Command.run(pix, {
|
|
309
|
+
const cli = (args) => Command.run(pix, {
|
|
318
310
|
name: "pix",
|
|
319
311
|
version: VERSION
|
|
320
|
-
});
|
|
312
|
+
})(args).pipe(Effect.provide(CliConfig.layer({ showTypes: false })));
|
|
321
313
|
//#endregion
|
|
322
314
|
//#region src/services/chunker.ts
|
|
323
315
|
const MIN_CHUNK_CHARS = 20;
|
|
@@ -451,9 +443,16 @@ const make$2 = Effect.gen(function* () {
|
|
|
451
443
|
const OnnxEmbedderLive = Layer.effect(Embedder, make$2);
|
|
452
444
|
//#endregion
|
|
453
445
|
//#region src/services/scanner.ts
|
|
446
|
+
const ALWAYS_IGNORE = new Set([
|
|
447
|
+
".pix",
|
|
448
|
+
"node_modules",
|
|
449
|
+
".git",
|
|
450
|
+
"dist",
|
|
451
|
+
"build",
|
|
452
|
+
".next"
|
|
453
|
+
]);
|
|
454
454
|
const make$1 = Effect.gen(function* () {
|
|
455
455
|
const fs = yield* FileSystem.FileSystem;
|
|
456
|
-
/** Loads all gitignore patterns from .gitignore files in the repo. */
|
|
457
456
|
const loadGitignoreRules = Effect.gen(function* () {
|
|
458
457
|
const ig = ignore();
|
|
459
458
|
const cwd = process.cwd();
|
|
@@ -466,13 +465,30 @@ const make$1 = Effect.gen(function* () {
|
|
|
466
465
|
}
|
|
467
466
|
return ig;
|
|
468
467
|
}).pipe(Effect.catchAll(() => Effect.succeed(ignore())));
|
|
468
|
+
const walk = (dir, extensions) => Effect.gen(function* () {
|
|
469
|
+
const entries = yield* fs.readDirectory(dir).pipe(Effect.catchAll(() => Effect.succeed([])));
|
|
470
|
+
let results = [];
|
|
471
|
+
for (const entry of entries) {
|
|
472
|
+
if (ALWAYS_IGNORE.has(entry)) continue;
|
|
473
|
+
const fullPath = `${dir}/${entry}`;
|
|
474
|
+
const info = yield* fs.stat(fullPath).pipe(Effect.catchAll(() => Effect.succeed(null)));
|
|
475
|
+
if (!info) continue;
|
|
476
|
+
if (info.type === "Directory") {
|
|
477
|
+
const subResults = yield* walk(fullPath, extensions);
|
|
478
|
+
results.push(...subResults);
|
|
479
|
+
} else if (info.type === "File") {
|
|
480
|
+
const dotIndex = entry.lastIndexOf(".");
|
|
481
|
+
if (dotIndex === -1) continue;
|
|
482
|
+
const ext = entry.slice(dotIndex);
|
|
483
|
+
if (extensions.has(ext)) results.push(fullPath);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return results;
|
|
487
|
+
});
|
|
469
488
|
const scanFiles = (extensions) => Effect.gen(function* () {
|
|
470
489
|
const ig = yield* loadGitignoreRules;
|
|
471
490
|
const cwd = process.cwd();
|
|
472
|
-
const
|
|
473
|
-
const relativePaths = (yield* Effect.tryPromise(() => fg(pattern, { dot: false })).pipe(Effect.catchAll(() => Effect.succeed([])))).map((p) => {
|
|
474
|
-
return p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;
|
|
475
|
-
});
|
|
491
|
+
const relativePaths = (yield* walk(cwd, new Set(extensions))).map((p) => p.startsWith(cwd) ? p.slice(cwd.length + 1) : p);
|
|
476
492
|
return ig.filter(relativePaths).map((p) => `${cwd}/${p}`);
|
|
477
493
|
});
|
|
478
494
|
return { scanFiles };
|
|
@@ -587,7 +603,7 @@ const make = Effect.gen(function* () {
|
|
|
587
603
|
const model = readModelFromChunks(lines);
|
|
588
604
|
const totalLines = countTotalLines(lines);
|
|
589
605
|
const vectorsStat = yield* fs.stat(VECTORS_FILE).pipe(Effect.catchAll(() => Effect.succeed(null)));
|
|
590
|
-
const byteSize = vectorsStat && "size" in vectorsStat ? vectorsStat.size : 0;
|
|
606
|
+
const byteSize = vectorsStat && "size" in vectorsStat ? Number(vectorsStat.size) : 0;
|
|
591
607
|
return {
|
|
592
608
|
chunks,
|
|
593
609
|
files,
|
|
@@ -603,13 +619,13 @@ const make = Effect.gen(function* () {
|
|
|
603
619
|
let freedBytes = 0;
|
|
604
620
|
if (yield* fs.exists(CHUNKS_FILE)) {
|
|
605
621
|
const stat = yield* fs.stat(CHUNKS_FILE);
|
|
606
|
-
freedBytes += stat && "size" in stat ? stat.size : 0;
|
|
622
|
+
freedBytes += stat && "size" in stat ? Number(stat.size) : 0;
|
|
607
623
|
yield* fs.remove(CHUNKS_FILE);
|
|
608
624
|
deletedChunks = true;
|
|
609
625
|
}
|
|
610
626
|
if (yield* fs.exists(VECTORS_FILE)) {
|
|
611
627
|
const stat = yield* fs.stat(VECTORS_FILE);
|
|
612
|
-
freedBytes += stat && "size" in stat ? stat.size : 0;
|
|
628
|
+
freedBytes += stat && "size" in stat ? Number(stat.size) : 0;
|
|
613
629
|
yield* fs.remove(VECTORS_FILE);
|
|
614
630
|
deletedVectors = true;
|
|
615
631
|
}
|
|
@@ -634,6 +650,6 @@ const ChunkerLayer = ChunkerLive.pipe(Layer.provide(ServicesLayer));
|
|
|
634
650
|
const InfraLayer = Layer.mergeAll(ServicesLayer, ChunkerLayer).pipe(Layer.provide(NodeContext.layer));
|
|
635
651
|
const UseCaseLayer = Layer.mergeAll(InitProject.Default, GetStatus.Default, QueryProject.Default, IndexProject.Default, ResetIndex.Default);
|
|
636
652
|
const AppLayer = Layer.merge(UseCaseLayer.pipe(Layer.provide(InfraLayer)), NodeContext.layer);
|
|
637
|
-
cli(process.argv).pipe(Effect.provide(AppLayer), NodeRuntime.runMain);
|
|
653
|
+
cli(process.argv).pipe(Effect.provide(AppLayer), NodeRuntime.runMain({ disableErrorReporting: true }));
|
|
638
654
|
//#endregion
|
|
639
655
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucas-bur/pix",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Lightweight local semantic project indexer",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -39,8 +39,13 @@
|
|
|
39
39
|
"test": "vp test",
|
|
40
40
|
"test:coverage": "vp test --coverage",
|
|
41
41
|
"check": "vp check",
|
|
42
|
-
"ci": "vp check && vp test
|
|
43
|
-
"lint:
|
|
42
|
+
"ci": "vp run check && vp run test:coverage && vp run build && vp run lint:effect && vp run lint:fallow",
|
|
43
|
+
"lint:effect": "effect-language-service diagnostics --project tsconfig.json --format pretty --strict",
|
|
44
|
+
"lint:effect:ci": "effect-language-service diagnostics --project tsconfig.json --format github-actions --strict",
|
|
45
|
+
"lint:effect:agent": "effect-language-service diagnostics --project tsconfig.json --format json --strict",
|
|
46
|
+
"lint:fallow": "fallow",
|
|
47
|
+
"lint:fallow:ci": "vpx fallow audit --base main --format badge",
|
|
48
|
+
"lint:fallow:agent": "fallow --format json",
|
|
44
49
|
"fallow": "fallow",
|
|
45
50
|
"prepublishOnly": "vp run build",
|
|
46
51
|
"pix": ""
|
|
@@ -51,7 +56,6 @@
|
|
|
51
56
|
"@effect/platform-node": "^0.106.0",
|
|
52
57
|
"@huggingface/transformers": "^4.2.0",
|
|
53
58
|
"effect": "^3.21.2",
|
|
54
|
-
"fast-glob": "^3.3.3",
|
|
55
59
|
"ignore": "^7.0.5"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
@@ -59,6 +63,7 @@
|
|
|
59
63
|
"@types/node": "^25.5.0",
|
|
60
64
|
"@typescript/native-preview": "7.0.0-dev.20260328.1",
|
|
61
65
|
"@vitest/coverage-v8": "^4.1.6",
|
|
66
|
+
"effect-memfs": "^0.8.0",
|
|
62
67
|
"fallow": "^2.65.0",
|
|
63
68
|
"typescript": "^6.0.2",
|
|
64
69
|
"vite-plus": "^0.1.14"
|