knowns 0.10.1 → 0.10.2
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 +398 -184
- package/dist/mcp/server.js +270 -133
- package/dist/ui/assets/{index-CavOnkoC.js → index-B37hMpJr.js} +62 -62
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -61849,22 +61849,25 @@ var searchCommand = new Command("search").description("Search tasks and document
|
|
|
61849
61849
|
const pathGroups = {};
|
|
61850
61850
|
for (const doc of docResults) {
|
|
61851
61851
|
const parts = doc.filename.split("/");
|
|
61852
|
-
const folder = parts.length > 1 ? `${parts.slice(0, -1).join("/")}/` : "
|
|
61852
|
+
const folder = parts.length > 1 ? `${parts.slice(0, -1).join("/")}/` : "";
|
|
61853
61853
|
if (!pathGroups[folder]) {
|
|
61854
61854
|
pathGroups[folder] = [];
|
|
61855
61855
|
}
|
|
61856
61856
|
pathGroups[folder].push(doc);
|
|
61857
61857
|
}
|
|
61858
61858
|
const sortedPaths = Object.keys(pathGroups).sort((a, b) => {
|
|
61859
|
-
if (a === "
|
|
61860
|
-
if (b === "
|
|
61859
|
+
if (a === "") return -1;
|
|
61860
|
+
if (b === "") return 1;
|
|
61861
61861
|
return a.localeCompare(b);
|
|
61862
61862
|
});
|
|
61863
61863
|
for (const path3 of sortedPaths) {
|
|
61864
|
-
|
|
61864
|
+
if (path3) {
|
|
61865
|
+
console.log(` ${path3}:`);
|
|
61866
|
+
}
|
|
61867
|
+
const indent = path3 ? " " : " ";
|
|
61865
61868
|
for (const doc of pathGroups[path3]) {
|
|
61866
61869
|
const filename = doc.filename.split("/").pop() || doc.filename;
|
|
61867
|
-
console.log(
|
|
61870
|
+
console.log(`${indent}${filename} - ${doc.metadata.title}`);
|
|
61868
61871
|
}
|
|
61869
61872
|
}
|
|
61870
61873
|
}
|
|
@@ -62482,6 +62485,7 @@ function createConfigRoutes(ctx) {
|
|
|
62482
62485
|
name: data.name,
|
|
62483
62486
|
id: data.id,
|
|
62484
62487
|
createdAt: data.createdAt,
|
|
62488
|
+
imports: data.imports,
|
|
62485
62489
|
...settings
|
|
62486
62490
|
};
|
|
62487
62491
|
if (!config2.visibleColumns) {
|
|
@@ -62501,10 +62505,13 @@ function createConfigRoutes(ctx) {
|
|
|
62501
62505
|
const content = await readFile7(configPath, "utf-8");
|
|
62502
62506
|
existingData = JSON.parse(content);
|
|
62503
62507
|
}
|
|
62504
|
-
const { name, ...settings } = config2;
|
|
62508
|
+
const { name, imports, id, createdAt, ...settings } = config2;
|
|
62505
62509
|
const merged = {
|
|
62506
62510
|
...existingData,
|
|
62507
62511
|
name: name || existingData.name,
|
|
62512
|
+
id: id || existingData.id,
|
|
62513
|
+
createdAt: createdAt || existingData.createdAt,
|
|
62514
|
+
imports: imports !== void 0 ? imports : existingData.imports,
|
|
62508
62515
|
settings
|
|
62509
62516
|
};
|
|
62510
62517
|
await writeFile4(configPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
@@ -63966,7 +63973,7 @@ async function importSource(projectRoot, source, options2 = {}) {
|
|
|
63966
63973
|
if (!nameValidation.valid) {
|
|
63967
63974
|
throw new ImportError(nameValidation.error || "Invalid name", "NAME_CONFLICT" /* NAME_CONFLICT */);
|
|
63968
63975
|
}
|
|
63969
|
-
if (!options2.force && await importExists(projectRoot, name)) {
|
|
63976
|
+
if (!options2.force && !options2.isSync && await importExists(projectRoot, name)) {
|
|
63970
63977
|
throw new ImportError(
|
|
63971
63978
|
`Import "${name}" already exists`,
|
|
63972
63979
|
"NAME_CONFLICT" /* NAME_CONFLICT */,
|
|
@@ -64144,8 +64151,10 @@ async function syncImport(projectRoot, name, options2 = {}) {
|
|
|
64144
64151
|
exclude: config2.exclude,
|
|
64145
64152
|
force: options2.force,
|
|
64146
64153
|
dryRun: options2.dryRun,
|
|
64147
|
-
noSave: true
|
|
64154
|
+
noSave: true,
|
|
64148
64155
|
// Don't update config on sync
|
|
64156
|
+
isSync: true
|
|
64157
|
+
// Bypass "already exists" check
|
|
64149
64158
|
});
|
|
64150
64159
|
}
|
|
64151
64160
|
async function syncAllImports(projectRoot, options2 = {}) {
|
|
@@ -64153,7 +64162,7 @@ async function syncAllImports(projectRoot, options2 = {}) {
|
|
|
64153
64162
|
const configs = await getImportConfigs2(projectRoot);
|
|
64154
64163
|
const results = [];
|
|
64155
64164
|
for (const config2 of configs) {
|
|
64156
|
-
if (config2.autoSync === false
|
|
64165
|
+
if (options2.autoOnly && config2.autoSync === false) {
|
|
64157
64166
|
continue;
|
|
64158
64167
|
}
|
|
64159
64168
|
try {
|
|
@@ -64197,7 +64206,38 @@ import { existsSync as existsSync14 } from "node:fs";
|
|
|
64197
64206
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
64198
64207
|
import { join as join17 } from "node:path";
|
|
64199
64208
|
var KNOWNS_DIR5 = ".knowns";
|
|
64209
|
+
var TEMPLATES_DIR2 = "templates";
|
|
64200
64210
|
var DOCS_DIR2 = "docs";
|
|
64211
|
+
async function getTemplateDirectories(projectRoot) {
|
|
64212
|
+
const results = [];
|
|
64213
|
+
const localTemplates = join17(projectRoot, KNOWNS_DIR5, TEMPLATES_DIR2);
|
|
64214
|
+
if (existsSync14(localTemplates)) {
|
|
64215
|
+
results.push({
|
|
64216
|
+
path: localTemplates,
|
|
64217
|
+
source: "local",
|
|
64218
|
+
isImported: false
|
|
64219
|
+
});
|
|
64220
|
+
}
|
|
64221
|
+
const importsDir = getImportsDir(projectRoot);
|
|
64222
|
+
if (existsSync14(importsDir)) {
|
|
64223
|
+
try {
|
|
64224
|
+
const entries = await readdir7(importsDir, { withFileTypes: true });
|
|
64225
|
+
for (const entry of entries) {
|
|
64226
|
+
if (!entry.isDirectory()) continue;
|
|
64227
|
+
const importedTemplates = join17(importsDir, entry.name, TEMPLATES_DIR2);
|
|
64228
|
+
if (existsSync14(importedTemplates)) {
|
|
64229
|
+
results.push({
|
|
64230
|
+
path: importedTemplates,
|
|
64231
|
+
source: entry.name,
|
|
64232
|
+
isImported: true
|
|
64233
|
+
});
|
|
64234
|
+
}
|
|
64235
|
+
}
|
|
64236
|
+
} catch {
|
|
64237
|
+
}
|
|
64238
|
+
}
|
|
64239
|
+
return results;
|
|
64240
|
+
}
|
|
64201
64241
|
async function getDocDirectories(projectRoot) {
|
|
64202
64242
|
const results = [];
|
|
64203
64243
|
const localDocs = join17(projectRoot, KNOWNS_DIR5, DOCS_DIR2);
|
|
@@ -64300,8 +64340,36 @@ async function resolveDocWithContext(projectRoot, docPath, context) {
|
|
|
64300
64340
|
}
|
|
64301
64341
|
return null;
|
|
64302
64342
|
}
|
|
64343
|
+
async function listAllTemplates(projectRoot) {
|
|
64344
|
+
const directories = await getTemplateDirectories(projectRoot);
|
|
64345
|
+
const importConfigs = await getImportConfigs(projectRoot);
|
|
64346
|
+
const sourceUrlMap = new Map(importConfigs.map((c) => [c.name, c.source]));
|
|
64347
|
+
const results = [];
|
|
64348
|
+
for (const dir of directories) {
|
|
64349
|
+
try {
|
|
64350
|
+
const entries = await readdir7(dir.path, { withFileTypes: true });
|
|
64351
|
+
for (const entry of entries) {
|
|
64352
|
+
if (!entry.isDirectory()) continue;
|
|
64353
|
+
if (entry.name.startsWith(".")) continue;
|
|
64354
|
+
const ref = dir.isImported ? `${dir.source}/${entry.name}` : entry.name;
|
|
64355
|
+
results.push({
|
|
64356
|
+
name: entry.name,
|
|
64357
|
+
ref,
|
|
64358
|
+
source: dir.source,
|
|
64359
|
+
sourceUrl: dir.isImported ? sourceUrlMap.get(dir.source) : void 0,
|
|
64360
|
+
path: join17(dir.path, entry.name),
|
|
64361
|
+
isImported: dir.isImported
|
|
64362
|
+
});
|
|
64363
|
+
}
|
|
64364
|
+
} catch {
|
|
64365
|
+
}
|
|
64366
|
+
}
|
|
64367
|
+
return results.sort((a, b) => a.ref.localeCompare(b.ref));
|
|
64368
|
+
}
|
|
64303
64369
|
async function listAllDocs(projectRoot) {
|
|
64304
64370
|
const directories = await getDocDirectories(projectRoot);
|
|
64371
|
+
const importConfigs = await getImportConfigs(projectRoot);
|
|
64372
|
+
const sourceUrlMap = new Map(importConfigs.map((c) => [c.name, c.source]));
|
|
64305
64373
|
const results = [];
|
|
64306
64374
|
async function scanDir(baseDir, relativePath, source, isImported) {
|
|
64307
64375
|
const currentDir = join17(baseDir, relativePath);
|
|
@@ -64319,6 +64387,7 @@ async function listAllDocs(projectRoot) {
|
|
|
64319
64387
|
name: docPath,
|
|
64320
64388
|
ref,
|
|
64321
64389
|
source,
|
|
64390
|
+
sourceUrl: isImported ? sourceUrlMap.get(source) : void 0,
|
|
64322
64391
|
fullPath: join17(currentDir, entry.name),
|
|
64323
64392
|
isImported
|
|
64324
64393
|
});
|
|
@@ -87092,131 +87161,190 @@ var createCommand3 = new Command("create").description("Create a new documentati
|
|
|
87092
87161
|
}
|
|
87093
87162
|
}
|
|
87094
87163
|
);
|
|
87095
|
-
var listCommand2 = new Command("list").description("List all documentation files").argument("[path]", "Filter by path (e.g., 'guides/' or 'patterns/')").option("--plain", "Plain text output for AI").option("-t, --tag <tag>", "Filter by tag").
|
|
87096
|
-
|
|
87097
|
-
|
|
87098
|
-
|
|
87099
|
-
|
|
87100
|
-
|
|
87101
|
-
|
|
87102
|
-
|
|
87103
|
-
|
|
87104
|
-
console.log(source_default.gray(`Create one with: knowns doc create "Title"`));
|
|
87105
|
-
}
|
|
87106
|
-
return;
|
|
87107
|
-
}
|
|
87108
|
-
const docs = [];
|
|
87109
|
-
for (const file3 of mdFiles) {
|
|
87110
|
-
const fileContent = await readFile18(join29(DOCS_DIR3, file3), "utf-8");
|
|
87111
|
-
const { data, content } = (0, import_gray_matter7.default)(fileContent);
|
|
87112
|
-
const stats = calculateDocStats(content);
|
|
87113
|
-
docs.push({
|
|
87114
|
-
filename: file3,
|
|
87115
|
-
metadata: data,
|
|
87116
|
-
tokens: stats.estimatedTokens
|
|
87117
|
-
});
|
|
87118
|
-
}
|
|
87119
|
-
let filteredDocs = docs;
|
|
87120
|
-
if (path3) {
|
|
87121
|
-
const normalizedPath = path3.endsWith("/") ? path3 : `${path3}/`;
|
|
87122
|
-
filteredDocs = docs.filter((doc) => doc.filename.startsWith(normalizedPath));
|
|
87123
|
-
}
|
|
87124
|
-
if (options2.tag) {
|
|
87125
|
-
filteredDocs = filteredDocs.filter((doc) => doc.metadata.tags?.includes(options2.tag));
|
|
87126
|
-
}
|
|
87127
|
-
if (filteredDocs.length === 0) {
|
|
87128
|
-
const filterMsg = path3 ? `path: ${path3}` : options2.tag ? `tag: ${options2.tag}` : "";
|
|
87129
|
-
console.log(
|
|
87130
|
-
options2.plain ? "No documentation found" : source_default.yellow(`No documentation found${filterMsg ? ` with ${filterMsg}` : ""}`)
|
|
87131
|
-
);
|
|
87132
|
-
return;
|
|
87133
|
-
}
|
|
87134
|
-
if (options2.plain) {
|
|
87135
|
-
const folders = /* @__PURE__ */ new Map();
|
|
87136
|
-
const rootDocs = [];
|
|
87137
|
-
for (const doc of filteredDocs) {
|
|
87138
|
-
const parts = doc.filename.split("/");
|
|
87139
|
-
if (parts.length === 1) {
|
|
87140
|
-
rootDocs.push({
|
|
87141
|
-
name: parts[0].replace(/\.md$/, ""),
|
|
87142
|
-
title: doc.metadata.title,
|
|
87143
|
-
tokens: doc.tokens
|
|
87144
|
-
});
|
|
87164
|
+
var listCommand2 = new Command("list").description("List all documentation files (local + imported)").argument("[path]", "Filter by path (e.g., 'guides/' or 'patterns/')").option("--plain", "Plain text output for AI").option("-t, --tag <tag>", "Filter by tag").option("--local", "Show only local docs").option("--imported", "Show only imported docs").action(
|
|
87165
|
+
async (path3, options2) => {
|
|
87166
|
+
try {
|
|
87167
|
+
await ensureDocsDir();
|
|
87168
|
+
const projectRoot = await findProjectRoot() || process.cwd();
|
|
87169
|
+
const allDocs = await listAllDocs(projectRoot);
|
|
87170
|
+
if (allDocs.length === 0) {
|
|
87171
|
+
if (options2.plain) {
|
|
87172
|
+
console.log("No documentation found");
|
|
87145
87173
|
} else {
|
|
87146
|
-
|
|
87147
|
-
|
|
87148
|
-
if (!folders.has(folder)) {
|
|
87149
|
-
folders.set(folder, []);
|
|
87150
|
-
}
|
|
87151
|
-
folders.get(folder)?.push({ name, title: doc.metadata.title, tokens: doc.tokens });
|
|
87174
|
+
console.log(source_default.yellow("No documentation files found."));
|
|
87175
|
+
console.log(source_default.gray(`Create one with: knowns doc create "Title"`));
|
|
87152
87176
|
}
|
|
87177
|
+
return;
|
|
87153
87178
|
}
|
|
87154
|
-
const
|
|
87155
|
-
for (const
|
|
87156
|
-
|
|
87157
|
-
|
|
87158
|
-
|
|
87159
|
-
|
|
87179
|
+
const docs = [];
|
|
87180
|
+
for (const doc of allDocs) {
|
|
87181
|
+
try {
|
|
87182
|
+
const fileContent = await readFile18(doc.fullPath, "utf-8");
|
|
87183
|
+
const { data, content } = (0, import_gray_matter7.default)(fileContent);
|
|
87184
|
+
const stats = calculateDocStats(content);
|
|
87185
|
+
docs.push({
|
|
87186
|
+
ref: doc.ref,
|
|
87187
|
+
name: doc.name,
|
|
87188
|
+
source: doc.source,
|
|
87189
|
+
sourceUrl: doc.sourceUrl,
|
|
87190
|
+
isImported: doc.isImported,
|
|
87191
|
+
fullPath: doc.fullPath,
|
|
87192
|
+
metadata: data,
|
|
87193
|
+
tokens: stats.estimatedTokens
|
|
87194
|
+
});
|
|
87195
|
+
} catch {
|
|
87160
87196
|
}
|
|
87161
87197
|
}
|
|
87162
|
-
|
|
87163
|
-
|
|
87164
|
-
|
|
87165
|
-
|
|
87166
|
-
|
|
87198
|
+
let filteredDocs = docs;
|
|
87199
|
+
if (options2.local) {
|
|
87200
|
+
filteredDocs = docs.filter((doc) => !doc.isImported);
|
|
87201
|
+
} else if (options2.imported) {
|
|
87202
|
+
filteredDocs = docs.filter((doc) => doc.isImported);
|
|
87167
87203
|
}
|
|
87168
|
-
|
|
87169
|
-
|
|
87170
|
-
|
|
87171
|
-
|
|
87172
|
-
|
|
87173
|
-
|
|
87174
|
-
|
|
87175
|
-
|
|
87176
|
-
|
|
87177
|
-
|
|
87178
|
-
|
|
87204
|
+
if (path3) {
|
|
87205
|
+
const normalizedPath = path3.endsWith("/") ? path3 : `${path3}/`;
|
|
87206
|
+
filteredDocs = filteredDocs.filter(
|
|
87207
|
+
(doc) => doc.ref.startsWith(normalizedPath) || doc.name.startsWith(normalizedPath)
|
|
87208
|
+
);
|
|
87209
|
+
}
|
|
87210
|
+
if (options2.tag) {
|
|
87211
|
+
filteredDocs = filteredDocs.filter((doc) => doc.metadata.tags?.includes(options2.tag));
|
|
87212
|
+
}
|
|
87213
|
+
if (filteredDocs.length === 0) {
|
|
87214
|
+
const filterMsg = path3 ? `path: ${path3}` : options2.tag ? `tag: ${options2.tag}` : "";
|
|
87215
|
+
console.log(
|
|
87216
|
+
options2.plain ? "No documentation found" : source_default.yellow(`No documentation found${filterMsg ? ` with ${filterMsg}` : ""}`)
|
|
87217
|
+
);
|
|
87218
|
+
return;
|
|
87219
|
+
}
|
|
87220
|
+
if (options2.plain) {
|
|
87221
|
+
const sources = /* @__PURE__ */ new Map();
|
|
87222
|
+
for (const doc of filteredDocs) {
|
|
87223
|
+
const sourceKey = doc.isImported ? `[${doc.source}]` : "[local]";
|
|
87224
|
+
if (!sources.has(sourceKey)) {
|
|
87225
|
+
sources.set(sourceKey, []);
|
|
87226
|
+
}
|
|
87227
|
+
sources.get(sourceKey)?.push(doc);
|
|
87228
|
+
}
|
|
87229
|
+
const sortedSources = Array.from(sources.keys()).sort((a, b) => {
|
|
87230
|
+
if (a === "[local]") return -1;
|
|
87231
|
+
if (b === "[local]") return 1;
|
|
87232
|
+
return a.localeCompare(b);
|
|
87233
|
+
});
|
|
87234
|
+
for (const sourceKey of sortedSources) {
|
|
87235
|
+
const sourceDocs = sources.get(sourceKey) || [];
|
|
87236
|
+
const sourceUrl = sourceDocs[0]?.sourceUrl;
|
|
87237
|
+
if (sourceUrl) {
|
|
87238
|
+
console.log(`${sourceKey} (${sourceUrl})`);
|
|
87239
|
+
} else {
|
|
87240
|
+
console.log(`${sourceKey}`);
|
|
87241
|
+
}
|
|
87242
|
+
const folders = /* @__PURE__ */ new Map();
|
|
87243
|
+
const rootDocs = [];
|
|
87244
|
+
for (const doc of sourceDocs) {
|
|
87245
|
+
const parts = doc.name.split("/");
|
|
87246
|
+
if (parts.length === 1) {
|
|
87247
|
+
rootDocs.push({
|
|
87248
|
+
name: parts[0],
|
|
87249
|
+
title: doc.metadata.title || parts[0],
|
|
87250
|
+
tokens: doc.tokens
|
|
87251
|
+
});
|
|
87252
|
+
} else {
|
|
87253
|
+
const folder = parts.slice(0, -1).join("/");
|
|
87254
|
+
const name = parts[parts.length - 1];
|
|
87255
|
+
if (!folders.has(folder)) {
|
|
87256
|
+
folders.set(folder, []);
|
|
87257
|
+
}
|
|
87258
|
+
folders.get(folder)?.push({ name, title: doc.metadata.title || name, tokens: doc.tokens });
|
|
87259
|
+
}
|
|
87260
|
+
}
|
|
87261
|
+
const sortedFolders = Array.from(folders.keys()).sort();
|
|
87262
|
+
for (const folder of sortedFolders) {
|
|
87263
|
+
console.log(` ${folder}/`);
|
|
87264
|
+
const folderDocs = folders.get(folder)?.sort((a, b) => a.name.localeCompare(b.name));
|
|
87265
|
+
for (const doc of folderDocs || []) {
|
|
87266
|
+
console.log(` ${doc.name} - ${doc.title} (~${doc.tokens} tokens)`);
|
|
87267
|
+
}
|
|
87268
|
+
}
|
|
87269
|
+
if (rootDocs.length > 0) {
|
|
87270
|
+
rootDocs.sort((a, b) => a.name.localeCompare(b.name));
|
|
87271
|
+
for (const doc of rootDocs) {
|
|
87272
|
+
console.log(` ${doc.name} - ${doc.title} (~${doc.tokens} tokens)`);
|
|
87273
|
+
}
|
|
87179
87274
|
}
|
|
87180
|
-
folders.get(folder)?.push(doc);
|
|
87181
87275
|
}
|
|
87182
|
-
}
|
|
87183
|
-
|
|
87276
|
+
} else {
|
|
87277
|
+
const sources = /* @__PURE__ */ new Map();
|
|
87278
|
+
for (const doc of filteredDocs) {
|
|
87279
|
+
const sourceKey = doc.isImported ? doc.source : "local";
|
|
87280
|
+
if (!sources.has(sourceKey)) {
|
|
87281
|
+
sources.set(sourceKey, []);
|
|
87282
|
+
}
|
|
87283
|
+
sources.get(sourceKey)?.push(doc);
|
|
87284
|
+
}
|
|
87285
|
+
const sortedSources = Array.from(sources.keys()).sort((a, b) => {
|
|
87286
|
+
if (a === "local") return -1;
|
|
87287
|
+
if (b === "local") return 1;
|
|
87288
|
+
return a.localeCompare(b);
|
|
87289
|
+
});
|
|
87290
|
+
console.log(source_default.bold(`
|
|
87184
87291
|
Documentation (${filteredDocs.length})
|
|
87185
87292
|
`));
|
|
87186
|
-
|
|
87187
|
-
|
|
87188
|
-
|
|
87189
|
-
|
|
87190
|
-
|
|
87191
|
-
|
|
87192
|
-
|
|
87193
|
-
console.log(source_default.
|
|
87194
|
-
}
|
|
87195
|
-
|
|
87196
|
-
|
|
87293
|
+
for (const sourceKey of sortedSources) {
|
|
87294
|
+
const sourceDocs = sources.get(sourceKey) || [];
|
|
87295
|
+
const sourceUrl = sourceDocs[0]?.sourceUrl;
|
|
87296
|
+
const sourceLabel = sourceKey === "local" ? "Local" : `Import: ${sourceKey}`;
|
|
87297
|
+
if (sourceUrl) {
|
|
87298
|
+
console.log(source_default.magenta.bold(`[${sourceLabel}]`) + source_default.gray(` ${sourceUrl}`));
|
|
87299
|
+
} else {
|
|
87300
|
+
console.log(source_default.magenta.bold(`[${sourceLabel}]`));
|
|
87301
|
+
}
|
|
87302
|
+
const folders = /* @__PURE__ */ new Map();
|
|
87303
|
+
const rootDocs = [];
|
|
87304
|
+
for (const doc of sourceDocs) {
|
|
87305
|
+
const parts = doc.name.split("/");
|
|
87306
|
+
if (parts.length === 1) {
|
|
87307
|
+
rootDocs.push(doc);
|
|
87308
|
+
} else {
|
|
87309
|
+
const folder = parts.slice(0, -1).join("/");
|
|
87310
|
+
if (!folders.has(folder)) {
|
|
87311
|
+
folders.set(folder, []);
|
|
87312
|
+
}
|
|
87313
|
+
folders.get(folder)?.push(doc);
|
|
87314
|
+
}
|
|
87197
87315
|
}
|
|
87198
|
-
|
|
87199
|
-
|
|
87200
|
-
|
|
87201
|
-
|
|
87202
|
-
|
|
87203
|
-
|
|
87204
|
-
|
|
87205
|
-
|
|
87206
|
-
|
|
87316
|
+
const sortedFolders = Array.from(folders.keys()).sort();
|
|
87317
|
+
for (const folder of sortedFolders) {
|
|
87318
|
+
console.log(source_default.cyan.bold(` ${folder}/`));
|
|
87319
|
+
const folderDocs = folders.get(folder)?.sort((a, b) => (a.metadata.title || "").localeCompare(b.metadata.title || ""));
|
|
87320
|
+
for (const doc of folderDocs || []) {
|
|
87321
|
+
console.log(source_default.white(` ${doc.metadata.title || doc.name}`));
|
|
87322
|
+
if (doc.metadata.description) {
|
|
87323
|
+
console.log(source_default.gray(` ${doc.metadata.description}`));
|
|
87324
|
+
}
|
|
87325
|
+
}
|
|
87207
87326
|
}
|
|
87208
|
-
if (
|
|
87209
|
-
|
|
87327
|
+
if (rootDocs.length > 0) {
|
|
87328
|
+
rootDocs.sort((a, b) => (a.metadata.title || "").localeCompare(b.metadata.title || ""));
|
|
87329
|
+
for (const doc of rootDocs) {
|
|
87330
|
+
console.log(source_default.white(` ${doc.metadata.title || doc.name}`));
|
|
87331
|
+
if (doc.metadata.description) {
|
|
87332
|
+
console.log(source_default.gray(` ${doc.metadata.description}`));
|
|
87333
|
+
}
|
|
87334
|
+
}
|
|
87210
87335
|
}
|
|
87211
87336
|
console.log();
|
|
87212
87337
|
}
|
|
87213
87338
|
}
|
|
87339
|
+
} catch (error48) {
|
|
87340
|
+
console.error(
|
|
87341
|
+
source_default.red("Error listing documentation:"),
|
|
87342
|
+
error48 instanceof Error ? error48.message : String(error48)
|
|
87343
|
+
);
|
|
87344
|
+
process.exit(1);
|
|
87214
87345
|
}
|
|
87215
|
-
} catch (error48) {
|
|
87216
|
-
console.error(source_default.red("Error listing documentation:"), error48 instanceof Error ? error48.message : String(error48));
|
|
87217
|
-
process.exit(1);
|
|
87218
87346
|
}
|
|
87219
|
-
|
|
87347
|
+
);
|
|
87220
87348
|
var viewCommand2 = new Command("view").description("View a documentation file").argument("<name>", "Document name (filename or title or path)").option("--plain", "Plain text output for AI").option("--info", "Show document stats (size, tokens, headings) without content").option("--toc", "Show table of contents only").option("--section <title>", "Show specific section by heading title or number (e.g., '2. Overview' or '2')").option("--smart", "Smart mode: auto-return full content if small, or stats+TOC if large (>2000 tokens)").action(
|
|
87221
87349
|
async (name, options2) => {
|
|
87222
87350
|
try {
|
|
@@ -96471,8 +96599,9 @@ async function resolveDocPath2(name) {
|
|
|
96471
96599
|
async function handleListDocs(args2) {
|
|
96472
96600
|
const input = listDocsSchema.parse(args2);
|
|
96473
96601
|
await ensureDocsDir2();
|
|
96474
|
-
const
|
|
96475
|
-
|
|
96602
|
+
const projectRoot = process.cwd();
|
|
96603
|
+
const allDocs = await listAllDocs(projectRoot);
|
|
96604
|
+
if (allDocs.length === 0) {
|
|
96476
96605
|
return successResponse({
|
|
96477
96606
|
count: 0,
|
|
96478
96607
|
docs: [],
|
|
@@ -96480,22 +96609,29 @@ async function handleListDocs(args2) {
|
|
|
96480
96609
|
});
|
|
96481
96610
|
}
|
|
96482
96611
|
const docs = [];
|
|
96483
|
-
for (const
|
|
96484
|
-
|
|
96485
|
-
|
|
96486
|
-
|
|
96487
|
-
|
|
96488
|
-
|
|
96489
|
-
|
|
96612
|
+
for (const doc of allDocs) {
|
|
96613
|
+
try {
|
|
96614
|
+
const fileContent = await readFile21(doc.fullPath, "utf-8");
|
|
96615
|
+
const { data, content } = (0, import_gray_matter9.default)(fileContent);
|
|
96616
|
+
const metadata = data;
|
|
96617
|
+
const stats = calculateDocStats(content);
|
|
96618
|
+
if (input.tag && !metadata.tags?.includes(input.tag)) {
|
|
96619
|
+
continue;
|
|
96620
|
+
}
|
|
96621
|
+
docs.push({
|
|
96622
|
+
path: doc.ref,
|
|
96623
|
+
// Use full ref path (includes import prefix if imported)
|
|
96624
|
+
title: metadata.title || doc.name,
|
|
96625
|
+
description: metadata.description,
|
|
96626
|
+
tags: metadata.tags,
|
|
96627
|
+
tokens: stats.estimatedTokens,
|
|
96628
|
+
updatedAt: metadata.updatedAt,
|
|
96629
|
+
source: doc.source,
|
|
96630
|
+
sourceUrl: doc.sourceUrl,
|
|
96631
|
+
isImported: doc.isImported
|
|
96632
|
+
});
|
|
96633
|
+
} catch {
|
|
96490
96634
|
}
|
|
96491
|
-
docs.push({
|
|
96492
|
-
path: file3.replace(/\.md$/, ""),
|
|
96493
|
-
title: metadata.title || file3.replace(/\.md$/, ""),
|
|
96494
|
-
description: metadata.description,
|
|
96495
|
-
tags: metadata.tags,
|
|
96496
|
-
tokens: stats.estimatedTokens,
|
|
96497
|
-
updatedAt: metadata.updatedAt
|
|
96498
|
-
});
|
|
96499
96635
|
}
|
|
96500
96636
|
return successResponse({
|
|
96501
96637
|
count: docs.length,
|
|
@@ -96803,7 +96939,7 @@ async function handleGetGuideline(args2) {
|
|
|
96803
96939
|
import { existsSync as existsSync29 } from "node:fs";
|
|
96804
96940
|
import { mkdir as mkdir18, writeFile as writeFile16 } from "node:fs/promises";
|
|
96805
96941
|
import { join as join34 } from "node:path";
|
|
96806
|
-
var
|
|
96942
|
+
var TEMPLATES_DIR3 = join34(process.cwd(), ".knowns", "templates");
|
|
96807
96943
|
var listTemplatesSchema = external_exports.object({});
|
|
96808
96944
|
var getTemplateSchema = external_exports.object({
|
|
96809
96945
|
name: external_exports.string()
|
|
@@ -96896,30 +97032,45 @@ var templateTools = [
|
|
|
96896
97032
|
];
|
|
96897
97033
|
async function handleListTemplates(_args) {
|
|
96898
97034
|
listTemplatesSchema.parse(_args);
|
|
96899
|
-
|
|
96900
|
-
return successResponse({
|
|
96901
|
-
count: 0,
|
|
96902
|
-
templates: [],
|
|
96903
|
-
message: "No templates directory found. Create templates in .knowns/templates/"
|
|
96904
|
-
});
|
|
96905
|
-
}
|
|
97035
|
+
const projectRoot = process.cwd();
|
|
96906
97036
|
try {
|
|
96907
|
-
const
|
|
96908
|
-
if (
|
|
97037
|
+
const allTemplates = await listAllTemplates(projectRoot);
|
|
97038
|
+
if (allTemplates.length === 0) {
|
|
96909
97039
|
return successResponse({
|
|
96910
97040
|
count: 0,
|
|
96911
97041
|
templates: [],
|
|
96912
|
-
message: "No templates found in .knowns/templates/"
|
|
97042
|
+
message: "No templates found. Create templates in .knowns/templates/"
|
|
96913
97043
|
});
|
|
96914
97044
|
}
|
|
96915
|
-
const templateList =
|
|
96916
|
-
|
|
96917
|
-
|
|
96918
|
-
|
|
96919
|
-
|
|
96920
|
-
|
|
96921
|
-
|
|
96922
|
-
|
|
97045
|
+
const templateList = [];
|
|
97046
|
+
for (const t of allTemplates) {
|
|
97047
|
+
try {
|
|
97048
|
+
const loaded = await listTemplates(join34(t.path, ".."));
|
|
97049
|
+
const match2 = loaded.find((l) => l.name === t.name);
|
|
97050
|
+
templateList.push({
|
|
97051
|
+
name: t.name,
|
|
97052
|
+
ref: t.ref,
|
|
97053
|
+
description: match2?.description || "No description",
|
|
97054
|
+
doc: match2?.doc,
|
|
97055
|
+
promptCount: match2?.prompts?.length || 0,
|
|
97056
|
+
fileCount: match2?.files?.length || 0,
|
|
97057
|
+
source: t.source,
|
|
97058
|
+
sourceUrl: t.sourceUrl,
|
|
97059
|
+
isImported: t.isImported
|
|
97060
|
+
});
|
|
97061
|
+
} catch {
|
|
97062
|
+
templateList.push({
|
|
97063
|
+
name: t.name,
|
|
97064
|
+
ref: t.ref,
|
|
97065
|
+
description: "No description",
|
|
97066
|
+
promptCount: 0,
|
|
97067
|
+
fileCount: 0,
|
|
97068
|
+
source: t.source,
|
|
97069
|
+
sourceUrl: t.sourceUrl,
|
|
97070
|
+
isImported: t.isImported
|
|
97071
|
+
});
|
|
97072
|
+
}
|
|
97073
|
+
}
|
|
96923
97074
|
return successResponse({
|
|
96924
97075
|
count: templateList.length,
|
|
96925
97076
|
templates: templateList
|
|
@@ -96930,11 +97081,11 @@ async function handleListTemplates(_args) {
|
|
|
96930
97081
|
}
|
|
96931
97082
|
async function handleGetTemplate(args2) {
|
|
96932
97083
|
const input = getTemplateSchema.parse(args2);
|
|
96933
|
-
if (!existsSync29(
|
|
97084
|
+
if (!existsSync29(TEMPLATES_DIR3)) {
|
|
96934
97085
|
return errorResponse("No templates directory found");
|
|
96935
97086
|
}
|
|
96936
97087
|
try {
|
|
96937
|
-
const template = await loadTemplateByName(input.name,
|
|
97088
|
+
const template = await loadTemplateByName(input.name, TEMPLATES_DIR3);
|
|
96938
97089
|
if (!template) {
|
|
96939
97090
|
return errorResponse(`Template not found: ${input.name}`);
|
|
96940
97091
|
}
|
|
@@ -96970,11 +97121,11 @@ async function handleGetTemplate(args2) {
|
|
|
96970
97121
|
async function handleRunTemplate(args2) {
|
|
96971
97122
|
const input = runTemplateSchema.parse(args2);
|
|
96972
97123
|
const dryRun = input.dryRun !== false;
|
|
96973
|
-
if (!existsSync29(
|
|
97124
|
+
if (!existsSync29(TEMPLATES_DIR3)) {
|
|
96974
97125
|
return errorResponse("No templates directory found");
|
|
96975
97126
|
}
|
|
96976
97127
|
try {
|
|
96977
|
-
const template = await loadTemplateByName(input.name,
|
|
97128
|
+
const template = await loadTemplateByName(input.name, TEMPLATES_DIR3);
|
|
96978
97129
|
if (!template) {
|
|
96979
97130
|
return errorResponse(`Template not found: ${input.name}`);
|
|
96980
97131
|
}
|
|
@@ -97022,10 +97173,10 @@ async function handleRunTemplate(args2) {
|
|
|
97022
97173
|
async function handleCreateTemplate(args2) {
|
|
97023
97174
|
const input = createTemplateSchema.parse(args2);
|
|
97024
97175
|
try {
|
|
97025
|
-
if (!existsSync29(
|
|
97026
|
-
await mkdir18(
|
|
97176
|
+
if (!existsSync29(TEMPLATES_DIR3)) {
|
|
97177
|
+
await mkdir18(TEMPLATES_DIR3, { recursive: true });
|
|
97027
97178
|
}
|
|
97028
|
-
const templateDir = join34(
|
|
97179
|
+
const templateDir = join34(TEMPLATES_DIR3, input.name);
|
|
97029
97180
|
if (existsSync29(templateDir)) {
|
|
97030
97181
|
return errorResponse(`Template "${input.name}" already exists`);
|
|
97031
97182
|
}
|
|
@@ -97645,7 +97796,7 @@ function showConfigInfo() {
|
|
|
97645
97796
|
import { existsSync as existsSync33 } from "node:fs";
|
|
97646
97797
|
import { mkdir as mkdir19, writeFile as writeFile17 } from "node:fs/promises";
|
|
97647
97798
|
import { join as join38 } from "node:path";
|
|
97648
|
-
var
|
|
97799
|
+
var TEMPLATES_DIR4 = ".knowns/templates";
|
|
97649
97800
|
function getProjectRoot3() {
|
|
97650
97801
|
const projectRoot = findProjectRoot();
|
|
97651
97802
|
if (!projectRoot) {
|
|
@@ -97656,7 +97807,7 @@ function getProjectRoot3() {
|
|
|
97656
97807
|
return projectRoot;
|
|
97657
97808
|
}
|
|
97658
97809
|
function getTemplatesDir(projectRoot) {
|
|
97659
|
-
return join38(projectRoot,
|
|
97810
|
+
return join38(projectRoot, TEMPLATES_DIR4);
|
|
97660
97811
|
}
|
|
97661
97812
|
async function ensureTemplatesDir(projectRoot) {
|
|
97662
97813
|
const templatesDir = getTemplatesDir(projectRoot);
|
|
@@ -97666,20 +97817,16 @@ async function ensureTemplatesDir(projectRoot) {
|
|
|
97666
97817
|
return templatesDir;
|
|
97667
97818
|
}
|
|
97668
97819
|
var templateCommand = new Command("template").description("Manage code generation templates").enablePositionalOptions();
|
|
97669
|
-
var listCommand4 = new Command("list").description("List available templates").option("--plain", "Plain text output for AI").action(async (options2) => {
|
|
97820
|
+
var listCommand4 = new Command("list").description("List available templates (local + imported)").option("--plain", "Plain text output for AI").option("--local", "Show only local templates").option("--imported", "Show only imported templates").action(async (options2) => {
|
|
97670
97821
|
try {
|
|
97671
97822
|
const projectRoot = getProjectRoot3();
|
|
97672
|
-
const
|
|
97673
|
-
|
|
97674
|
-
|
|
97675
|
-
|
|
97676
|
-
|
|
97677
|
-
|
|
97678
|
-
console.log(source_default.gray(" Create one with: knowns template create <name>"));
|
|
97679
|
-
}
|
|
97680
|
-
return;
|
|
97823
|
+
const allTemplates = await listAllTemplates(projectRoot);
|
|
97824
|
+
let templates = allTemplates;
|
|
97825
|
+
if (options2.local) {
|
|
97826
|
+
templates = allTemplates.filter((t) => !t.isImported);
|
|
97827
|
+
} else if (options2.imported) {
|
|
97828
|
+
templates = allTemplates.filter((t) => t.isImported);
|
|
97681
97829
|
}
|
|
97682
|
-
const templates = await listTemplates(templatesDir);
|
|
97683
97830
|
if (templates.length === 0) {
|
|
97684
97831
|
if (options2.plain) {
|
|
97685
97832
|
console.log("No templates found");
|
|
@@ -97689,21 +97836,88 @@ var listCommand4 = new Command("list").description("List available templates").o
|
|
|
97689
97836
|
}
|
|
97690
97837
|
return;
|
|
97691
97838
|
}
|
|
97839
|
+
const templatesWithDesc = [];
|
|
97840
|
+
for (const t of templates) {
|
|
97841
|
+
try {
|
|
97842
|
+
const loaded = await listTemplates(join38(t.path, ".."));
|
|
97843
|
+
const match2 = loaded.find((l) => l.name === t.name);
|
|
97844
|
+
templatesWithDesc.push({
|
|
97845
|
+
ref: t.ref,
|
|
97846
|
+
name: t.name,
|
|
97847
|
+
source: t.source,
|
|
97848
|
+
sourceUrl: t.sourceUrl,
|
|
97849
|
+
isImported: t.isImported,
|
|
97850
|
+
description: match2?.description || "No description"
|
|
97851
|
+
});
|
|
97852
|
+
} catch {
|
|
97853
|
+
templatesWithDesc.push({
|
|
97854
|
+
ref: t.ref,
|
|
97855
|
+
name: t.name,
|
|
97856
|
+
source: t.source,
|
|
97857
|
+
sourceUrl: t.sourceUrl,
|
|
97858
|
+
isImported: t.isImported,
|
|
97859
|
+
description: "No description"
|
|
97860
|
+
});
|
|
97861
|
+
}
|
|
97862
|
+
}
|
|
97692
97863
|
if (options2.plain) {
|
|
97693
|
-
|
|
97694
|
-
|
|
97864
|
+
const sources = /* @__PURE__ */ new Map();
|
|
97865
|
+
for (const t of templatesWithDesc) {
|
|
97866
|
+
const sourceKey = t.isImported ? `[${t.source}]` : "[local]";
|
|
97867
|
+
if (!sources.has(sourceKey)) {
|
|
97868
|
+
sources.set(sourceKey, []);
|
|
97869
|
+
}
|
|
97870
|
+
sources.get(sourceKey)?.push(t);
|
|
97871
|
+
}
|
|
97872
|
+
const sortedSources = Array.from(sources.keys()).sort((a, b) => {
|
|
97873
|
+
if (a === "[local]") return -1;
|
|
97874
|
+
if (b === "[local]") return 1;
|
|
97875
|
+
return a.localeCompare(b);
|
|
97876
|
+
});
|
|
97877
|
+
for (const sourceKey of sortedSources) {
|
|
97878
|
+
const sourceTemplates = sources.get(sourceKey) || [];
|
|
97879
|
+
const sourceUrl = sourceTemplates[0]?.sourceUrl;
|
|
97880
|
+
if (sourceUrl) {
|
|
97881
|
+
console.log(`${sourceKey} (${sourceUrl})`);
|
|
97882
|
+
} else {
|
|
97883
|
+
console.log(sourceKey);
|
|
97884
|
+
}
|
|
97885
|
+
for (const t of sourceTemplates) {
|
|
97886
|
+
console.log(` ${t.name} - ${t.description}`);
|
|
97887
|
+
}
|
|
97695
97888
|
}
|
|
97696
97889
|
} else {
|
|
97697
97890
|
console.log(source_default.bold("\nTemplates:\n"));
|
|
97698
|
-
const
|
|
97699
|
-
|
|
97700
|
-
|
|
97701
|
-
|
|
97702
|
-
|
|
97703
|
-
|
|
97704
|
-
|
|
97891
|
+
const sources = /* @__PURE__ */ new Map();
|
|
97892
|
+
for (const t of templatesWithDesc) {
|
|
97893
|
+
const sourceKey = t.isImported ? t.source : "local";
|
|
97894
|
+
if (!sources.has(sourceKey)) {
|
|
97895
|
+
sources.set(sourceKey, []);
|
|
97896
|
+
}
|
|
97897
|
+
sources.get(sourceKey)?.push(t);
|
|
97898
|
+
}
|
|
97899
|
+
const sortedSources = Array.from(sources.keys()).sort((a, b) => {
|
|
97900
|
+
if (a === "local") return -1;
|
|
97901
|
+
if (b === "local") return 1;
|
|
97902
|
+
return a.localeCompare(b);
|
|
97903
|
+
});
|
|
97904
|
+
for (const sourceKey of sortedSources) {
|
|
97905
|
+
const sourceTemplates = sources.get(sourceKey) || [];
|
|
97906
|
+
const sourceUrl = sourceTemplates[0]?.sourceUrl;
|
|
97907
|
+
const sourceLabel = sourceKey === "local" ? "Local" : `Import: ${sourceKey}`;
|
|
97908
|
+
if (sourceUrl) {
|
|
97909
|
+
console.log(source_default.magenta.bold(`[${sourceLabel}]`) + source_default.gray(` ${sourceUrl}`));
|
|
97910
|
+
} else {
|
|
97911
|
+
console.log(source_default.magenta.bold(`[${sourceLabel}]`));
|
|
97912
|
+
}
|
|
97913
|
+
const maxNameLen = Math.max(...sourceTemplates.map((t) => t.name.length), 4);
|
|
97914
|
+
for (const t of sourceTemplates) {
|
|
97915
|
+
const name = source_default.cyan(t.name.padEnd(maxNameLen + 2));
|
|
97916
|
+
const desc = t.description || source_default.gray("No description");
|
|
97917
|
+
console.log(` ${name}${desc}`);
|
|
97918
|
+
}
|
|
97919
|
+
console.log();
|
|
97705
97920
|
}
|
|
97706
|
-
console.log();
|
|
97707
97921
|
}
|
|
97708
97922
|
} catch (error48) {
|
|
97709
97923
|
console.error(source_default.red("Error:"), error48 instanceof Error ? error48.message : String(error48));
|
|
@@ -97831,7 +98045,7 @@ export function {{camelCase name}}() {
|
|
|
97831
98045
|
await writeFile17(join38(templateDir, "example.ts.hbs"), exampleTemplate, "utf-8");
|
|
97832
98046
|
console.log();
|
|
97833
98047
|
console.log(source_default.green(`\u2713 Created template: ${name}`));
|
|
97834
|
-
console.log(source_default.gray(` Location: ${
|
|
98048
|
+
console.log(source_default.gray(` Location: ${TEMPLATES_DIR4}/${name}/`));
|
|
97835
98049
|
console.log();
|
|
97836
98050
|
console.log(source_default.cyan("Files created:"));
|
|
97837
98051
|
console.log(source_default.gray(" - _template.yaml (config)"));
|
|
@@ -98636,7 +98850,7 @@ async function notifyCliUpdate(options2) {
|
|
|
98636
98850
|
// package.json
|
|
98637
98851
|
var package_default = {
|
|
98638
98852
|
name: "knowns",
|
|
98639
|
-
version: "0.10.
|
|
98853
|
+
version: "0.10.2",
|
|
98640
98854
|
description: "AI-native task and documentation management for dev teams",
|
|
98641
98855
|
module: "index.ts",
|
|
98642
98856
|
type: "module",
|