@madh-io/alfred-ai 0.3.0 → 0.3.1
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/bundle/index.js +87 -54
- package/package.json +1 -1
package/bundle/index.js
CHANGED
|
@@ -4554,6 +4554,9 @@ var init_dist7 = __esm({
|
|
|
4554
4554
|
});
|
|
4555
4555
|
|
|
4556
4556
|
// ../core/dist/alfred.js
|
|
4557
|
+
import fs4 from "node:fs";
|
|
4558
|
+
import path4 from "node:path";
|
|
4559
|
+
import yaml2 from "js-yaml";
|
|
4557
4560
|
var Alfred;
|
|
4558
4561
|
var init_alfred = __esm({
|
|
4559
4562
|
"../core/dist/alfred.js"() {
|
|
@@ -4588,8 +4591,10 @@ var init_alfred = __esm({
|
|
|
4588
4591
|
const reminderRepo = new ReminderRepository(db);
|
|
4589
4592
|
this.logger.info("Storage initialized");
|
|
4590
4593
|
const ruleEngine = new RuleEngine();
|
|
4594
|
+
const rules = this.loadSecurityRules();
|
|
4595
|
+
ruleEngine.loadRules(rules);
|
|
4591
4596
|
const securityManager = new SecurityManager(ruleEngine, auditRepo, this.logger.child({ component: "security" }));
|
|
4592
|
-
this.logger.info("Security engine initialized");
|
|
4597
|
+
this.logger.info({ ruleCount: rules.length }, "Security engine initialized");
|
|
4593
4598
|
const llmProvider = createLLMProvider(this.config.llm);
|
|
4594
4599
|
await llmProvider.initialize();
|
|
4595
4600
|
this.logger.info({ provider: this.config.llm.provider, model: this.config.llm.model }, "LLM provider initialized");
|
|
@@ -4708,6 +4713,34 @@ var init_alfred = __esm({
|
|
|
4708
4713
|
this.logger.warn({ platform }, "Adapter disconnected");
|
|
4709
4714
|
});
|
|
4710
4715
|
}
|
|
4716
|
+
loadSecurityRules() {
|
|
4717
|
+
const rulesPath = path4.resolve(this.config.security.rulesPath);
|
|
4718
|
+
const rules = [];
|
|
4719
|
+
if (!fs4.existsSync(rulesPath)) {
|
|
4720
|
+
this.logger.warn({ rulesPath }, "Security rules directory not found, using default deny");
|
|
4721
|
+
return rules;
|
|
4722
|
+
}
|
|
4723
|
+
const stat = fs4.statSync(rulesPath);
|
|
4724
|
+
if (!stat.isDirectory()) {
|
|
4725
|
+
this.logger.warn({ rulesPath }, "Security rules path is not a directory");
|
|
4726
|
+
return rules;
|
|
4727
|
+
}
|
|
4728
|
+
const files = fs4.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
4729
|
+
for (const file of files) {
|
|
4730
|
+
try {
|
|
4731
|
+
const filePath = path4.join(rulesPath, file);
|
|
4732
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
4733
|
+
const parsed = yaml2.load(content);
|
|
4734
|
+
if (parsed?.rules && Array.isArray(parsed.rules)) {
|
|
4735
|
+
rules.push(...parsed.rules);
|
|
4736
|
+
this.logger.info({ file, count: parsed.rules.length }, "Loaded security rules");
|
|
4737
|
+
}
|
|
4738
|
+
} catch (err) {
|
|
4739
|
+
this.logger.error({ err, file }, "Failed to load security rules file");
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4742
|
+
return rules;
|
|
4743
|
+
}
|
|
4711
4744
|
};
|
|
4712
4745
|
}
|
|
4713
4746
|
});
|
|
@@ -4790,9 +4823,9 @@ __export(setup_exports, {
|
|
|
4790
4823
|
});
|
|
4791
4824
|
import { createInterface } from "node:readline/promises";
|
|
4792
4825
|
import { stdin as input, stdout as output } from "node:process";
|
|
4793
|
-
import
|
|
4794
|
-
import
|
|
4795
|
-
import
|
|
4826
|
+
import fs5 from "node:fs";
|
|
4827
|
+
import path5 from "node:path";
|
|
4828
|
+
import yaml3 from "js-yaml";
|
|
4796
4829
|
function green(s) {
|
|
4797
4830
|
return `${GREEN}${s}${RESET}`;
|
|
4798
4831
|
}
|
|
@@ -4822,20 +4855,20 @@ function loadExistingConfig(projectRoot) {
|
|
|
4822
4855
|
let shellEnabled = false;
|
|
4823
4856
|
let writeInGroups = false;
|
|
4824
4857
|
let rateLimit = 30;
|
|
4825
|
-
const configPath =
|
|
4826
|
-
if (
|
|
4858
|
+
const configPath = path5.join(projectRoot, "config", "default.yml");
|
|
4859
|
+
if (fs5.existsSync(configPath)) {
|
|
4827
4860
|
try {
|
|
4828
|
-
const parsed =
|
|
4861
|
+
const parsed = yaml3.load(fs5.readFileSync(configPath, "utf-8"));
|
|
4829
4862
|
if (parsed && typeof parsed === "object") {
|
|
4830
4863
|
Object.assign(config, parsed);
|
|
4831
4864
|
}
|
|
4832
4865
|
} catch {
|
|
4833
4866
|
}
|
|
4834
4867
|
}
|
|
4835
|
-
const envPath =
|
|
4836
|
-
if (
|
|
4868
|
+
const envPath = path5.join(projectRoot, ".env");
|
|
4869
|
+
if (fs5.existsSync(envPath)) {
|
|
4837
4870
|
try {
|
|
4838
|
-
const lines =
|
|
4871
|
+
const lines = fs5.readFileSync(envPath, "utf-8").split("\n");
|
|
4839
4872
|
for (const line of lines) {
|
|
4840
4873
|
const trimmed = line.trim();
|
|
4841
4874
|
if (!trimmed || trimmed.startsWith("#"))
|
|
@@ -4848,10 +4881,10 @@ function loadExistingConfig(projectRoot) {
|
|
|
4848
4881
|
} catch {
|
|
4849
4882
|
}
|
|
4850
4883
|
}
|
|
4851
|
-
const rulesPath =
|
|
4852
|
-
if (
|
|
4884
|
+
const rulesPath = path5.join(projectRoot, "config", "rules", "default-rules.yml");
|
|
4885
|
+
if (fs5.existsSync(rulesPath)) {
|
|
4853
4886
|
try {
|
|
4854
|
-
const rulesContent =
|
|
4887
|
+
const rulesContent = yaml3.load(fs5.readFileSync(rulesPath, "utf-8"));
|
|
4855
4888
|
if (rulesContent?.rules) {
|
|
4856
4889
|
shellEnabled = rulesContent.rules.some((r) => r.id === "allow-owner-admin" && r.effect === "allow");
|
|
4857
4890
|
const writeDmRule = rulesContent.rules.find((r) => r.id === "allow-write-for-dm" || r.id === "allow-write-all");
|
|
@@ -5209,12 +5242,12 @@ ${bold("Writing configuration files...")}`);
|
|
|
5209
5242
|
envLines.push("# ALFRED_OWNER_USER_ID=");
|
|
5210
5243
|
}
|
|
5211
5244
|
envLines.push("");
|
|
5212
|
-
const envPath =
|
|
5213
|
-
|
|
5245
|
+
const envPath = path5.join(projectRoot, ".env");
|
|
5246
|
+
fs5.writeFileSync(envPath, envLines.join("\n"), "utf-8");
|
|
5214
5247
|
console.log(` ${green("+")} ${dim(".env")} written`);
|
|
5215
|
-
const configDir =
|
|
5216
|
-
if (!
|
|
5217
|
-
|
|
5248
|
+
const configDir = path5.join(projectRoot, "config");
|
|
5249
|
+
if (!fs5.existsSync(configDir)) {
|
|
5250
|
+
fs5.mkdirSync(configDir, { recursive: true });
|
|
5218
5251
|
}
|
|
5219
5252
|
const config = {
|
|
5220
5253
|
name: botName,
|
|
@@ -5278,13 +5311,13 @@ ${bold("Writing configuration files...")}`);
|
|
|
5278
5311
|
if (ownerUserId) {
|
|
5279
5312
|
config.security.ownerUserId = ownerUserId;
|
|
5280
5313
|
}
|
|
5281
|
-
const yamlStr = "# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n" +
|
|
5282
|
-
const configPath =
|
|
5283
|
-
|
|
5314
|
+
const yamlStr = "# Alfred \u2014 Configuration\n# Generated by `alfred setup`\n# Edit manually or re-run `alfred setup` to reconfigure.\n\n" + yaml3.dump(config, { lineWidth: 120, noRefs: true, sortKeys: false });
|
|
5315
|
+
const configPath = path5.join(configDir, "default.yml");
|
|
5316
|
+
fs5.writeFileSync(configPath, yamlStr, "utf-8");
|
|
5284
5317
|
console.log(` ${green("+")} ${dim("config/default.yml")} written`);
|
|
5285
|
-
const rulesDir =
|
|
5286
|
-
if (!
|
|
5287
|
-
|
|
5318
|
+
const rulesDir = path5.join(configDir, "rules");
|
|
5319
|
+
if (!fs5.existsSync(rulesDir)) {
|
|
5320
|
+
fs5.mkdirSync(rulesDir, { recursive: true });
|
|
5288
5321
|
}
|
|
5289
5322
|
const ownerAdminRule = enableShell && ownerUserId ? `
|
|
5290
5323
|
# Allow admin actions (shell, etc.) for the owner only
|
|
@@ -5365,12 +5398,12 @@ ${ownerAdminRule}
|
|
|
5365
5398
|
actions: ["*"]
|
|
5366
5399
|
riskLevels: [read, write, destructive, admin]
|
|
5367
5400
|
`;
|
|
5368
|
-
const rulesPath =
|
|
5369
|
-
|
|
5401
|
+
const rulesPath = path5.join(rulesDir, "default-rules.yml");
|
|
5402
|
+
fs5.writeFileSync(rulesPath, rulesYaml, "utf-8");
|
|
5370
5403
|
console.log(` ${green("+")} ${dim("config/rules/default-rules.yml")} written`);
|
|
5371
|
-
const dataDir =
|
|
5372
|
-
if (!
|
|
5373
|
-
|
|
5404
|
+
const dataDir = path5.join(projectRoot, "data");
|
|
5405
|
+
if (!fs5.existsSync(dataDir)) {
|
|
5406
|
+
fs5.mkdirSync(dataDir, { recursive: true });
|
|
5374
5407
|
console.log(` ${green("+")} ${dim("data/")} directory created`);
|
|
5375
5408
|
}
|
|
5376
5409
|
console.log("");
|
|
@@ -5643,9 +5676,9 @@ var rules_exports = {};
|
|
|
5643
5676
|
__export(rules_exports, {
|
|
5644
5677
|
rulesCommand: () => rulesCommand
|
|
5645
5678
|
});
|
|
5646
|
-
import
|
|
5647
|
-
import
|
|
5648
|
-
import
|
|
5679
|
+
import fs6 from "node:fs";
|
|
5680
|
+
import path6 from "node:path";
|
|
5681
|
+
import yaml4 from "js-yaml";
|
|
5649
5682
|
async function rulesCommand() {
|
|
5650
5683
|
const configLoader = new ConfigLoader();
|
|
5651
5684
|
let config;
|
|
@@ -5655,18 +5688,18 @@ async function rulesCommand() {
|
|
|
5655
5688
|
console.error("Failed to load configuration:", error.message);
|
|
5656
5689
|
process.exit(1);
|
|
5657
5690
|
}
|
|
5658
|
-
const rulesPath =
|
|
5659
|
-
if (!
|
|
5691
|
+
const rulesPath = path6.resolve(config.security.rulesPath);
|
|
5692
|
+
if (!fs6.existsSync(rulesPath)) {
|
|
5660
5693
|
console.log(`Rules directory not found: ${rulesPath}`);
|
|
5661
5694
|
console.log("No security rules loaded.");
|
|
5662
5695
|
return;
|
|
5663
5696
|
}
|
|
5664
|
-
const stat =
|
|
5697
|
+
const stat = fs6.statSync(rulesPath);
|
|
5665
5698
|
if (!stat.isDirectory()) {
|
|
5666
5699
|
console.error(`Rules path is not a directory: ${rulesPath}`);
|
|
5667
5700
|
process.exit(1);
|
|
5668
5701
|
}
|
|
5669
|
-
const files =
|
|
5702
|
+
const files = fs6.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
5670
5703
|
if (files.length === 0) {
|
|
5671
5704
|
console.log(`No YAML rule files found in: ${rulesPath}`);
|
|
5672
5705
|
return;
|
|
@@ -5675,10 +5708,10 @@ async function rulesCommand() {
|
|
|
5675
5708
|
const allRules = [];
|
|
5676
5709
|
const errors = [];
|
|
5677
5710
|
for (const file of files) {
|
|
5678
|
-
const filePath =
|
|
5711
|
+
const filePath = path6.join(rulesPath, file);
|
|
5679
5712
|
try {
|
|
5680
|
-
const raw =
|
|
5681
|
-
const parsed =
|
|
5713
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
5714
|
+
const parsed = yaml4.load(raw);
|
|
5682
5715
|
const rules = ruleLoader.loadFromObject(parsed);
|
|
5683
5716
|
allRules.push(...rules);
|
|
5684
5717
|
} catch (error) {
|
|
@@ -5729,9 +5762,9 @@ var status_exports = {};
|
|
|
5729
5762
|
__export(status_exports, {
|
|
5730
5763
|
statusCommand: () => statusCommand
|
|
5731
5764
|
});
|
|
5732
|
-
import
|
|
5733
|
-
import
|
|
5734
|
-
import
|
|
5765
|
+
import fs7 from "node:fs";
|
|
5766
|
+
import path7 from "node:path";
|
|
5767
|
+
import yaml5 from "js-yaml";
|
|
5735
5768
|
async function statusCommand() {
|
|
5736
5769
|
const configLoader = new ConfigLoader();
|
|
5737
5770
|
let config;
|
|
@@ -5787,23 +5820,23 @@ async function statusCommand() {
|
|
|
5787
5820
|
}
|
|
5788
5821
|
console.log("");
|
|
5789
5822
|
console.log("Storage:");
|
|
5790
|
-
const dbPath =
|
|
5791
|
-
const dbExists =
|
|
5823
|
+
const dbPath = path7.resolve(config.storage.path);
|
|
5824
|
+
const dbExists = fs7.existsSync(dbPath);
|
|
5792
5825
|
console.log(` Database: ${dbPath}`);
|
|
5793
5826
|
console.log(` Status: ${dbExists ? "exists" : "not yet created"}`);
|
|
5794
5827
|
console.log("");
|
|
5795
|
-
const rulesPath =
|
|
5828
|
+
const rulesPath = path7.resolve(config.security.rulesPath);
|
|
5796
5829
|
let ruleCount = 0;
|
|
5797
5830
|
let ruleFileCount = 0;
|
|
5798
|
-
if (
|
|
5799
|
-
const files =
|
|
5831
|
+
if (fs7.existsSync(rulesPath) && fs7.statSync(rulesPath).isDirectory()) {
|
|
5832
|
+
const files = fs7.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
5800
5833
|
ruleFileCount = files.length;
|
|
5801
5834
|
const ruleLoader = new RuleLoader();
|
|
5802
5835
|
for (const file of files) {
|
|
5803
|
-
const filePath =
|
|
5836
|
+
const filePath = path7.join(rulesPath, file);
|
|
5804
5837
|
try {
|
|
5805
|
-
const raw =
|
|
5806
|
-
const parsed =
|
|
5838
|
+
const raw = fs7.readFileSync(filePath, "utf-8");
|
|
5839
|
+
const parsed = yaml5.load(raw);
|
|
5807
5840
|
const rules = ruleLoader.loadFromObject(parsed);
|
|
5808
5841
|
ruleCount += rules.length;
|
|
5809
5842
|
} catch {
|
|
@@ -5836,8 +5869,8 @@ var logs_exports = {};
|
|
|
5836
5869
|
__export(logs_exports, {
|
|
5837
5870
|
logsCommand: () => logsCommand
|
|
5838
5871
|
});
|
|
5839
|
-
import
|
|
5840
|
-
import
|
|
5872
|
+
import fs8 from "node:fs";
|
|
5873
|
+
import path8 from "node:path";
|
|
5841
5874
|
async function logsCommand(tail) {
|
|
5842
5875
|
const configLoader = new ConfigLoader();
|
|
5843
5876
|
let config;
|
|
@@ -5847,8 +5880,8 @@ async function logsCommand(tail) {
|
|
|
5847
5880
|
console.error("Failed to load configuration:", error.message);
|
|
5848
5881
|
process.exit(1);
|
|
5849
5882
|
}
|
|
5850
|
-
const dbPath =
|
|
5851
|
-
if (!
|
|
5883
|
+
const dbPath = path8.resolve(config.storage.path);
|
|
5884
|
+
if (!fs8.existsSync(dbPath)) {
|
|
5852
5885
|
console.log(`Database not found at: ${dbPath}`);
|
|
5853
5886
|
console.log("No audit log entries. Alfred has not been run yet, or the database path is incorrect.");
|
|
5854
5887
|
return;
|