feat: choose your own pool account; skills with "token" in a doc name upload; System Health off Linux

- Skill snapshot/upload: a key file's name (.env, *.pem, id_rsa, .netrc,
  .credentials.json…) is always refused, but a word like token/secret/
  password/credential only in a data file's name — design-tokens.md or
  count_tokens.py is skill content, not a key.
- System Health: off Linux the History, CPU threads and Busiest processes
  cards (all read from /proc) are left out instead of shown empty; the CPU
  bar without a sample and Windows' always-zero Load row go too.
- Users pick their own pool account per tool (/api/me/pool-accounts,
  Settings → AI tools), within their groups, refused while pinned.
- Admin user detail, 9router update, session replay and Antigravity
  catalog changes from parallel sessions.
This commit is contained in:
2026-10-28 10:41:53 +07:00
parent 4999325210
commit 0f17efe3b4
39 changed files with 1306 additions and 230 deletions
+11 -1
View File
@@ -176,6 +176,16 @@ function readChunk(file, offset, size) {
return { text: buf.toString("utf8", 0, end), bytes: end, more: offset + end < size && end > 0 };
}
/** A regular file, by `stat`: `existsSync` is access(2), blind to the
* CAP_DAC_READ_SEARCH that reaches a member's 0700 CODEX_HOME (S3). */
function isFile(p) {
try {
return fs.statSync(p).isFile();
} catch {
return false;
}
}
/** Every total vector in a parent journal: the history a fork copied. Streamed. */
async function parentTotals(file) {
const keys = new Set();
@@ -498,7 +508,7 @@ function ingestCodexUsage({
if (walkedAll) return null;
const known = threadPath.get(id)?.path;
const root = path.join(home || getCodexHome(), "sessions") + path.sep;
if (known && known.startsWith(root) && fs.existsSync(known)) return known;
if (known && known.startsWith(root) && isFile(known)) return known;
walkedAll = true;
for (const f of allRolloutFiles(home)) {
const m = FILE_NAME.exec(path.basename(f.path));