ctxloom-pro 1.3.0 → 1.4.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 +6 -1
- package/apps/dashboard/dist/server/index.js +169 -102
- package/dist/budgetStats-TURA232F.js +116 -0
- package/dist/chunk-5I6CJITG.js +99 -0
- package/dist/{chunk-Q2KTZNNU.js → chunk-7GZVGIQL.js} +1429 -71
- package/dist/eventCollector-QSRBVUDF.js +18 -0
- package/dist/index.js +56 -9
- package/dist/{src-HNXOOOWF.js → src-CH2OSHKF.js} +31 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,8 @@ The full first-run flow is **one install + one trial + one init per project.** E
|
|
|
47
47
|
npm install -g ctxloom-pro
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
> **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.4.0`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
|
|
51
|
+
|
|
50
52
|
### 2 — Start your free trial (once per email)
|
|
51
53
|
|
|
52
54
|
```bash
|
|
@@ -341,7 +343,10 @@ jobs:
|
|
|
341
343
|
- uses: actions/checkout@v4
|
|
342
344
|
- uses: actions/setup-node@v4
|
|
343
345
|
with: { node-version: '20' }
|
|
344
|
-
|
|
346
|
+
# Exact pin (not `@^1`) so future CLI releases that add/remove MCP
|
|
347
|
+
# tools don't silently desync your reviewer-agent specs. Bump on
|
|
348
|
+
# every release; see CHANGELOG.md for the live version table.
|
|
349
|
+
- run: npm install -g ctxloom-pro@1.4.0
|
|
345
350
|
- run: ctxloom index
|
|
346
351
|
- run: ctxloom rules check --json
|
|
347
352
|
```
|
|
@@ -166,12 +166,12 @@ var init_VectorStore = __esm({
|
|
|
166
166
|
// server/index.ts
|
|
167
167
|
import express from "express";
|
|
168
168
|
import cors from "cors";
|
|
169
|
-
import
|
|
170
|
-
import
|
|
169
|
+
import path46 from "path";
|
|
170
|
+
import fs34 from "fs";
|
|
171
171
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
172
172
|
|
|
173
173
|
// server/loader.ts
|
|
174
|
-
import
|
|
174
|
+
import path40 from "path";
|
|
175
175
|
|
|
176
176
|
// ../../packages/core/src/graph/DependencyGraph.ts
|
|
177
177
|
import fs7 from "fs";
|
|
@@ -3181,8 +3181,8 @@ var CoChangeIndex = class _CoChangeIndex {
|
|
|
3181
3181
|
if (event.isBulk || event.isMerge) return;
|
|
3182
3182
|
const paths = event.files.map((f) => f.path);
|
|
3183
3183
|
if (paths.length === 0) return;
|
|
3184
|
-
for (const
|
|
3185
|
-
this.nodeCounts.set(
|
|
3184
|
+
for (const path47 of paths) {
|
|
3185
|
+
this.nodeCounts.set(path47, (this.nodeCounts.get(path47) ?? 0) + 1);
|
|
3186
3186
|
}
|
|
3187
3187
|
for (let i = 0; i < paths.length; i++) {
|
|
3188
3188
|
for (let j = i + 1; j < paths.length; j++) {
|
|
@@ -3329,8 +3329,8 @@ var ChurnIndex = class _ChurnIndex {
|
|
|
3329
3329
|
*/
|
|
3330
3330
|
snapshot() {
|
|
3331
3331
|
const nodes = {};
|
|
3332
|
-
for (const [
|
|
3333
|
-
nodes[
|
|
3332
|
+
for (const [path47, raw] of this.nodes) {
|
|
3333
|
+
nodes[path47] = {
|
|
3334
3334
|
commits: raw.commits,
|
|
3335
3335
|
churnLines: raw.churnLines,
|
|
3336
3336
|
bugCommits: raw.bugCommits,
|
|
@@ -3345,8 +3345,8 @@ var ChurnIndex = class _ChurnIndex {
|
|
|
3345
3345
|
*/
|
|
3346
3346
|
static load(s) {
|
|
3347
3347
|
const idx = new _ChurnIndex();
|
|
3348
|
-
for (const [
|
|
3349
|
-
idx.nodes.set(
|
|
3348
|
+
for (const [path47, raw] of Object.entries(s.nodes)) {
|
|
3349
|
+
idx.nodes.set(path47, {
|
|
3350
3350
|
commits: raw.commits,
|
|
3351
3351
|
churnLines: raw.churnLines,
|
|
3352
3352
|
bugCommits: raw.bugCommits,
|
|
@@ -3359,8 +3359,8 @@ var ChurnIndex = class _ChurnIndex {
|
|
|
3359
3359
|
// -------------------------------------------------------------------------
|
|
3360
3360
|
// Private helpers
|
|
3361
3361
|
// -------------------------------------------------------------------------
|
|
3362
|
-
getOrCreate(
|
|
3363
|
-
const existing = this.nodes.get(
|
|
3362
|
+
getOrCreate(path47) {
|
|
3363
|
+
const existing = this.nodes.get(path47);
|
|
3364
3364
|
if (existing !== void 0) return existing;
|
|
3365
3365
|
const fresh = {
|
|
3366
3366
|
commits: 0,
|
|
@@ -3369,7 +3369,7 @@ var ChurnIndex = class _ChurnIndex {
|
|
|
3369
3369
|
authorCounts: {},
|
|
3370
3370
|
lastTouch: 0
|
|
3371
3371
|
};
|
|
3372
|
-
this.nodes.set(
|
|
3372
|
+
this.nodes.set(path47, fresh);
|
|
3373
3373
|
return fresh;
|
|
3374
3374
|
}
|
|
3375
3375
|
};
|
|
@@ -3450,12 +3450,12 @@ var OwnershipIndex = class _OwnershipIndex {
|
|
|
3450
3450
|
*/
|
|
3451
3451
|
snapshot() {
|
|
3452
3452
|
const nodes = {};
|
|
3453
|
-
for (const [
|
|
3453
|
+
for (const [path47, raw] of this.nodes) {
|
|
3454
3454
|
const authorWeights = {};
|
|
3455
3455
|
for (const [email, entry] of Object.entries(raw.authorWeights)) {
|
|
3456
3456
|
authorWeights[email] = { ...entry };
|
|
3457
3457
|
}
|
|
3458
|
-
nodes[
|
|
3458
|
+
nodes[path47] = { authorWeights, lastTouch: raw.lastTouch };
|
|
3459
3459
|
}
|
|
3460
3460
|
return { version: 1, nodes };
|
|
3461
3461
|
}
|
|
@@ -3464,23 +3464,23 @@ var OwnershipIndex = class _OwnershipIndex {
|
|
|
3464
3464
|
*/
|
|
3465
3465
|
static load(s) {
|
|
3466
3466
|
const idx = new _OwnershipIndex();
|
|
3467
|
-
for (const [
|
|
3467
|
+
for (const [path47, raw] of Object.entries(s.nodes)) {
|
|
3468
3468
|
const authorWeights = {};
|
|
3469
3469
|
for (const [email, entry] of Object.entries(raw.authorWeights)) {
|
|
3470
3470
|
authorWeights[email] = { ...entry };
|
|
3471
3471
|
}
|
|
3472
|
-
idx.nodes.set(
|
|
3472
|
+
idx.nodes.set(path47, { authorWeights, lastTouch: raw.lastTouch });
|
|
3473
3473
|
}
|
|
3474
3474
|
return idx;
|
|
3475
3475
|
}
|
|
3476
3476
|
// -------------------------------------------------------------------------
|
|
3477
3477
|
// Private helpers
|
|
3478
3478
|
// -------------------------------------------------------------------------
|
|
3479
|
-
getOrCreate(
|
|
3480
|
-
const existing = this.nodes.get(
|
|
3479
|
+
getOrCreate(path47) {
|
|
3480
|
+
const existing = this.nodes.get(path47);
|
|
3481
3481
|
if (existing !== void 0) return existing;
|
|
3482
3482
|
const fresh = { authorWeights: {}, lastTouch: 0 };
|
|
3483
|
-
this.nodes.set(
|
|
3483
|
+
this.nodes.set(path47, fresh);
|
|
3484
3484
|
return fresh;
|
|
3485
3485
|
}
|
|
3486
3486
|
};
|
|
@@ -4718,8 +4718,8 @@ function getErrorMap() {
|
|
|
4718
4718
|
|
|
4719
4719
|
// ../../node_modules/zod/v3/helpers/parseUtil.js
|
|
4720
4720
|
var makeIssue = (params) => {
|
|
4721
|
-
const { data, path:
|
|
4722
|
-
const fullPath = [...
|
|
4721
|
+
const { data, path: path47, errorMaps, issueData } = params;
|
|
4722
|
+
const fullPath = [...path47, ...issueData.path || []];
|
|
4723
4723
|
const fullIssue = {
|
|
4724
4724
|
...issueData,
|
|
4725
4725
|
path: fullPath
|
|
@@ -4835,11 +4835,11 @@ var errorUtil;
|
|
|
4835
4835
|
|
|
4836
4836
|
// ../../node_modules/zod/v3/types.js
|
|
4837
4837
|
var ParseInputLazyPath = class {
|
|
4838
|
-
constructor(parent, value,
|
|
4838
|
+
constructor(parent, value, path47, key) {
|
|
4839
4839
|
this._cachedPath = [];
|
|
4840
4840
|
this.parent = parent;
|
|
4841
4841
|
this.data = value;
|
|
4842
|
-
this._path =
|
|
4842
|
+
this._path = path47;
|
|
4843
4843
|
this._key = key;
|
|
4844
4844
|
}
|
|
4845
4845
|
get path() {
|
|
@@ -8294,6 +8294,13 @@ init_embedder();
|
|
|
8294
8294
|
// ../../packages/core/src/budget/budget.ts
|
|
8295
8295
|
init_logger();
|
|
8296
8296
|
|
|
8297
|
+
// ../../packages/core/src/budget/eventCollector.ts
|
|
8298
|
+
init_logger();
|
|
8299
|
+
import fs16 from "fs";
|
|
8300
|
+
import os2 from "os";
|
|
8301
|
+
import path16 from "path";
|
|
8302
|
+
var DEFAULT_TELEMETRY_DIR = path16.join(os2.homedir(), ".ctxloom", "telemetry");
|
|
8303
|
+
|
|
8297
8304
|
// ../../packages/core/src/tools/search.ts
|
|
8298
8305
|
var Schema = external_exports.object({
|
|
8299
8306
|
query: external_exports.string().describe("Search query \u2014 natural language or code fragment"),
|
|
@@ -8316,7 +8323,7 @@ var Schema2 = external_exports.object({
|
|
|
8316
8323
|
});
|
|
8317
8324
|
|
|
8318
8325
|
// ../../packages/core/src/tools/context-packet.ts
|
|
8319
|
-
import
|
|
8326
|
+
import path17 from "path";
|
|
8320
8327
|
var Schema3 = external_exports.object({
|
|
8321
8328
|
target_file: external_exports.string().describe("Relative path to the primary file"),
|
|
8322
8329
|
mode: external_exports.enum(["edit", "read"]).optional().default("edit").describe("Context mode"),
|
|
@@ -8328,7 +8335,7 @@ var Schema3 = external_exports.object({
|
|
|
8328
8335
|
});
|
|
8329
8336
|
|
|
8330
8337
|
// ../../packages/core/src/tools/findCallers.ts
|
|
8331
|
-
import
|
|
8338
|
+
import path18 from "path";
|
|
8332
8339
|
|
|
8333
8340
|
// ../../packages/core/src/tools/call-graph.ts
|
|
8334
8341
|
var Schema4 = external_exports.object({
|
|
@@ -8429,7 +8436,7 @@ var Schema12 = external_exports.object({
|
|
|
8429
8436
|
});
|
|
8430
8437
|
|
|
8431
8438
|
// ../../packages/core/src/tools/knowledge-gaps.ts
|
|
8432
|
-
import
|
|
8439
|
+
import path19 from "path";
|
|
8433
8440
|
var Schema13 = external_exports.object({
|
|
8434
8441
|
min_importers: external_exports.number().min(1).max(50).optional().default(3).describe(
|
|
8435
8442
|
"Minimum importers to qualify as an untested hub (default: 3)"
|
|
@@ -8458,7 +8465,7 @@ var Schema14 = external_exports.object({
|
|
|
8458
8465
|
});
|
|
8459
8466
|
|
|
8460
8467
|
// ../../packages/core/src/tools/wiki-generate.ts
|
|
8461
|
-
import
|
|
8468
|
+
import fs17 from "fs";
|
|
8462
8469
|
var Schema15 = external_exports.object({
|
|
8463
8470
|
force: external_exports.boolean().optional().default(false).describe(
|
|
8464
8471
|
"Regenerate all pages even if content unchanged (default: false)"
|
|
@@ -8506,8 +8513,8 @@ var Schema17 = external_exports.object({
|
|
|
8506
8513
|
});
|
|
8507
8514
|
|
|
8508
8515
|
// ../../packages/core/src/tools/refactor-preview.ts
|
|
8509
|
-
import
|
|
8510
|
-
import
|
|
8516
|
+
import fs18 from "fs";
|
|
8517
|
+
import path20 from "path";
|
|
8511
8518
|
var Schema18 = external_exports.object({
|
|
8512
8519
|
symbol: external_exports.string().min(1).describe("Symbol name to rename (exact match, case-sensitive)"),
|
|
8513
8520
|
new_name: external_exports.string().min(1).describe("New name for the symbol"),
|
|
@@ -8542,8 +8549,8 @@ var Schema19 = external_exports.object({
|
|
|
8542
8549
|
init_embedder();
|
|
8543
8550
|
init_VectorStore();
|
|
8544
8551
|
init_logger();
|
|
8545
|
-
import
|
|
8546
|
-
import
|
|
8552
|
+
import fs19 from "fs";
|
|
8553
|
+
import path21 from "path";
|
|
8547
8554
|
var Schema20 = external_exports.object({
|
|
8548
8555
|
query: external_exports.string().min(1).describe("Search query \u2014 natural language or code fragment"),
|
|
8549
8556
|
limit: external_exports.number().min(1).max(100).optional().default(10).describe(
|
|
@@ -8560,8 +8567,8 @@ var Schema20 = external_exports.object({
|
|
|
8560
8567
|
});
|
|
8561
8568
|
|
|
8562
8569
|
// ../../packages/core/src/tools/apply-refactor.ts
|
|
8563
|
-
import
|
|
8564
|
-
import
|
|
8570
|
+
import fs20 from "fs";
|
|
8571
|
+
import path22 from "path";
|
|
8565
8572
|
var Schema21 = external_exports.object({
|
|
8566
8573
|
symbol: external_exports.string().min(1).describe("Symbol name to rename (exact, case-sensitive)"),
|
|
8567
8574
|
new_name: external_exports.string().min(1).describe("New name for the symbol"),
|
|
@@ -8594,8 +8601,8 @@ var Schema22 = external_exports.object({
|
|
|
8594
8601
|
});
|
|
8595
8602
|
|
|
8596
8603
|
// ../../packages/core/src/tools/full-text-search.ts
|
|
8597
|
-
import
|
|
8598
|
-
import
|
|
8604
|
+
import fs21 from "fs";
|
|
8605
|
+
import path23 from "path";
|
|
8599
8606
|
var Schema23 = external_exports.object({
|
|
8600
8607
|
query: external_exports.string().min(1).describe("Search term \u2014 literal or /regex/"),
|
|
8601
8608
|
mode: external_exports.enum(["hybrid", "keyword", "semantic"]).optional().default("hybrid"),
|
|
@@ -8627,8 +8634,8 @@ var Schema25 = external_exports.object({
|
|
|
8627
8634
|
});
|
|
8628
8635
|
|
|
8629
8636
|
// ../../packages/core/src/tools/graph-snapshot.ts
|
|
8630
|
-
import
|
|
8631
|
-
import
|
|
8637
|
+
import fs22 from "fs";
|
|
8638
|
+
import path24 from "path";
|
|
8632
8639
|
var schema = external_exports.object({
|
|
8633
8640
|
name: external_exports.string().min(1).max(64).regex(/^[\w.-]+$/, "Name may only contain letters, digits, dots, underscores, hyphens").describe(
|
|
8634
8641
|
'Snapshot name (e.g. "before-refactor", "v1.0"). Used as the filename.'
|
|
@@ -8640,8 +8647,8 @@ var schema = external_exports.object({
|
|
|
8640
8647
|
});
|
|
8641
8648
|
|
|
8642
8649
|
// ../../packages/core/src/tools/graph-diff.ts
|
|
8643
|
-
import
|
|
8644
|
-
import
|
|
8650
|
+
import fs23 from "fs";
|
|
8651
|
+
import path25 from "path";
|
|
8645
8652
|
var schema2 = external_exports.object({
|
|
8646
8653
|
baseline: external_exports.string().min(1).describe('Name of the baseline snapshot (the "before" state).'),
|
|
8647
8654
|
current: external_exports.string().min(1).describe('Name of the current snapshot (the "after" state).'),
|
|
@@ -8682,8 +8689,8 @@ var Schema27 = external_exports.object({
|
|
|
8682
8689
|
});
|
|
8683
8690
|
|
|
8684
8691
|
// ../../packages/core/src/rules/loadConfig.ts
|
|
8685
|
-
import
|
|
8686
|
-
import
|
|
8692
|
+
import fs24 from "fs/promises";
|
|
8693
|
+
import path26 from "path";
|
|
8687
8694
|
|
|
8688
8695
|
// ../../node_modules/js-yaml/dist/js-yaml.mjs
|
|
8689
8696
|
function isNothing(subject) {
|
|
@@ -11311,25 +11318,37 @@ var Schema29 = external_exports.object({
|
|
|
11311
11318
|
project_root: ProjectRootField
|
|
11312
11319
|
});
|
|
11313
11320
|
|
|
11314
|
-
// ../../packages/core/src/tools/
|
|
11315
|
-
import
|
|
11316
|
-
|
|
11321
|
+
// ../../packages/core/src/tools/minimal-context.ts
|
|
11322
|
+
import { execSync } from "child_process";
|
|
11323
|
+
var Schema30 = external_exports.object({
|
|
11324
|
+
task: external_exports.string().max(200).optional().describe(
|
|
11325
|
+
"Free-text description of what you're about to do (e.g. 'review PR 142', 'rename emitTelemetry'). The tool routes by regex to the most-fitting suggested-first-tool. Capped at 200 chars; control characters stripped."
|
|
11326
|
+
),
|
|
11327
|
+
project_root: ProjectRootField,
|
|
11328
|
+
max_response_tokens: external_exports.number().int().positive().optional(),
|
|
11329
|
+
on_budget_exceeded: external_exports.enum(["skeleton", "truncate", "error"]).optional(),
|
|
11330
|
+
response_format: external_exports.enum(["full", "skeleton", "auto"]).optional()
|
|
11331
|
+
});
|
|
11317
11332
|
|
|
11318
|
-
// ../../packages/core/src/
|
|
11319
|
-
import fs25 from "fs
|
|
11333
|
+
// ../../packages/core/src/tools/ruleManager.ts
|
|
11334
|
+
import fs25 from "fs";
|
|
11320
11335
|
import path27 from "path";
|
|
11321
11336
|
|
|
11322
|
-
// ../../packages/core/src/review/
|
|
11337
|
+
// ../../packages/core/src/review/AuthorResolver.ts
|
|
11323
11338
|
import fs26 from "fs/promises";
|
|
11324
11339
|
import path28 from "path";
|
|
11325
11340
|
|
|
11326
|
-
// ../../packages/core/src/review/
|
|
11341
|
+
// ../../packages/core/src/review/CodeownersWriter.ts
|
|
11327
11342
|
import fs27 from "fs/promises";
|
|
11328
11343
|
import path29 from "path";
|
|
11329
11344
|
|
|
11330
|
-
// ../../packages/core/src/
|
|
11345
|
+
// ../../packages/core/src/review/loadConfig.ts
|
|
11346
|
+
import fs28 from "fs/promises";
|
|
11331
11347
|
import path30 from "path";
|
|
11332
|
-
|
|
11348
|
+
|
|
11349
|
+
// ../../packages/core/src/security/PathValidator.ts
|
|
11350
|
+
import path31 from "path";
|
|
11351
|
+
import fs29 from "fs";
|
|
11333
11352
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
11334
11353
|
|
|
11335
11354
|
// ../../packages/core/src/index.ts
|
|
@@ -11340,7 +11359,7 @@ init_logger();
|
|
|
11340
11359
|
|
|
11341
11360
|
// ../../packages/core/src/license/LicenseStore.ts
|
|
11342
11361
|
import { readFileSync, writeFileSync, unlinkSync, mkdirSync, chmodSync, existsSync } from "fs";
|
|
11343
|
-
import
|
|
11362
|
+
import path32 from "path";
|
|
11344
11363
|
|
|
11345
11364
|
// ../../packages/core/src/license/types.ts
|
|
11346
11365
|
var FINGERPRINT_RE = /^sha256:[0-9a-f]{64}$/;
|
|
@@ -11363,19 +11382,19 @@ var API_BASE = process.env["CTXLOOM_API_BASE"] ?? "https://api.ctxloom.com";
|
|
|
11363
11382
|
|
|
11364
11383
|
// ../../packages/core/src/license/Fingerprint.ts
|
|
11365
11384
|
import crypto4 from "crypto";
|
|
11366
|
-
import
|
|
11385
|
+
import os3 from "os";
|
|
11367
11386
|
import { readFileSync as readFileSync2 } from "fs";
|
|
11368
11387
|
|
|
11369
11388
|
// ../../packages/core/src/license/index.ts
|
|
11370
|
-
import
|
|
11389
|
+
import os6 from "os";
|
|
11371
11390
|
|
|
11372
11391
|
// ../../packages/core/src/license/DistinctIdStore.ts
|
|
11373
11392
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
|
|
11374
|
-
import
|
|
11375
|
-
import
|
|
11393
|
+
import path33 from "path";
|
|
11394
|
+
import os4 from "os";
|
|
11376
11395
|
var UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
11377
11396
|
function distinctIdPath(home) {
|
|
11378
|
-
return
|
|
11397
|
+
return path33.join(home ?? os4.homedir(), ".ctxloom", "distinct_id");
|
|
11379
11398
|
}
|
|
11380
11399
|
function isValidV4(id) {
|
|
11381
11400
|
return typeof id === "string" && UUID_V4_REGEX.test(id);
|
|
@@ -11394,9 +11413,9 @@ function getOrCreateDistinctId(home) {
|
|
|
11394
11413
|
}
|
|
11395
11414
|
const record = {
|
|
11396
11415
|
id: crypto.randomUUID(),
|
|
11397
|
-
alias_pending:
|
|
11416
|
+
alias_pending: os4.hostname()
|
|
11398
11417
|
};
|
|
11399
|
-
mkdirSync2(
|
|
11418
|
+
mkdirSync2(path33.dirname(filePath), { recursive: true });
|
|
11400
11419
|
writeFileSync2(filePath, JSON.stringify(record), { mode: 384 });
|
|
11401
11420
|
return record;
|
|
11402
11421
|
}
|
|
@@ -11422,7 +11441,7 @@ function resolveTelemetryLevel() {
|
|
|
11422
11441
|
}
|
|
11423
11442
|
var TELEMETRY_LEVEL = resolveTelemetryLevel();
|
|
11424
11443
|
var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
|
|
11425
|
-
var CTXLOOM_VERSION = "1.
|
|
11444
|
+
var CTXLOOM_VERSION = "1.4.0".length > 0 ? "1.4.0" : "dev";
|
|
11426
11445
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
11427
11446
|
var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
|
|
11428
11447
|
var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
|
|
@@ -11555,31 +11574,79 @@ function parseStack(stack) {
|
|
|
11555
11574
|
|
|
11556
11575
|
// ../../packages/core/src/license/FunnelMilestones.ts
|
|
11557
11576
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
11558
|
-
import
|
|
11559
|
-
import
|
|
11577
|
+
import path34 from "path";
|
|
11578
|
+
import os5 from "os";
|
|
11560
11579
|
|
|
11561
11580
|
// ../../packages/core/src/license/TelemetryNotice.ts
|
|
11562
11581
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
11563
|
-
import
|
|
11564
|
-
import
|
|
11582
|
+
import path35 from "path";
|
|
11583
|
+
import os7 from "os";
|
|
11565
11584
|
|
|
11566
11585
|
// ../../packages/core/src/server/ProjectState.ts
|
|
11567
|
-
import
|
|
11586
|
+
import path37 from "path";
|
|
11568
11587
|
|
|
11569
11588
|
// ../../packages/core/src/server/projectId.ts
|
|
11570
11589
|
import crypto5 from "crypto";
|
|
11571
|
-
import
|
|
11590
|
+
import path36 from "path";
|
|
11572
11591
|
|
|
11573
11592
|
// ../../packages/core/src/server/ProjectStateManager.ts
|
|
11574
11593
|
init_logger();
|
|
11575
11594
|
|
|
11576
11595
|
// ../../packages/core/src/server/resolveProjectRoot.ts
|
|
11577
|
-
import
|
|
11578
|
-
import
|
|
11596
|
+
import fs30 from "fs";
|
|
11597
|
+
import path38 from "path";
|
|
11598
|
+
|
|
11599
|
+
// ../../packages/core/src/install/installer.ts
|
|
11600
|
+
import fs31 from "fs";
|
|
11601
|
+
import path39 from "path";
|
|
11602
|
+
|
|
11603
|
+
// ../../packages/core/src/install/templates.ts
|
|
11604
|
+
var SESSION_START_HEADER = `#!/usr/bin/env bash
|
|
11605
|
+
# ctxloom \u2014 agent-harness session-start hook
|
|
11606
|
+
# Generated by \`ctxloom init\`. Re-run \`ctxloom init\` to update.
|
|
11607
|
+
# Manual edits will be overwritten on the next install.
|
|
11608
|
+
|
|
11609
|
+
set -e
|
|
11610
|
+
`;
|
|
11611
|
+
var SESSION_START_BODY = `DB=".ctxloom/graph.db"
|
|
11612
|
+
|
|
11613
|
+
if [ -f "$DB" ]; then
|
|
11614
|
+
# \`ctxloom status --json\` is cached + sub-100ms \u2014 keeps the hook
|
|
11615
|
+
# under its 2s timeout even on cold disk.
|
|
11616
|
+
STATS=$(ctxloom status --json 2>/dev/null || echo '{"nodes":0,"edges":0}')
|
|
11617
|
+
NODES=$(echo "$STATS" | grep -oE '"nodes":\\s*[0-9]+' | grep -oE '[0-9]+' || echo "?")
|
|
11618
|
+
EDGES=$(echo "$STATS" | grep -oE '"edges":\\s*[0-9]+' | grep -oE '[0-9]+' || echo "?")
|
|
11619
|
+
|
|
11620
|
+
cat <<EOF
|
|
11621
|
+
[ctxloom] Knowledge graph ready (\${NODES} nodes, \${EDGES} edges).
|
|
11622
|
+
|
|
11623
|
+
Start every workflow with \\\`ctx_get_minimal_context(task="...")\\\`.
|
|
11624
|
+
It returns ~150 tokens of orientation + a task-aware
|
|
11625
|
+
suggested_first_tool. Follow the meta.next_tool_suggestions on
|
|
11626
|
+
every response.
|
|
11627
|
+
|
|
11628
|
+
Prefer ctxloom MCP tools over Grep/Glob/Read:
|
|
11629
|
+
- ctx_detect_changes for code review
|
|
11630
|
+
- ctx_blast_radius / ctx_get_call_graph before refactoring
|
|
11631
|
+
- ctx_architecture_overview for orientation
|
|
11632
|
+
EOF
|
|
11633
|
+
else
|
|
11634
|
+
cat <<EOF
|
|
11635
|
+
[ctxloom] No knowledge graph found here.
|
|
11636
|
+
Run: ctxloom build
|
|
11637
|
+
|
|
11638
|
+
Then restart this session to enable graph-powered queries.
|
|
11639
|
+
EOF
|
|
11640
|
+
fi
|
|
11641
|
+
`;
|
|
11642
|
+
var SESSION_START_FULL = SESSION_START_HEADER + "\n" + SESSION_START_BODY;
|
|
11643
|
+
|
|
11644
|
+
// ../../packages/core/src/install/hmacBlock.ts
|
|
11645
|
+
import crypto6 from "crypto";
|
|
11579
11646
|
|
|
11580
11647
|
// server/loader.ts
|
|
11581
11648
|
async function loadContext(root) {
|
|
11582
|
-
const absRoot =
|
|
11649
|
+
const absRoot = path40.resolve(root);
|
|
11583
11650
|
const overlay = new GitOverlayStore(absRoot);
|
|
11584
11651
|
const gitEnabled = await overlay.loadSnapshot();
|
|
11585
11652
|
const graph = new DependencyGraph();
|
|
@@ -11832,21 +11899,21 @@ function buildOwnershipRouter(ctx) {
|
|
|
11832
11899
|
|
|
11833
11900
|
// server/routes/file.ts
|
|
11834
11901
|
import { Router as Router7 } from "express";
|
|
11835
|
-
import
|
|
11836
|
-
import
|
|
11902
|
+
import fs32 from "fs/promises";
|
|
11903
|
+
import path41 from "path";
|
|
11837
11904
|
function buildFileRouter(ctx) {
|
|
11838
11905
|
const router = Router7();
|
|
11839
11906
|
router.get("/", async (req, res) => {
|
|
11840
11907
|
const rel = req.query.path;
|
|
11841
11908
|
if (!rel) return res.status(400).json({ error: "missing path" });
|
|
11842
|
-
const abs =
|
|
11843
|
-
const rootBoundary = ctx.root.endsWith(
|
|
11909
|
+
const abs = path41.resolve(ctx.root, rel);
|
|
11910
|
+
const rootBoundary = ctx.root.endsWith(path41.sep) ? ctx.root : ctx.root + path41.sep;
|
|
11844
11911
|
if (abs !== ctx.root && !abs.startsWith(rootBoundary)) {
|
|
11845
11912
|
return res.status(403).json({ error: "forbidden" });
|
|
11846
11913
|
}
|
|
11847
11914
|
try {
|
|
11848
|
-
const content = await
|
|
11849
|
-
const ext =
|
|
11915
|
+
const content = await fs32.readFile(abs, "utf-8");
|
|
11916
|
+
const ext = path41.extname(abs).slice(1);
|
|
11850
11917
|
res.json({ content, lines: content.split("\n").length, ext });
|
|
11851
11918
|
} catch {
|
|
11852
11919
|
res.status(404).json({ error: "not found" });
|
|
@@ -11858,7 +11925,7 @@ function buildFileRouter(ctx) {
|
|
|
11858
11925
|
// server/routes/open.ts
|
|
11859
11926
|
import { Router as Router8 } from "express";
|
|
11860
11927
|
import { execFile as execFile2 } from "child_process";
|
|
11861
|
-
import
|
|
11928
|
+
import path42 from "path";
|
|
11862
11929
|
function tryOpen(bin, abs) {
|
|
11863
11930
|
return new Promise((resolve) => {
|
|
11864
11931
|
execFile2(bin, [abs], { timeout: 5e3 }, (err) => resolve(!err));
|
|
@@ -11869,8 +11936,8 @@ function buildOpenRouter(ctx) {
|
|
|
11869
11936
|
router.post("/", async (req, res) => {
|
|
11870
11937
|
const rel = req.body?.path;
|
|
11871
11938
|
if (!rel || typeof rel !== "string") return res.status(400).json({ error: "missing path" });
|
|
11872
|
-
const abs =
|
|
11873
|
-
const rootBoundary = ctx.root.endsWith(
|
|
11939
|
+
const abs = path42.resolve(ctx.root, rel);
|
|
11940
|
+
const rootBoundary = ctx.root.endsWith(path42.sep) ? ctx.root : ctx.root + path42.sep;
|
|
11874
11941
|
if (abs !== ctx.root && !abs.startsWith(rootBoundary)) {
|
|
11875
11942
|
return res.status(403).json({ error: "forbidden" });
|
|
11876
11943
|
}
|
|
@@ -11882,8 +11949,8 @@ function buildOpenRouter(ctx) {
|
|
|
11882
11949
|
|
|
11883
11950
|
// server/routes/tokens.ts
|
|
11884
11951
|
import { Router as Router9 } from "express";
|
|
11885
|
-
import
|
|
11886
|
-
import
|
|
11952
|
+
import path43 from "path";
|
|
11953
|
+
import fs33 from "fs";
|
|
11887
11954
|
var CHARS_PER_TOKEN = 4;
|
|
11888
11955
|
var cache = null;
|
|
11889
11956
|
function buildTokensRouter(ctx) {
|
|
@@ -11898,9 +11965,9 @@ function buildTokensRouter(ctx) {
|
|
|
11898
11965
|
let fullChars = 0;
|
|
11899
11966
|
let skeletonChars = 0;
|
|
11900
11967
|
for (const file of files) {
|
|
11901
|
-
const absPath =
|
|
11968
|
+
const absPath = path43.join(ctx.root, file);
|
|
11902
11969
|
try {
|
|
11903
|
-
const content =
|
|
11970
|
+
const content = fs33.readFileSync(absPath, "utf-8");
|
|
11904
11971
|
fullChars += content.length;
|
|
11905
11972
|
const skeleton = await skeletonizer.skeletonize(absPath);
|
|
11906
11973
|
skeletonChars += skeleton.length;
|
|
@@ -12001,18 +12068,18 @@ function buildFileTrendsRouter(ctx) {
|
|
|
12001
12068
|
|
|
12002
12069
|
// server/routes/projects.ts
|
|
12003
12070
|
import { Router as Router12 } from "express";
|
|
12004
|
-
import
|
|
12071
|
+
import path45 from "path";
|
|
12005
12072
|
|
|
12006
12073
|
// server/projects.ts
|
|
12007
12074
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
12008
|
-
import
|
|
12009
|
-
import
|
|
12010
|
-
import
|
|
12011
|
-
var HOME =
|
|
12012
|
-
var REGISTRY_PATH =
|
|
12075
|
+
import os8 from "os";
|
|
12076
|
+
import path44 from "path";
|
|
12077
|
+
import crypto7 from "crypto";
|
|
12078
|
+
var HOME = os8.homedir();
|
|
12079
|
+
var REGISTRY_PATH = path44.join(HOME, ".ctxloom", "repos.json");
|
|
12013
12080
|
function slugFor(root) {
|
|
12014
|
-
const abs =
|
|
12015
|
-
return
|
|
12081
|
+
const abs = path44.resolve(root);
|
|
12082
|
+
return crypto7.createHash("sha1").update(abs).digest("hex").slice(0, 12);
|
|
12016
12083
|
}
|
|
12017
12084
|
function readRegistry() {
|
|
12018
12085
|
if (!existsSync5(REGISTRY_PATH)) return [];
|
|
@@ -12026,27 +12093,27 @@ function readRegistry() {
|
|
|
12026
12093
|
}
|
|
12027
12094
|
}
|
|
12028
12095
|
function listProjects(defaultRoot) {
|
|
12029
|
-
const absDefault =
|
|
12096
|
+
const absDefault = path44.resolve(defaultRoot);
|
|
12030
12097
|
const out = [
|
|
12031
12098
|
{
|
|
12032
12099
|
slug: slugFor(absDefault),
|
|
12033
|
-
name:
|
|
12100
|
+
name: path44.basename(absDefault) || absDefault,
|
|
12034
12101
|
root: absDefault,
|
|
12035
12102
|
isDefault: true,
|
|
12036
|
-
hasSnapshot: existsSync5(
|
|
12103
|
+
hasSnapshot: existsSync5(path44.join(absDefault, ".ctxloom"))
|
|
12037
12104
|
}
|
|
12038
12105
|
];
|
|
12039
12106
|
const seen = /* @__PURE__ */ new Set([absDefault]);
|
|
12040
12107
|
for (const entry of readRegistry()) {
|
|
12041
|
-
const abs =
|
|
12108
|
+
const abs = path44.resolve(entry.root);
|
|
12042
12109
|
if (seen.has(abs)) continue;
|
|
12043
12110
|
seen.add(abs);
|
|
12044
12111
|
const item = {
|
|
12045
12112
|
slug: slugFor(abs),
|
|
12046
|
-
name: entry.name ?? (
|
|
12113
|
+
name: entry.name ?? (path44.basename(abs) || abs),
|
|
12047
12114
|
root: abs,
|
|
12048
12115
|
isDefault: false,
|
|
12049
|
-
hasSnapshot: existsSync5(
|
|
12116
|
+
hasSnapshot: existsSync5(path44.join(abs, ".ctxloom"))
|
|
12050
12117
|
};
|
|
12051
12118
|
if (entry.alias !== void 0) item.alias = entry.alias;
|
|
12052
12119
|
out.push(item);
|
|
@@ -12099,7 +12166,7 @@ function buildProjectsRouter(deps) {
|
|
|
12099
12166
|
} catch (err) {
|
|
12100
12167
|
const detail = err instanceof Error ? err.message : String(err);
|
|
12101
12168
|
res.status(500).json({
|
|
12102
|
-
error: `failed to switch to ${
|
|
12169
|
+
error: `failed to switch to ${path45.basename(target.root)}: ${detail}`
|
|
12103
12170
|
});
|
|
12104
12171
|
}
|
|
12105
12172
|
});
|
|
@@ -12156,7 +12223,7 @@ function buildTelemetryRouter() {
|
|
|
12156
12223
|
}
|
|
12157
12224
|
|
|
12158
12225
|
// server/index.ts
|
|
12159
|
-
var __dirname2 =
|
|
12226
|
+
var __dirname2 = path46.dirname(fileURLToPath2(import.meta.url));
|
|
12160
12227
|
async function startDashboard(options) {
|
|
12161
12228
|
const { root, port, open } = options;
|
|
12162
12229
|
console.log(`ctxloom dashboard \u2014 loading context from ${root}...`);
|
|
@@ -12215,9 +12282,9 @@ async function startDashboard(options) {
|
|
|
12215
12282
|
}
|
|
12216
12283
|
activeWatcher = null;
|
|
12217
12284
|
}
|
|
12218
|
-
const snapshotDir =
|
|
12285
|
+
const snapshotDir = path46.join(targetRoot, ".ctxloom");
|
|
12219
12286
|
try {
|
|
12220
|
-
activeWatcher =
|
|
12287
|
+
activeWatcher = fs34.watch(snapshotDir, (_event, filename) => {
|
|
12221
12288
|
if (!filename || !filename.includes("snapshot")) return;
|
|
12222
12289
|
if (debounce) clearTimeout(debounce);
|
|
12223
12290
|
debounce = setTimeout(async () => {
|
|
@@ -12246,12 +12313,12 @@ async function startDashboard(options) {
|
|
|
12246
12313
|
attachSnapshotWatcher(newRoot);
|
|
12247
12314
|
}
|
|
12248
12315
|
}));
|
|
12249
|
-
const clientDist =
|
|
12250
|
-
const clientDistExists =
|
|
12316
|
+
const clientDist = path46.join(__dirname2, "../dashboard/client");
|
|
12317
|
+
const clientDistExists = fs34.existsSync(path46.join(clientDist, "index.html"));
|
|
12251
12318
|
if (clientDistExists) {
|
|
12252
12319
|
app.use(express.static(clientDist, { dotfiles: "allow" }));
|
|
12253
12320
|
app.get(/.*/, (_req, res) => {
|
|
12254
|
-
res.sendFile(
|
|
12321
|
+
res.sendFile(path46.join(clientDist, "index.html"), { dotfiles: "allow" });
|
|
12255
12322
|
});
|
|
12256
12323
|
} else {
|
|
12257
12324
|
app.get(/^\/(?!api\/).*/, (_req, res) => {
|