rrce-workflow 0.2.92 → 0.2.93
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/index.js +220 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1562,6 +1562,33 @@ var init_rag = __esm({
|
|
|
1562
1562
|
logger.error(`[RAG] Failed to save index to ${this.indexPath}`, error);
|
|
1563
1563
|
}
|
|
1564
1564
|
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Save index to a temp file and atomically replace
|
|
1567
|
+
*/
|
|
1568
|
+
saveIndexAtomic() {
|
|
1569
|
+
if (!this.index) return;
|
|
1570
|
+
const dir = path15.dirname(this.indexPath);
|
|
1571
|
+
if (!fs13.existsSync(dir)) {
|
|
1572
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
1573
|
+
}
|
|
1574
|
+
const tmpPath = `${this.indexPath}.tmp`;
|
|
1575
|
+
fs13.writeFileSync(tmpPath, JSON.stringify(this.index, null, 2));
|
|
1576
|
+
fs13.renameSync(tmpPath, this.indexPath);
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Save index only if enough time passed since last save
|
|
1580
|
+
*/
|
|
1581
|
+
maybeSaveIndex(force = false) {
|
|
1582
|
+
if (!this.index) return;
|
|
1583
|
+
const now = Date.now();
|
|
1584
|
+
const intervalMs = 1e3;
|
|
1585
|
+
const last = this.index.metadata?.lastSaveAt;
|
|
1586
|
+
if (force || last === void 0 || now - last >= intervalMs) {
|
|
1587
|
+
this.index.metadata = { ...this.index.metadata ?? {}, lastSaveAt: now };
|
|
1588
|
+
this.saveIndexAtomic();
|
|
1589
|
+
logger.info(`[RAG] Saved index (atomic) to ${this.indexPath} with ${this.index.chunks.length} chunks.`);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1565
1592
|
/**
|
|
1566
1593
|
* Generate embedding for text
|
|
1567
1594
|
*/
|
|
@@ -1612,7 +1639,7 @@ var init_rag = __esm({
|
|
|
1612
1639
|
mtime: mtime ?? Date.now(),
|
|
1613
1640
|
chunkCount: chunks.length
|
|
1614
1641
|
};
|
|
1615
|
-
this.
|
|
1642
|
+
this.maybeSaveIndex();
|
|
1616
1643
|
return true;
|
|
1617
1644
|
}
|
|
1618
1645
|
/**
|
|
@@ -1628,7 +1655,7 @@ var init_rag = __esm({
|
|
|
1628
1655
|
}
|
|
1629
1656
|
if (this.index.chunks.length !== initialCount) {
|
|
1630
1657
|
logger.info(`[RAG] Removed file ${filePath} from index (${initialCount - this.index.chunks.length} chunks removed)`);
|
|
1631
|
-
this.
|
|
1658
|
+
this.maybeSaveIndex(true);
|
|
1632
1659
|
}
|
|
1633
1660
|
}
|
|
1634
1661
|
/**
|
|
@@ -1651,7 +1678,7 @@ var init_rag = __esm({
|
|
|
1651
1678
|
this.loadIndex();
|
|
1652
1679
|
if (!this.index) return;
|
|
1653
1680
|
this.index.lastFullIndex = Date.now();
|
|
1654
|
-
this.
|
|
1681
|
+
this.maybeSaveIndex(true);
|
|
1655
1682
|
}
|
|
1656
1683
|
/**
|
|
1657
1684
|
* Search the index
|
|
@@ -1681,9 +1708,11 @@ var init_rag = __esm({
|
|
|
1681
1708
|
let normA = 0;
|
|
1682
1709
|
let normB = 0;
|
|
1683
1710
|
for (let i = 0; i < a.length; i++) {
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1711
|
+
const av = a[i] ?? 0;
|
|
1712
|
+
const bv = b[i] ?? 0;
|
|
1713
|
+
dotProduct += av * bv;
|
|
1714
|
+
normA += av * av;
|
|
1715
|
+
normB += bv * bv;
|
|
1687
1716
|
}
|
|
1688
1717
|
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
1689
1718
|
}
|
|
@@ -1716,6 +1745,83 @@ var init_rag = __esm({
|
|
|
1716
1745
|
}
|
|
1717
1746
|
});
|
|
1718
1747
|
|
|
1748
|
+
// src/mcp/services/indexing-jobs.ts
|
|
1749
|
+
var IndexingJobManager, indexingJobs;
|
|
1750
|
+
var init_indexing_jobs = __esm({
|
|
1751
|
+
"src/mcp/services/indexing-jobs.ts"() {
|
|
1752
|
+
"use strict";
|
|
1753
|
+
init_logger();
|
|
1754
|
+
IndexingJobManager = class {
|
|
1755
|
+
jobs = /* @__PURE__ */ new Map();
|
|
1756
|
+
getProgress(project) {
|
|
1757
|
+
const existing = this.jobs.get(project);
|
|
1758
|
+
if (existing) return { ...existing.progress };
|
|
1759
|
+
return {
|
|
1760
|
+
project,
|
|
1761
|
+
state: "idle",
|
|
1762
|
+
itemsDone: 0,
|
|
1763
|
+
itemsTotal: void 0
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
update(project, patch) {
|
|
1767
|
+
const existing = this.jobs.get(project);
|
|
1768
|
+
const next = {
|
|
1769
|
+
...existing?.progress ?? this.getProgress(project),
|
|
1770
|
+
...patch,
|
|
1771
|
+
project
|
|
1772
|
+
};
|
|
1773
|
+
this.jobs.set(project, { ...existing ?? { progress: next }, progress: next });
|
|
1774
|
+
}
|
|
1775
|
+
isRunning(project) {
|
|
1776
|
+
return this.getProgress(project).state === "running";
|
|
1777
|
+
}
|
|
1778
|
+
startOrStatus(project, runner) {
|
|
1779
|
+
const current = this.jobs.get(project);
|
|
1780
|
+
if (current?.progress.state === "running" && current.promise) {
|
|
1781
|
+
return {
|
|
1782
|
+
status: "already_running",
|
|
1783
|
+
state: "running",
|
|
1784
|
+
progress: { ...current.progress }
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
const startedAt = Date.now();
|
|
1788
|
+
const initial = {
|
|
1789
|
+
project,
|
|
1790
|
+
state: "running",
|
|
1791
|
+
startedAt,
|
|
1792
|
+
itemsDone: 0,
|
|
1793
|
+
itemsTotal: void 0,
|
|
1794
|
+
currentItem: void 0,
|
|
1795
|
+
lastError: void 0
|
|
1796
|
+
};
|
|
1797
|
+
const job = { progress: initial };
|
|
1798
|
+
this.jobs.set(project, job);
|
|
1799
|
+
job.promise = (async () => {
|
|
1800
|
+
try {
|
|
1801
|
+
await runner();
|
|
1802
|
+
this.update(project, { state: "complete", completedAt: Date.now(), currentItem: void 0 });
|
|
1803
|
+
} catch (err) {
|
|
1804
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1805
|
+
logger.error(`[RAG] Indexing job failed for '${project}'`, err);
|
|
1806
|
+
this.update(project, {
|
|
1807
|
+
state: "failed",
|
|
1808
|
+
completedAt: Date.now(),
|
|
1809
|
+
currentItem: void 0,
|
|
1810
|
+
lastError: msg
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
})();
|
|
1814
|
+
return {
|
|
1815
|
+
status: "started",
|
|
1816
|
+
state: "running",
|
|
1817
|
+
progress: { ...this.getProgress(project) }
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
indexingJobs = new IndexingJobManager();
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1824
|
+
|
|
1719
1825
|
// src/mcp/resources.ts
|
|
1720
1826
|
import * as fs14 from "fs";
|
|
1721
1827
|
import * as path16 from "path";
|
|
@@ -1887,6 +1993,8 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
1887
1993
|
if (projectFilter && project.name !== projectFilter) continue;
|
|
1888
1994
|
const permissions = getProjectPermissions(config, project.name, project.sourcePath || project.path);
|
|
1889
1995
|
if (!permissions.knowledge || !project.knowledgePath) continue;
|
|
1996
|
+
const indexingInProgress = indexingJobs.isRunning(project.name);
|
|
1997
|
+
const advisoryMessage = indexingInProgress ? "Indexing in progress; results may be stale/incomplete." : void 0;
|
|
1890
1998
|
const projConfig = config.projects.find(
|
|
1891
1999
|
(p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.sourcePath || project.path) || !p.path && p.name === project.name
|
|
1892
2000
|
);
|
|
@@ -1903,7 +2011,9 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
1903
2011
|
file: path16.relative(project.knowledgePath, r.filePath),
|
|
1904
2012
|
matches: [r.content],
|
|
1905
2013
|
// The chunk content is the match
|
|
1906
|
-
score: r.score
|
|
2014
|
+
score: r.score,
|
|
2015
|
+
indexingInProgress: indexingInProgress || void 0,
|
|
2016
|
+
advisoryMessage
|
|
1907
2017
|
});
|
|
1908
2018
|
}
|
|
1909
2019
|
continue;
|
|
@@ -1928,8 +2038,10 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
1928
2038
|
results.push({
|
|
1929
2039
|
project: project.name,
|
|
1930
2040
|
file,
|
|
1931
|
-
matches: matches.slice(0, 5)
|
|
2041
|
+
matches: matches.slice(0, 5),
|
|
1932
2042
|
// Limit to 5 matches per file
|
|
2043
|
+
indexingInProgress: indexingInProgress || void 0,
|
|
2044
|
+
advisoryMessage
|
|
1933
2045
|
});
|
|
1934
2046
|
}
|
|
1935
2047
|
}
|
|
@@ -1941,20 +2053,44 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
1941
2053
|
async function indexKnowledge(projectName, force = false) {
|
|
1942
2054
|
const config = loadMCPConfig();
|
|
1943
2055
|
const projects = getExposedProjects();
|
|
1944
|
-
const project = projects.find((
|
|
2056
|
+
const project = projects.find((p2) => p2.name === projectName || p2.path && p2.path === projectName);
|
|
1945
2057
|
if (!project) {
|
|
1946
|
-
return {
|
|
2058
|
+
return {
|
|
2059
|
+
state: "failed",
|
|
2060
|
+
status: "failed",
|
|
2061
|
+
success: false,
|
|
2062
|
+
message: `Project '${projectName}' not found`,
|
|
2063
|
+
filesIndexed: 0,
|
|
2064
|
+
filesSkipped: 0,
|
|
2065
|
+
progress: { itemsDone: 0 }
|
|
2066
|
+
};
|
|
1947
2067
|
}
|
|
1948
2068
|
const projConfig = config.projects.find(
|
|
1949
|
-
(
|
|
2069
|
+
(p2) => p2.path && normalizeProjectPath(p2.path) === normalizeProjectPath(project.sourcePath || project.path) || !p2.path && p2.name === project.name
|
|
1950
2070
|
) || (project.source === "global" ? { semanticSearch: { enabled: true, model: "Xenova/all-MiniLM-L6-v2" } } : void 0);
|
|
1951
2071
|
const isEnabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled;
|
|
1952
2072
|
if (!isEnabled) {
|
|
1953
|
-
return {
|
|
2073
|
+
return {
|
|
2074
|
+
state: "failed",
|
|
2075
|
+
status: "failed",
|
|
2076
|
+
success: false,
|
|
2077
|
+
message: "Semantic Search is not enabled for this project",
|
|
2078
|
+
filesIndexed: 0,
|
|
2079
|
+
filesSkipped: 0,
|
|
2080
|
+
progress: { itemsDone: 0 }
|
|
2081
|
+
};
|
|
1954
2082
|
}
|
|
1955
2083
|
const scanRoot = project.sourcePath || project.path || project.dataPath;
|
|
1956
2084
|
if (!fs14.existsSync(scanRoot)) {
|
|
1957
|
-
return {
|
|
2085
|
+
return {
|
|
2086
|
+
state: "failed",
|
|
2087
|
+
status: "failed",
|
|
2088
|
+
success: false,
|
|
2089
|
+
message: "Project root not found",
|
|
2090
|
+
filesIndexed: 0,
|
|
2091
|
+
filesSkipped: 0,
|
|
2092
|
+
progress: { itemsDone: 0 }
|
|
2093
|
+
};
|
|
1958
2094
|
}
|
|
1959
2095
|
const INDEXABLE_EXTENSIONS = [
|
|
1960
2096
|
".ts",
|
|
@@ -1995,18 +2131,37 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
1995
2131
|
".less"
|
|
1996
2132
|
];
|
|
1997
2133
|
const SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
|
|
1998
|
-
|
|
2134
|
+
const runIndexing = async () => {
|
|
1999
2135
|
const indexPath = path16.join(project.knowledgePath || path16.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
|
|
2000
2136
|
const model = projConfig?.semanticSearch?.model || "Xenova/all-MiniLM-L6-v2";
|
|
2001
2137
|
const rag = new RAGService(indexPath, model);
|
|
2002
2138
|
let indexed = 0;
|
|
2003
2139
|
let skipped = 0;
|
|
2140
|
+
let itemsTotal = 0;
|
|
2141
|
+
let itemsDone = 0;
|
|
2142
|
+
const shouldSkipDir = (dirName) => SKIP_DIRS.includes(dirName) || dirName.startsWith(".");
|
|
2143
|
+
const preCount = (dir) => {
|
|
2144
|
+
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
2145
|
+
for (const entry of entries) {
|
|
2146
|
+
const fullPath = path16.join(dir, entry.name);
|
|
2147
|
+
if (entry.isDirectory()) {
|
|
2148
|
+
if (shouldSkipDir(entry.name)) continue;
|
|
2149
|
+
preCount(fullPath);
|
|
2150
|
+
} else if (entry.isFile()) {
|
|
2151
|
+
const ext = path16.extname(entry.name).toLowerCase();
|
|
2152
|
+
if (!INDEXABLE_EXTENSIONS.includes(ext)) continue;
|
|
2153
|
+
itemsTotal++;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2157
|
+
preCount(scanRoot);
|
|
2158
|
+
indexingJobs.update(project.name, { itemsTotal });
|
|
2004
2159
|
const scanDir = async (dir) => {
|
|
2005
2160
|
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
2006
2161
|
for (const entry of entries) {
|
|
2007
2162
|
const fullPath = path16.join(dir, entry.name);
|
|
2008
2163
|
if (entry.isDirectory()) {
|
|
2009
|
-
if (
|
|
2164
|
+
if (shouldSkipDir(entry.name)) {
|
|
2010
2165
|
continue;
|
|
2011
2166
|
}
|
|
2012
2167
|
await scanDir(fullPath);
|
|
@@ -2016,6 +2171,7 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2016
2171
|
continue;
|
|
2017
2172
|
}
|
|
2018
2173
|
try {
|
|
2174
|
+
indexingJobs.update(project.name, { currentItem: fullPath, itemsDone });
|
|
2019
2175
|
const stat = fs14.statSync(fullPath);
|
|
2020
2176
|
const mtime = force ? void 0 : stat.mtimeMs;
|
|
2021
2177
|
const content = fs14.readFileSync(fullPath, "utf-8");
|
|
@@ -2026,6 +2182,12 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2026
2182
|
skipped++;
|
|
2027
2183
|
}
|
|
2028
2184
|
} catch (err) {
|
|
2185
|
+
} finally {
|
|
2186
|
+
itemsDone++;
|
|
2187
|
+
indexingJobs.update(project.name, { itemsDone });
|
|
2188
|
+
if (itemsDone % 10 === 0) {
|
|
2189
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
2190
|
+
}
|
|
2029
2191
|
}
|
|
2030
2192
|
}
|
|
2031
2193
|
}
|
|
@@ -2033,15 +2195,28 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2033
2195
|
await scanDir(scanRoot);
|
|
2034
2196
|
rag.markFullIndex();
|
|
2035
2197
|
const stats = rag.getStats();
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2198
|
+
const message = `Indexed ${indexed} files, skipped ${skipped} unchanged. Total: ${stats.totalChunks} chunks from ${stats.totalFiles} files.`;
|
|
2199
|
+
logger.info(`[RAG] ${project.name}: ${message}`);
|
|
2200
|
+
indexingJobs.update(project.name, { currentItem: void 0 });
|
|
2201
|
+
};
|
|
2202
|
+
const startResult = indexingJobs.startOrStatus(project.name, runIndexing);
|
|
2203
|
+
const p = startResult.progress;
|
|
2204
|
+
return {
|
|
2205
|
+
state: startResult.state,
|
|
2206
|
+
status: startResult.status,
|
|
2207
|
+
success: startResult.status === "started" || startResult.status === "already_running",
|
|
2208
|
+
message: startResult.status === "started" ? `Indexing started in background for '${project.name}'.` : `Indexing already running for '${project.name}'.`,
|
|
2209
|
+
filesIndexed: 0,
|
|
2210
|
+
filesSkipped: 0,
|
|
2211
|
+
progress: {
|
|
2212
|
+
itemsDone: p.itemsDone,
|
|
2213
|
+
itemsTotal: p.itemsTotal,
|
|
2214
|
+
currentItem: p.currentItem,
|
|
2215
|
+
startedAt: p.startedAt,
|
|
2216
|
+
completedAt: p.completedAt,
|
|
2217
|
+
lastError: p.lastError
|
|
2218
|
+
}
|
|
2219
|
+
};
|
|
2045
2220
|
}
|
|
2046
2221
|
function getContextPreamble() {
|
|
2047
2222
|
const projects = getExposedProjects();
|
|
@@ -2189,6 +2364,7 @@ var init_resources = __esm({
|
|
|
2189
2364
|
init_detection();
|
|
2190
2365
|
init_detection_service();
|
|
2191
2366
|
init_rag();
|
|
2367
|
+
init_indexing_jobs();
|
|
2192
2368
|
init_paths();
|
|
2193
2369
|
}
|
|
2194
2370
|
});
|
|
@@ -3440,6 +3616,7 @@ var IndexingStatus;
|
|
|
3440
3616
|
var init_IndexingStatus = __esm({
|
|
3441
3617
|
"src/mcp/ui/IndexingStatus.tsx"() {
|
|
3442
3618
|
"use strict";
|
|
3619
|
+
init_indexing_jobs();
|
|
3443
3620
|
init_rag();
|
|
3444
3621
|
init_resources();
|
|
3445
3622
|
init_config_utils();
|
|
@@ -3456,9 +3633,14 @@ var init_IndexingStatus = __esm({
|
|
|
3456
3633
|
}
|
|
3457
3634
|
const enabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled || false;
|
|
3458
3635
|
if (!enabled) {
|
|
3636
|
+
const prog = indexingJobs.getProgress(project.name);
|
|
3459
3637
|
newStats.push({
|
|
3460
3638
|
projectName: project.name,
|
|
3461
3639
|
enabled: false,
|
|
3640
|
+
state: prog.state,
|
|
3641
|
+
itemsDone: prog.itemsDone,
|
|
3642
|
+
itemsTotal: prog.itemsTotal,
|
|
3643
|
+
currentItem: prog.currentItem,
|
|
3462
3644
|
totalFiles: 0,
|
|
3463
3645
|
totalChunks: 0
|
|
3464
3646
|
});
|
|
@@ -3468,17 +3650,27 @@ var init_IndexingStatus = __esm({
|
|
|
3468
3650
|
const indexPath = getRAGIndexPath(project);
|
|
3469
3651
|
const rag = new RAGService(indexPath, "dummy");
|
|
3470
3652
|
const s = rag.getStats();
|
|
3653
|
+
const prog = indexingJobs.getProgress(project.name);
|
|
3471
3654
|
newStats.push({
|
|
3472
3655
|
projectName: project.name,
|
|
3473
3656
|
enabled: true,
|
|
3657
|
+
state: prog.state,
|
|
3658
|
+
itemsDone: prog.itemsDone,
|
|
3659
|
+
itemsTotal: prog.itemsTotal,
|
|
3660
|
+
currentItem: prog.currentItem,
|
|
3474
3661
|
totalFiles: s.totalFiles,
|
|
3475
3662
|
totalChunks: s.totalChunks,
|
|
3476
3663
|
lastFullIndex: s.lastFullIndex
|
|
3477
3664
|
});
|
|
3478
3665
|
} catch (e) {
|
|
3666
|
+
const prog = indexingJobs.getProgress(project.name);
|
|
3479
3667
|
newStats.push({
|
|
3480
3668
|
projectName: project.name,
|
|
3481
3669
|
enabled: true,
|
|
3670
|
+
state: prog.state,
|
|
3671
|
+
itemsDone: prog.itemsDone,
|
|
3672
|
+
itemsTotal: prog.itemsTotal,
|
|
3673
|
+
currentItem: prog.currentItem,
|
|
3482
3674
|
totalFiles: 0,
|
|
3483
3675
|
totalChunks: 0,
|
|
3484
3676
|
error: String(e)
|
|
@@ -3501,13 +3693,16 @@ var init_IndexingStatus = __esm({
|
|
|
3501
3693
|
/* @__PURE__ */ jsxs8(Box9, { children: [
|
|
3502
3694
|
/* @__PURE__ */ jsx9(Box9, { width: 25, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Project" }) }),
|
|
3503
3695
|
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Status" }) }),
|
|
3696
|
+
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "State" }) }),
|
|
3697
|
+
/* @__PURE__ */ jsx9(Box9, { width: 18, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Progress" }) }),
|
|
3504
3698
|
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Indexed Files" }) }),
|
|
3505
3699
|
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Total Chunks" }) }),
|
|
3506
3700
|
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text9, { underline: true, children: "Last Index" }) })
|
|
3507
3701
|
] }),
|
|
3508
3702
|
stats.length === 0 ? /* @__PURE__ */ jsx9(Text9, { color: "dim", children: "No exposed projects found." }) : stats.map((s) => /* @__PURE__ */ jsxs8(Box9, { marginTop: 0, children: [
|
|
3509
3703
|
/* @__PURE__ */ jsx9(Box9, { width: 25, children: /* @__PURE__ */ jsx9(Text9, { color: "white", children: s.projectName }) }),
|
|
3510
|
-
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { color: s.enabled ? "green" : "dim", children: s.enabled ?
|
|
3704
|
+
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { color: s.state === "running" ? "yellow" : s.state === "failed" ? "red" : s.enabled ? "green" : "dim", children: s.enabled ? s.state : "disabled" }) }),
|
|
3705
|
+
/* @__PURE__ */ jsx9(Box9, { width: 18, children: /* @__PURE__ */ jsx9(Text9, { children: s.state === "running" ? `${s.itemsDone}/${s.itemsTotal ?? "?"}` : "-" }) }),
|
|
3511
3706
|
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { children: s.enabled ? s.totalFiles : "-" }) }),
|
|
3512
3707
|
/* @__PURE__ */ jsx9(Box9, { width: 15, children: /* @__PURE__ */ jsx9(Text9, { children: s.enabled ? s.totalChunks : "-" }) }),
|
|
3513
3708
|
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text9, { children: s.lastFullIndex ? new Date(s.lastFullIndex).toLocaleTimeString() : "-" }) })
|