bazilion 0.7.0 → 0.8.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.
Files changed (37) hide show
  1. package/dist/cli.js +80 -17
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon.js +143 -23
  4. package/dist/daemon.js.map +1 -1
  5. package/dist/web/client/assets/{TemplatesTabs-Da7mg9FI.js → TemplatesTabs-UM04RMO9.js} +1 -1
  6. package/dist/web/client/assets/{_id-LT6Ejjr0.js → _id-BNJapCT4.js} +1 -1
  7. package/dist/web/client/assets/{_id-_6jIt0_-.js → _id-CjGoV8Mr.js} +1 -1
  8. package/dist/web/client/assets/{_id-BdKmo0gb.js → _id-DehuCHUw.js} +1 -1
  9. package/dist/web/client/assets/{_id-MR2XjWh0.js → _id-Dz9fjcCM.js} +1 -1
  10. package/dist/web/client/assets/{agents-0arKbVYG.js → agents-M6omAXcZ.js} +1 -1
  11. package/dist/web/client/assets/{config-BSAVT-17.js → config-DIuEc5bm.js} +1 -1
  12. package/dist/web/client/assets/{groups-BqTkhHes.js → groups-DpE2d2zZ.js} +1 -1
  13. package/dist/web/client/assets/{inbox-ozoCXzr5.js → inbox-BPnLsRNf.js} +1 -1
  14. package/dist/web/client/assets/{index-iayCEuU2.js → index-MAJuXnie.js} +2 -2
  15. package/dist/web/client/assets/{login-D8lNr2SX.js → login-CawJX16E.js} +1 -1
  16. package/dist/web/client/assets/{mcp-BLnngDsj.js → mcp-DIrh9-v_.js} +1 -1
  17. package/dist/web/client/assets/{memory-D1GQjEvN.js → memory-BpHbdKsd.js} +1 -1
  18. package/dist/web/client/assets/{profile-groups-C2yJPTaE.js → profile-groups-ByoKak0c.js} +1 -1
  19. package/dist/web/client/assets/{profiles-BV7AAZjj.js → profiles-BEjv8LGo.js} +1 -1
  20. package/dist/web/client/assets/{routes-DSHQLA7K.js → routes-D2COHy7v.js} +1 -1
  21. package/dist/web/client/assets/{services-BbCJe1Du.js → services-D212jSK_.js} +1 -1
  22. package/dist/web/client/assets/skills-Da0MURjY.js +1 -0
  23. package/dist/web/client/assets/styles-BgE5bCHA.css +2 -0
  24. package/dist/web/client/assets/{telegram-gE4j8gte.js → telegram-Czh2MdVm.js} +1 -1
  25. package/dist/web/client/assets/{tokens-D2_O9ARe.js → tokens-E_JvO5JN.js} +1 -1
  26. package/dist/web/client/assets/{triggers-WljnfEfJ.js → triggers-BBRZQOm7.js} +1 -1
  27. package/dist/web/server/assets/{_id-D0ytyXGY.js → _id-BdRiQb2H.js} +42 -5
  28. package/dist/web/server/assets/{_id-81NrHA5d.js → _id-DUIrFV3G.js} +1 -1
  29. package/dist/web/server/assets/{_tanstack-start-manifest_v-DBlFH2gg.js → _tanstack-start-manifest_v-D9FLKShQ.js} +23 -23
  30. package/dist/web/server/assets/{router-BpBZgRwn.js → router-BrDascdO.js} +3 -3
  31. package/dist/web/server/assets/{skills-dLyBZb3B.js → skills-D89ND2kR.js} +67 -7
  32. package/dist/web/server/assets/{skills-CpsyR_WA.js → skills-l2cyQ3zS.js} +1 -1
  33. package/dist/web/server/server.js +2 -2
  34. package/dist/worker.js.map +1 -1
  35. package/package.json +3 -3
  36. package/dist/web/client/assets/skills-C6czKR5I.js +0 -1
  37. package/dist/web/client/assets/styles-C06axZZk.css +0 -2
package/dist/daemon.js CHANGED
@@ -12518,11 +12518,11 @@ var require_util = __commonJS({
12518
12518
  return false;
12519
12519
  }
12520
12520
  exports.schemaHasRules = schemaHasRules;
12521
- function schemaHasRulesButRef(schema, RULES) {
12521
+ function schemaHasRulesButRef(schema, RULES2) {
12522
12522
  if (typeof schema == "boolean")
12523
12523
  return !schema;
12524
12524
  for (const key2 in schema)
12525
- if (key2 !== "$ref" && RULES.all[key2])
12525
+ if (key2 !== "$ref" && RULES2.all[key2])
12526
12526
  return true;
12527
12527
  return false;
12528
12528
  }
@@ -13916,17 +13916,17 @@ var require_validate = __commonJS({
13916
13916
  }
13917
13917
  function schemaKeywords(it, types, typeErrors, errsCount) {
13918
13918
  const { gen, schema, data, allErrors, opts, self } = it;
13919
- const { RULES } = self;
13920
- if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
13921
- gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition));
13919
+ const { RULES: RULES2 } = self;
13920
+ if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES2))) {
13921
+ gen.block(() => keywordCode(it, "$ref", RULES2.all.$ref.definition));
13922
13922
  return;
13923
13923
  }
13924
13924
  if (!opts.jtd)
13925
13925
  checkStrictTypes(it, types);
13926
13926
  gen.block(() => {
13927
- for (const group of RULES.rules)
13927
+ for (const group of RULES2.rules)
13928
13928
  groupKeywords(group);
13929
- groupKeywords(RULES.post);
13929
+ groupKeywords(RULES2.post);
13930
13930
  });
13931
13931
  function groupKeywords(group) {
13932
13932
  if (!(0, applicability_1.shouldUseGroup)(schema, group))
@@ -15715,10 +15715,10 @@ var require_core = __commonJS({
15715
15715
  }
15716
15716
  // Remove keyword
15717
15717
  removeKeyword(keyword) {
15718
- const { RULES } = this;
15719
- delete RULES.keywords[keyword];
15720
- delete RULES.all[keyword];
15721
- for (const group of RULES.rules) {
15718
+ const { RULES: RULES2 } = this;
15719
+ delete RULES2.keywords[keyword];
15720
+ delete RULES2.all[keyword];
15721
+ for (const group of RULES2.rules) {
15722
15722
  const i = group.rules.findIndex((rule) => rule.keyword === keyword);
15723
15723
  if (i >= 0)
15724
15724
  group.rules.splice(i, 1);
@@ -15886,9 +15886,9 @@ var require_core = __commonJS({
15886
15886
  }
15887
15887
  var KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
15888
15888
  function checkKeyword(keyword, def) {
15889
- const { RULES } = this;
15889
+ const { RULES: RULES2 } = this;
15890
15890
  (0, util_1.eachItem)(keyword, (kwd) => {
15891
- if (RULES.keywords[kwd])
15891
+ if (RULES2.keywords[kwd])
15892
15892
  throw new Error(`Keyword ${kwd} is already defined`);
15893
15893
  if (!KEYWORD_NAME.test(kwd))
15894
15894
  throw new Error(`Keyword ${kwd} has invalid name`);
@@ -15904,13 +15904,13 @@ var require_core = __commonJS({
15904
15904
  const post = definition === null || definition === void 0 ? void 0 : definition.post;
15905
15905
  if (dataType && post)
15906
15906
  throw new Error('keyword with "post" flag cannot have "type"');
15907
- const { RULES } = this;
15908
- let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t }) => t === dataType);
15907
+ const { RULES: RULES2 } = this;
15908
+ let ruleGroup = post ? RULES2.post : RULES2.rules.find(({ type: t }) => t === dataType);
15909
15909
  if (!ruleGroup) {
15910
15910
  ruleGroup = { type: dataType, rules: [] };
15911
- RULES.rules.push(ruleGroup);
15911
+ RULES2.rules.push(ruleGroup);
15912
15912
  }
15913
- RULES.keywords[keyword] = true;
15913
+ RULES2.keywords[keyword] = true;
15914
15914
  if (!definition)
15915
15915
  return;
15916
15916
  const rule = {
@@ -15925,7 +15925,7 @@ var require_core = __commonJS({
15925
15925
  addBeforeRule.call(this, ruleGroup, rule, definition.before);
15926
15926
  else
15927
15927
  ruleGroup.rules.push(rule);
15928
- RULES.all[keyword] = rule;
15928
+ RULES2.all[keyword] = rule;
15929
15929
  (_a3 = definition.implements) === null || _a3 === void 0 ? void 0 : _a3.forEach((kwd) => this.addKeyword(kwd));
15930
15930
  }
15931
15931
  function addBeforeRule(ruleGroup, rule, before) {
@@ -21738,7 +21738,74 @@ function parseSkillFile(path) {
21738
21738
  return parseSkillContent(raw);
21739
21739
  }
21740
21740
 
21741
+ // ../daemon/src/core/skills/scan.ts
21742
+ var SECRET_ENV_RE = /\b(ANTHROPIC_API_KEY|OPENAI_API_KEY|OPENAI_CODEX_OAUTH|GEMINI_API_KEY|GOOGLE_API_KEY|AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY|AZURE_OPENAI_API_KEY|MISTRAL_API_KEY|GROQ_API_KEY|BRAVE_API_KEY|SEARXNG_URL)\b/i;
21743
+ var SENSITIVE_PATH_RE = /(~\/\.(ssh|aws|gnupg|config)|\b(auth\.json|bazilion\.db)\b)/i;
21744
+ var SECRET_TARGET_RE = /(secret|credential|token|api[-_\s]?key|env(?:ironment)?(?: variable)?|private key|ssh key|auth\.json|bazilion\.db|~\/\.(ssh|aws|gnupg))/i;
21745
+ var EXFIL_VERB_RE = /(exfiltrat|send|upload|post|curl|webhook|pastebin|remote server|external server|http endpoint)/i;
21746
+ var UNICODE_STEALTH_RE = /[\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFEFF]/;
21747
+ var RULES = [
21748
+ {
21749
+ code: "sensitive-reference",
21750
+ severity: "danger",
21751
+ message: "Mentions a sensitive path, database, auth file, or credential environment variable.",
21752
+ test: (line) => SENSITIVE_PATH_RE.test(line) || SECRET_ENV_RE.test(line)
21753
+ },
21754
+ {
21755
+ code: "secret-exfiltration",
21756
+ severity: "danger",
21757
+ message: "Combines secret/env/file access with exfiltration-style language.",
21758
+ test: (line) => SECRET_TARGET_RE.test(line) && EXFIL_VERB_RE.test(line)
21759
+ },
21760
+ {
21761
+ code: "instruction-hijack",
21762
+ severity: "danger",
21763
+ message: "Contains instruction-hijacking language such as ignoring prior instructions.",
21764
+ test: (line) => /ignore (all )?(previous|prior|system|developer|user) instructions/i.test(line) || /override (the )?(system|developer) (prompt|instructions)/i.test(line) || /bypass (safety|security|policy|guardrails)/i.test(line) || /you are now (root|unrestricted|in developer mode)/i.test(line)
21765
+ },
21766
+ {
21767
+ code: "unicode-stealth",
21768
+ severity: "warning",
21769
+ message: "Contains zero-width, bidi, or byte-order characters that can hide prompt text.",
21770
+ test: (line) => UNICODE_STEALTH_RE.test(line)
21771
+ }
21772
+ ];
21773
+ function addFinding(findings, seen, finding) {
21774
+ const key2 = `${finding.code}:${finding.line ?? 0}`;
21775
+ if (seen.has(key2)) return;
21776
+ seen.add(key2);
21777
+ findings.push(finding);
21778
+ }
21779
+ function scanSkillContent(raw) {
21780
+ const findings = [];
21781
+ const seen = /* @__PURE__ */ new Set();
21782
+ const lines = raw.split(/\r?\n/);
21783
+ lines.forEach((line, index) => {
21784
+ for (const rule of RULES) {
21785
+ if (!rule.test(line)) continue;
21786
+ addFinding(findings, seen, {
21787
+ code: rule.code,
21788
+ severity: rule.severity,
21789
+ message: rule.message,
21790
+ line: index + 1
21791
+ });
21792
+ }
21793
+ });
21794
+ return findings;
21795
+ }
21796
+
21741
21797
  // ../daemon/src/core/skills/import.ts
21798
+ var SkillScanBlockedError = class extends Error {
21799
+ findings;
21800
+ constructor(findings) {
21801
+ const names = Object.keys(findings).sort();
21802
+ super(
21803
+ `skill scan blocked import: ${names.join(", ")} ${names.length === 1 ? "has" : "have"} findings (rerun with --force to confirm)`
21804
+ );
21805
+ this.name = "SkillScanBlockedError";
21806
+ this.findings = findings;
21807
+ }
21808
+ };
21742
21809
  function extractZipSafely(zipPath) {
21743
21810
  const root = mkdtempSync(join10(tmpdir(), "bazilion-skill-zip-"));
21744
21811
  try {
@@ -21805,8 +21872,14 @@ function importSkillsFromDir(paths, source, input) {
21805
21872
  if (candidates.length === 0) {
21806
21873
  throw new Error(`no skills found in ${source}`);
21807
21874
  }
21875
+ const findingsBySkill = {};
21808
21876
  for (const c of candidates) {
21809
- parseSkillFile(join10(c.dir, "SKILL.md"));
21877
+ const parsed = parseSkillFile(join10(c.dir, "SKILL.md"));
21878
+ const findings = scanSkillContent(parsed.raw);
21879
+ if (findings.length > 0) findingsBySkill[c.name] = findings;
21880
+ }
21881
+ if (Object.keys(findingsBySkill).length > 0 && !input.force) {
21882
+ throw new SkillScanBlockedError(findingsBySkill);
21810
21883
  }
21811
21884
  const imported = [];
21812
21885
  const skipped = [];
@@ -21815,14 +21888,19 @@ function importSkillsFromDir(paths, source, input) {
21815
21888
  if (existsSync8(target) && !input.force) {
21816
21889
  skipped.push({
21817
21890
  name: c.name,
21818
- reason: "already exists (use --force to overwrite)"
21891
+ reason: "already exists (use --force to overwrite)",
21892
+ findings: findingsBySkill[c.name]
21819
21893
  });
21820
21894
  continue;
21821
21895
  }
21822
21896
  cpSync(c.dir, target, { recursive: true, force: !!input.force });
21823
21897
  imported.push(c.name);
21824
21898
  }
21825
- return { imported, skipped };
21899
+ return {
21900
+ imported,
21901
+ skipped,
21902
+ findings: Object.keys(findingsBySkill).length > 0 ? findingsBySkill : void 0
21903
+ };
21826
21904
  }
21827
21905
 
21828
21906
  // ../daemon/src/core/skills/resolve.ts
@@ -29958,7 +30036,8 @@ agentsRouter.get("/:id/skills", (c) => {
29958
30036
  name: s.name,
29959
30037
  description: s.parsed.frontmatter.description,
29960
30038
  source: meta2?.source ?? null,
29961
- importedAt: meta2?.importedAt ?? null
30039
+ importedAt: meta2?.importedAt ?? null,
30040
+ scanFindings: scanSkillContent(s.parsed.raw)
29962
30041
  };
29963
30042
  }),
29964
30043
  missing: set.missing
@@ -29973,6 +30052,24 @@ agentsRouter.post("/:id/skills", async (c) => {
29973
30052
  const { db, paths, authToken } = getCtx();
29974
30053
  const agent = agents_exports.get(db, c.req.param("id"));
29975
30054
  if (!agent) return c.json({ error: `agent not found: ${c.req.param("id")}` }, 404);
30055
+ const discovered = discoverSkills(paths).find((s) => s.name === body.skill);
30056
+ if (discovered) {
30057
+ try {
30058
+ const parsed = parseSkillFile(discovered.skillFile);
30059
+ const findings = scanSkillContent(parsed.raw);
30060
+ if (findings.length > 0 && !body.allowFindings) {
30061
+ return c.json(
30062
+ {
30063
+ error: `skill scan blocked attach: ${body.skill} has findings`,
30064
+ code: "skill_scan_blocked",
30065
+ findings
30066
+ },
30067
+ 400
30068
+ );
30069
+ }
30070
+ } catch {
30071
+ }
30072
+ }
29976
30073
  agents_exports.attachSkill(db, agent.id, body.skill);
29977
30074
  return c.body(null, 204);
29978
30075
  });
@@ -31491,6 +31588,7 @@ skillsRouter.get("/", (c) => {
31491
31588
  try {
31492
31589
  const parsed = parseSkillFile(s.skillFile);
31493
31590
  entry.description = parsed.frontmatter.description;
31591
+ entry.scanFindings = scanSkillContent(parsed.raw);
31494
31592
  } catch (err) {
31495
31593
  entry.parseError = err.message;
31496
31594
  }
@@ -31521,14 +31619,36 @@ skillsRouter.post("/import", async (c) => {
31521
31619
  for (const name of result.imported) {
31522
31620
  skillMeta_exports.upsert(db, { name, source: input.sourceLabel, importedAt: now });
31523
31621
  }
31524
- const res = { imported: result.imported, skipped: result.skipped };
31622
+ const res = {
31623
+ imported: result.imported,
31624
+ skipped: result.skipped,
31625
+ findings: result.findings
31626
+ };
31525
31627
  return c.json(res);
31526
31628
  } catch (err) {
31629
+ if (err instanceof SkillScanBlockedError) {
31630
+ return c.json(
31631
+ {
31632
+ error: err.message,
31633
+ code: "skill_scan_blocked",
31634
+ findings: flattenFindings(err.findings)
31635
+ },
31636
+ 400
31637
+ );
31638
+ }
31527
31639
  return c.json({ error: err.message }, 400);
31528
31640
  } finally {
31529
31641
  if (input.tempZipPath) rmSync10(input.tempZipPath, { recursive: true, force: true });
31530
31642
  }
31531
31643
  });
31644
+ function flattenFindings(findings) {
31645
+ return Object.entries(findings).flatMap(
31646
+ ([name, items]) => items.map((item) => ({
31647
+ ...item,
31648
+ message: `${name}: ${item.message}`
31649
+ }))
31650
+ );
31651
+ }
31532
31652
  async function parseImportInput(request) {
31533
31653
  const contentType = request.headers.get("content-type") ?? "";
31534
31654
  if (contentType.startsWith("multipart/form-data")) {