ai-advisory-board 0.1.1 → 0.2.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/CHANGELOG.md +10 -0
- package/dist/bin/aab.js +39 -7
- package/dist/bin/aab.js.map +1 -1
- package/gui/app.js +226 -27
- package/gui/style.css +81 -2
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# CHANGELOG — AI Advisory Board CLI
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- cc1521a: Knowledge & discussion UI improvements:
|
|
8
|
+
|
|
9
|
+
- **Multi-source ingest** — the web UI Ingest panel now accepts multiple URLs (one per line) plus native file and folder pickers alongside pasted text. Picked files upload their content to the local server (browsers never expose absolute paths), are filtered to ingestible text/doc types with a 20 MB cap, and are ingested sequentially with per-item progress. New `ingestFileBuffer()` core function and a `file: { name, contentBase64 }` variant on `POST /api/knowledge/ingest`.
|
|
10
|
+
- **Markdown rendering in board-member answers** — member responses now render markdown (bold, headings, lists, inline code, code fences, blockquotes, and `[[wikilinks]]`) instead of showing raw markers.
|
|
11
|
+
- **Add action steps to the Action Board from a discussion** — each suggested action step now has a "+ Add" button that creates a linked action item (attributed to the advising member) without leaving the discussion view.
|
|
12
|
+
|
|
3
13
|
## 0.1.1
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/bin/aab.js
CHANGED
|
@@ -5807,10 +5807,26 @@ async function ingestFile(opts) {
|
|
|
5807
5807
|
throw new UserError(`ingest: not a file: ${opts.path}`);
|
|
5808
5808
|
}
|
|
5809
5809
|
const buf = readFileSync13(opts.path);
|
|
5810
|
+
return ingestFileBuffer({
|
|
5811
|
+
buffer: buf,
|
|
5812
|
+
originalName: basename3(opts.path),
|
|
5813
|
+
workspace: opts.workspace,
|
|
5814
|
+
settings: opts.settings,
|
|
5815
|
+
force: opts.force,
|
|
5816
|
+
hintType: opts.hintType,
|
|
5817
|
+
modelOverride: opts.modelOverride
|
|
5818
|
+
});
|
|
5819
|
+
}
|
|
5820
|
+
async function ingestFileBuffer(opts) {
|
|
5821
|
+
const buf = opts.buffer;
|
|
5822
|
+
if (!buf || buf.length === 0) {
|
|
5823
|
+
throw new UserError("ingest: file is empty.");
|
|
5824
|
+
}
|
|
5825
|
+
const leaf = basename3(opts.originalName.replace(/\\/g, "/")) || "upload";
|
|
5810
5826
|
const hash = sha256Hex(buf);
|
|
5811
5827
|
const h6 = hash.slice(0, 6);
|
|
5812
|
-
const ext = extname(
|
|
5813
|
-
const sanitizedName = sanitizeFilename(basename3(
|
|
5828
|
+
const ext = extname(leaf).toLowerCase() || ".md";
|
|
5829
|
+
const sanitizedName = sanitizeFilename(basename3(leaf, extname(leaf)));
|
|
5814
5830
|
const rawFilename = `${h6}-${sanitizedName}${ext}`;
|
|
5815
5831
|
const p = paths(opts.workspace.root);
|
|
5816
5832
|
ensureWikiDirs(opts.workspace.root);
|
|
@@ -5821,7 +5837,7 @@ async function ingestFile(opts) {
|
|
|
5821
5837
|
}
|
|
5822
5838
|
const rawRelPath = toPosix(relative2(opts.workspace.root, rawPath));
|
|
5823
5839
|
let inlineBody;
|
|
5824
|
-
if ([".md", ".txt", ".json", ".csv", ".yaml", ".yml"].includes(ext)) {
|
|
5840
|
+
if ([".md", ".markdown", ".txt", ".json", ".csv", ".tsv", ".yaml", ".yml"].includes(ext)) {
|
|
5825
5841
|
try {
|
|
5826
5842
|
inlineBody = buf.toString("utf8");
|
|
5827
5843
|
} catch {
|
|
@@ -5835,7 +5851,7 @@ async function ingestFile(opts) {
|
|
|
5835
5851
|
rawRelPath,
|
|
5836
5852
|
sourceType: "file",
|
|
5837
5853
|
hash,
|
|
5838
|
-
originalName:
|
|
5854
|
+
originalName: opts.originalName,
|
|
5839
5855
|
hintType: opts.hintType,
|
|
5840
5856
|
inlineBody,
|
|
5841
5857
|
force: opts.force,
|
|
@@ -11973,7 +11989,12 @@ async function startUiServer(opts) {
|
|
|
11973
11989
|
const projectRoot = opts.projectRoot ?? process.cwd();
|
|
11974
11990
|
const guiDir = resolveGuiDir();
|
|
11975
11991
|
const app = express();
|
|
11976
|
-
|
|
11992
|
+
const jsonStd = express.json({ limit: "256kb" });
|
|
11993
|
+
const jsonLarge = express.json({ limit: "64mb" });
|
|
11994
|
+
app.use((req, res, next) => {
|
|
11995
|
+
if (req.method === "POST" && req.path === "/api/knowledge/ingest") return jsonLarge(req, res, next);
|
|
11996
|
+
return jsonStd(req, res, next);
|
|
11997
|
+
});
|
|
11977
11998
|
const sockets = /* @__PURE__ */ new Set();
|
|
11978
11999
|
const broadcast = (evt) => {
|
|
11979
12000
|
const data = JSON.stringify(evt);
|
|
@@ -13214,16 +13235,27 @@ async function startUiServer(opts) {
|
|
|
13214
13235
|
const body = req.body ?? {};
|
|
13215
13236
|
const workspace = resolveWorkspaceForWiki();
|
|
13216
13237
|
const settings = await opts.storage.loadSettings();
|
|
13217
|
-
|
|
13238
|
+
const sourceType = body.url ? "url" : body.path || body.file ? "file" : "pasted";
|
|
13239
|
+
broadcast({ type: "wiki_ingest_started", sourceType });
|
|
13218
13240
|
let result;
|
|
13219
13241
|
if (body.paste) {
|
|
13220
13242
|
result = await ingestPaste({ text: body.paste, workspace, settings, force: body.force, hintType: body.type });
|
|
13221
13243
|
} else if (body.url) {
|
|
13222
13244
|
result = await ingestUrl({ url: body.url, workspace, settings, force: body.force, hintType: body.type });
|
|
13245
|
+
} else if (body.file?.contentBase64) {
|
|
13246
|
+
const buffer = Buffer.from(body.file.contentBase64, "base64");
|
|
13247
|
+
result = await ingestFileBuffer({
|
|
13248
|
+
buffer,
|
|
13249
|
+
originalName: body.file.name?.trim() || "upload",
|
|
13250
|
+
workspace,
|
|
13251
|
+
settings,
|
|
13252
|
+
force: body.force,
|
|
13253
|
+
hintType: body.type
|
|
13254
|
+
});
|
|
13223
13255
|
} else if (body.path) {
|
|
13224
13256
|
result = await ingestFile({ path: body.path, workspace, settings, force: body.force, hintType: body.type });
|
|
13225
13257
|
} else {
|
|
13226
|
-
res.status(400).json({ error: "Provide paste, url, or path." });
|
|
13258
|
+
res.status(400).json({ error: "Provide paste, url, file, or path." });
|
|
13227
13259
|
return;
|
|
13228
13260
|
}
|
|
13229
13261
|
for (const page of result.producedPages) broadcast({ type: "wiki_ingest_page_written", path: page, action: "created" });
|