@madh-io/alfred-ai 0.3.0 → 0.3.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/bundle/index.js +109 -57
- package/package.json +1 -1
package/bundle/index.js
CHANGED
|
@@ -2239,8 +2239,8 @@ var init_system_info = __esm({
|
|
|
2239
2239
|
properties: {
|
|
2240
2240
|
category: {
|
|
2241
2241
|
type: "string",
|
|
2242
|
-
enum: ["general", "memory", "uptime"],
|
|
2243
|
-
description: "Category of system info"
|
|
2242
|
+
enum: ["general", "memory", "uptime", "datetime"],
|
|
2243
|
+
description: "Category of system info (use datetime for current date/time)"
|
|
2244
2244
|
}
|
|
2245
2245
|
},
|
|
2246
2246
|
required: ["category"]
|
|
@@ -2255,6 +2255,8 @@ var init_system_info = __esm({
|
|
|
2255
2255
|
return this.getMemoryInfo();
|
|
2256
2256
|
case "uptime":
|
|
2257
2257
|
return this.getUptimeInfo();
|
|
2258
|
+
case "datetime":
|
|
2259
|
+
return this.getDateTimeInfo();
|
|
2258
2260
|
default:
|
|
2259
2261
|
return {
|
|
2260
2262
|
success: false,
|
|
@@ -2304,6 +2306,21 @@ var init_system_info = __esm({
|
|
|
2304
2306
|
display: `Uptime: ${info.formatted}`
|
|
2305
2307
|
};
|
|
2306
2308
|
}
|
|
2309
|
+
getDateTimeInfo() {
|
|
2310
|
+
const now = /* @__PURE__ */ new Date();
|
|
2311
|
+
const info = {
|
|
2312
|
+
iso: now.toISOString(),
|
|
2313
|
+
date: now.toLocaleDateString("de-DE", { weekday: "long", year: "numeric", month: "long", day: "numeric" }),
|
|
2314
|
+
time: now.toLocaleTimeString("de-DE"),
|
|
2315
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
2316
|
+
timestamp: now.getTime()
|
|
2317
|
+
};
|
|
2318
|
+
return {
|
|
2319
|
+
success: true,
|
|
2320
|
+
data: info,
|
|
2321
|
+
display: `${info.date}, ${info.time} (${info.timezone})`
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2307
2324
|
};
|
|
2308
2325
|
}
|
|
2309
2326
|
});
|
|
@@ -3906,6 +3923,7 @@ var init_message_pipeline = __esm({
|
|
|
3906
3923
|
const result = await this.executeToolCall(toolCall, {
|
|
3907
3924
|
userId: user.id,
|
|
3908
3925
|
chatId: message.chatId,
|
|
3926
|
+
chatType: message.chatType,
|
|
3909
3927
|
platform: message.platform,
|
|
3910
3928
|
conversationId: conversation.id
|
|
3911
3929
|
});
|
|
@@ -3940,7 +3958,8 @@ var init_message_pipeline = __esm({
|
|
|
3940
3958
|
action: toolCall.name,
|
|
3941
3959
|
riskLevel: skill.metadata.riskLevel,
|
|
3942
3960
|
platform: context.platform,
|
|
3943
|
-
chatId: context.chatId
|
|
3961
|
+
chatId: context.chatId,
|
|
3962
|
+
chatType: context.chatType
|
|
3944
3963
|
});
|
|
3945
3964
|
if (!evaluation.allowed) {
|
|
3946
3965
|
this.logger.warn({ tool: toolCall.name, reason: evaluation.reason, rule: evaluation.matchedRule?.id }, "Skill execution denied by security rules");
|
|
@@ -4554,6 +4573,9 @@ var init_dist7 = __esm({
|
|
|
4554
4573
|
});
|
|
4555
4574
|
|
|
4556
4575
|
// ../core/dist/alfred.js
|
|
4576
|
+
import fs4 from "node:fs";
|
|
4577
|
+
import path4 from "node:path";
|
|
4578
|
+
import yaml2 from "js-yaml";
|
|
4557
4579
|
var Alfred;
|
|
4558
4580
|
var init_alfred = __esm({
|
|
4559
4581
|
"../core/dist/alfred.js"() {
|
|
@@ -4588,8 +4610,10 @@ var init_alfred = __esm({
|
|
|
4588
4610
|
const reminderRepo = new ReminderRepository(db);
|
|
4589
4611
|
this.logger.info("Storage initialized");
|
|
4590
4612
|
const ruleEngine = new RuleEngine();
|
|
4613
|
+
const rules = this.loadSecurityRules();
|
|
4614
|
+
ruleEngine.loadRules(rules);
|
|
4591
4615
|
const securityManager = new SecurityManager(ruleEngine, auditRepo, this.logger.child({ component: "security" }));
|
|
4592
|
-
this.logger.info("Security engine initialized");
|
|
4616
|
+
this.logger.info({ ruleCount: rules.length }, "Security engine initialized");
|
|
4593
4617
|
const llmProvider = createLLMProvider(this.config.llm);
|
|
4594
4618
|
await llmProvider.initialize();
|
|
4595
4619
|
this.logger.info({ provider: this.config.llm.provider, model: this.config.llm.model }, "LLM provider initialized");
|
|
@@ -4708,6 +4732,34 @@ var init_alfred = __esm({
|
|
|
4708
4732
|
this.logger.warn({ platform }, "Adapter disconnected");
|
|
4709
4733
|
});
|
|
4710
4734
|
}
|
|
4735
|
+
loadSecurityRules() {
|
|
4736
|
+
const rulesPath = path4.resolve(this.config.security.rulesPath);
|
|
4737
|
+
const rules = [];
|
|
4738
|
+
if (!fs4.existsSync(rulesPath)) {
|
|
4739
|
+
this.logger.warn({ rulesPath }, "Security rules directory not found, using default deny");
|
|
4740
|
+
return rules;
|
|
4741
|
+
}
|
|
4742
|
+
const stat = fs4.statSync(rulesPath);
|
|
4743
|
+
if (!stat.isDirectory()) {
|
|
4744
|
+
this.logger.warn({ rulesPath }, "Security rules path is not a directory");
|
|
4745
|
+
return rules;
|
|
4746
|
+
}
|
|
4747
|
+
const files = fs4.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
4748
|
+
for (const file of files) {
|
|
4749
|
+
try {
|
|
4750
|
+
const filePath = path4.join(rulesPath, file);
|
|
4751
|
+
const content = fs4.readFileSync(filePath, "utf-8");
|
|
4752
|
+
const parsed = yaml2.load(content);
|
|
4753
|
+
if (parsed?.rules && Array.isArray(parsed.rules)) {
|
|
4754
|
+
rules.push(...parsed.rules);
|
|
4755
|
+
this.logger.info({ file, count: parsed.rules.length }, "Loaded security rules");
|
|
4756
|
+
}
|
|
4757
|
+
} catch (err) {
|
|
4758
|
+
this.logger.error({ err, file }, "Failed to load security rules file");
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
return rules;
|
|
4762
|
+
}
|
|
4711
4763
|
};
|
|
4712
4764
|
}
|
|
4713
4765
|
});
|
|
@@ -4790,9 +4842,9 @@ __export(setup_exports, {
|
|
|
4790
4842
|
});
|
|
4791
4843
|
import { createInterface } from "node:readline/promises";
|
|
4792
4844
|
import { stdin as input, stdout as output } from "node:process";
|
|
4793
|
-
import
|
|
4794
|
-
import
|
|
4795
|
-
import
|
|
4845
|
+
import fs5 from "node:fs";
|
|
4846
|
+
import path5 from "node:path";
|
|
4847
|
+
import yaml3 from "js-yaml";
|
|
4796
4848
|
function green(s) {
|
|
4797
4849
|
return `${GREEN}${s}${RESET}`;
|
|
4798
4850
|
}
|
|
@@ -4822,20 +4874,20 @@ function loadExistingConfig(projectRoot) {
|
|
|
4822
4874
|
let shellEnabled = false;
|
|
4823
4875
|
let writeInGroups = false;
|
|
4824
4876
|
let rateLimit = 30;
|
|
4825
|
-
const configPath =
|
|
4826
|
-
if (
|
|
4877
|
+
const configPath = path5.join(projectRoot, "config", "default.yml");
|
|
4878
|
+
if (fs5.existsSync(configPath)) {
|
|
4827
4879
|
try {
|
|
4828
|
-
const parsed =
|
|
4880
|
+
const parsed = yaml3.load(fs5.readFileSync(configPath, "utf-8"));
|
|
4829
4881
|
if (parsed && typeof parsed === "object") {
|
|
4830
4882
|
Object.assign(config, parsed);
|
|
4831
4883
|
}
|
|
4832
4884
|
} catch {
|
|
4833
4885
|
}
|
|
4834
4886
|
}
|
|
4835
|
-
const envPath =
|
|
4836
|
-
if (
|
|
4887
|
+
const envPath = path5.join(projectRoot, ".env");
|
|
4888
|
+
if (fs5.existsSync(envPath)) {
|
|
4837
4889
|
try {
|
|
4838
|
-
const lines =
|
|
4890
|
+
const lines = fs5.readFileSync(envPath, "utf-8").split("\n");
|
|
4839
4891
|
for (const line of lines) {
|
|
4840
4892
|
const trimmed = line.trim();
|
|
4841
4893
|
if (!trimmed || trimmed.startsWith("#"))
|
|
@@ -4848,10 +4900,10 @@ function loadExistingConfig(projectRoot) {
|
|
|
4848
4900
|
} catch {
|
|
4849
4901
|
}
|
|
4850
4902
|
}
|
|
4851
|
-
const rulesPath =
|
|
4852
|
-
if (
|
|
4903
|
+
const rulesPath = path5.join(projectRoot, "config", "rules", "default-rules.yml");
|
|
4904
|
+
if (fs5.existsSync(rulesPath)) {
|
|
4853
4905
|
try {
|
|
4854
|
-
const rulesContent =
|
|
4906
|
+
const rulesContent = yaml3.load(fs5.readFileSync(rulesPath, "utf-8"));
|
|
4855
4907
|
if (rulesContent?.rules) {
|
|
4856
4908
|
shellEnabled = rulesContent.rules.some((r) => r.id === "allow-owner-admin" && r.effect === "allow");
|
|
4857
4909
|
const writeDmRule = rulesContent.rules.find((r) => r.id === "allow-write-for-dm" || r.id === "allow-write-all");
|
|
@@ -5209,12 +5261,12 @@ ${bold("Writing configuration files...")}`);
|
|
|
5209
5261
|
envLines.push("# ALFRED_OWNER_USER_ID=");
|
|
5210
5262
|
}
|
|
5211
5263
|
envLines.push("");
|
|
5212
|
-
const envPath =
|
|
5213
|
-
|
|
5264
|
+
const envPath = path5.join(projectRoot, ".env");
|
|
5265
|
+
fs5.writeFileSync(envPath, envLines.join("\n"), "utf-8");
|
|
5214
5266
|
console.log(` ${green("+")} ${dim(".env")} written`);
|
|
5215
|
-
const configDir =
|
|
5216
|
-
if (!
|
|
5217
|
-
|
|
5267
|
+
const configDir = path5.join(projectRoot, "config");
|
|
5268
|
+
if (!fs5.existsSync(configDir)) {
|
|
5269
|
+
fs5.mkdirSync(configDir, { recursive: true });
|
|
5218
5270
|
}
|
|
5219
5271
|
const config = {
|
|
5220
5272
|
name: botName,
|
|
@@ -5278,13 +5330,13 @@ ${bold("Writing configuration files...")}`);
|
|
|
5278
5330
|
if (ownerUserId) {
|
|
5279
5331
|
config.security.ownerUserId = ownerUserId;
|
|
5280
5332
|
}
|
|
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
|
-
|
|
5333
|
+
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 });
|
|
5334
|
+
const configPath = path5.join(configDir, "default.yml");
|
|
5335
|
+
fs5.writeFileSync(configPath, yamlStr, "utf-8");
|
|
5284
5336
|
console.log(` ${green("+")} ${dim("config/default.yml")} written`);
|
|
5285
|
-
const rulesDir =
|
|
5286
|
-
if (!
|
|
5287
|
-
|
|
5337
|
+
const rulesDir = path5.join(configDir, "rules");
|
|
5338
|
+
if (!fs5.existsSync(rulesDir)) {
|
|
5339
|
+
fs5.mkdirSync(rulesDir, { recursive: true });
|
|
5288
5340
|
}
|
|
5289
5341
|
const ownerAdminRule = enableShell && ownerUserId ? `
|
|
5290
5342
|
# Allow admin actions (shell, etc.) for the owner only
|
|
@@ -5365,12 +5417,12 @@ ${ownerAdminRule}
|
|
|
5365
5417
|
actions: ["*"]
|
|
5366
5418
|
riskLevels: [read, write, destructive, admin]
|
|
5367
5419
|
`;
|
|
5368
|
-
const rulesPath =
|
|
5369
|
-
|
|
5420
|
+
const rulesPath = path5.join(rulesDir, "default-rules.yml");
|
|
5421
|
+
fs5.writeFileSync(rulesPath, rulesYaml, "utf-8");
|
|
5370
5422
|
console.log(` ${green("+")} ${dim("config/rules/default-rules.yml")} written`);
|
|
5371
|
-
const dataDir =
|
|
5372
|
-
if (!
|
|
5373
|
-
|
|
5423
|
+
const dataDir = path5.join(projectRoot, "data");
|
|
5424
|
+
if (!fs5.existsSync(dataDir)) {
|
|
5425
|
+
fs5.mkdirSync(dataDir, { recursive: true });
|
|
5374
5426
|
console.log(` ${green("+")} ${dim("data/")} directory created`);
|
|
5375
5427
|
}
|
|
5376
5428
|
console.log("");
|
|
@@ -5643,9 +5695,9 @@ var rules_exports = {};
|
|
|
5643
5695
|
__export(rules_exports, {
|
|
5644
5696
|
rulesCommand: () => rulesCommand
|
|
5645
5697
|
});
|
|
5646
|
-
import
|
|
5647
|
-
import
|
|
5648
|
-
import
|
|
5698
|
+
import fs6 from "node:fs";
|
|
5699
|
+
import path6 from "node:path";
|
|
5700
|
+
import yaml4 from "js-yaml";
|
|
5649
5701
|
async function rulesCommand() {
|
|
5650
5702
|
const configLoader = new ConfigLoader();
|
|
5651
5703
|
let config;
|
|
@@ -5655,18 +5707,18 @@ async function rulesCommand() {
|
|
|
5655
5707
|
console.error("Failed to load configuration:", error.message);
|
|
5656
5708
|
process.exit(1);
|
|
5657
5709
|
}
|
|
5658
|
-
const rulesPath =
|
|
5659
|
-
if (!
|
|
5710
|
+
const rulesPath = path6.resolve(config.security.rulesPath);
|
|
5711
|
+
if (!fs6.existsSync(rulesPath)) {
|
|
5660
5712
|
console.log(`Rules directory not found: ${rulesPath}`);
|
|
5661
5713
|
console.log("No security rules loaded.");
|
|
5662
5714
|
return;
|
|
5663
5715
|
}
|
|
5664
|
-
const stat =
|
|
5716
|
+
const stat = fs6.statSync(rulesPath);
|
|
5665
5717
|
if (!stat.isDirectory()) {
|
|
5666
5718
|
console.error(`Rules path is not a directory: ${rulesPath}`);
|
|
5667
5719
|
process.exit(1);
|
|
5668
5720
|
}
|
|
5669
|
-
const files =
|
|
5721
|
+
const files = fs6.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
5670
5722
|
if (files.length === 0) {
|
|
5671
5723
|
console.log(`No YAML rule files found in: ${rulesPath}`);
|
|
5672
5724
|
return;
|
|
@@ -5675,10 +5727,10 @@ async function rulesCommand() {
|
|
|
5675
5727
|
const allRules = [];
|
|
5676
5728
|
const errors = [];
|
|
5677
5729
|
for (const file of files) {
|
|
5678
|
-
const filePath =
|
|
5730
|
+
const filePath = path6.join(rulesPath, file);
|
|
5679
5731
|
try {
|
|
5680
|
-
const raw =
|
|
5681
|
-
const parsed =
|
|
5732
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
5733
|
+
const parsed = yaml4.load(raw);
|
|
5682
5734
|
const rules = ruleLoader.loadFromObject(parsed);
|
|
5683
5735
|
allRules.push(...rules);
|
|
5684
5736
|
} catch (error) {
|
|
@@ -5729,9 +5781,9 @@ var status_exports = {};
|
|
|
5729
5781
|
__export(status_exports, {
|
|
5730
5782
|
statusCommand: () => statusCommand
|
|
5731
5783
|
});
|
|
5732
|
-
import
|
|
5733
|
-
import
|
|
5734
|
-
import
|
|
5784
|
+
import fs7 from "node:fs";
|
|
5785
|
+
import path7 from "node:path";
|
|
5786
|
+
import yaml5 from "js-yaml";
|
|
5735
5787
|
async function statusCommand() {
|
|
5736
5788
|
const configLoader = new ConfigLoader();
|
|
5737
5789
|
let config;
|
|
@@ -5787,23 +5839,23 @@ async function statusCommand() {
|
|
|
5787
5839
|
}
|
|
5788
5840
|
console.log("");
|
|
5789
5841
|
console.log("Storage:");
|
|
5790
|
-
const dbPath =
|
|
5791
|
-
const dbExists =
|
|
5842
|
+
const dbPath = path7.resolve(config.storage.path);
|
|
5843
|
+
const dbExists = fs7.existsSync(dbPath);
|
|
5792
5844
|
console.log(` Database: ${dbPath}`);
|
|
5793
5845
|
console.log(` Status: ${dbExists ? "exists" : "not yet created"}`);
|
|
5794
5846
|
console.log("");
|
|
5795
|
-
const rulesPath =
|
|
5847
|
+
const rulesPath = path7.resolve(config.security.rulesPath);
|
|
5796
5848
|
let ruleCount = 0;
|
|
5797
5849
|
let ruleFileCount = 0;
|
|
5798
|
-
if (
|
|
5799
|
-
const files =
|
|
5850
|
+
if (fs7.existsSync(rulesPath) && fs7.statSync(rulesPath).isDirectory()) {
|
|
5851
|
+
const files = fs7.readdirSync(rulesPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
|
|
5800
5852
|
ruleFileCount = files.length;
|
|
5801
5853
|
const ruleLoader = new RuleLoader();
|
|
5802
5854
|
for (const file of files) {
|
|
5803
|
-
const filePath =
|
|
5855
|
+
const filePath = path7.join(rulesPath, file);
|
|
5804
5856
|
try {
|
|
5805
|
-
const raw =
|
|
5806
|
-
const parsed =
|
|
5857
|
+
const raw = fs7.readFileSync(filePath, "utf-8");
|
|
5858
|
+
const parsed = yaml5.load(raw);
|
|
5807
5859
|
const rules = ruleLoader.loadFromObject(parsed);
|
|
5808
5860
|
ruleCount += rules.length;
|
|
5809
5861
|
} catch {
|
|
@@ -5836,8 +5888,8 @@ var logs_exports = {};
|
|
|
5836
5888
|
__export(logs_exports, {
|
|
5837
5889
|
logsCommand: () => logsCommand
|
|
5838
5890
|
});
|
|
5839
|
-
import
|
|
5840
|
-
import
|
|
5891
|
+
import fs8 from "node:fs";
|
|
5892
|
+
import path8 from "node:path";
|
|
5841
5893
|
async function logsCommand(tail) {
|
|
5842
5894
|
const configLoader = new ConfigLoader();
|
|
5843
5895
|
let config;
|
|
@@ -5847,8 +5899,8 @@ async function logsCommand(tail) {
|
|
|
5847
5899
|
console.error("Failed to load configuration:", error.message);
|
|
5848
5900
|
process.exit(1);
|
|
5849
5901
|
}
|
|
5850
|
-
const dbPath =
|
|
5851
|
-
if (!
|
|
5902
|
+
const dbPath = path8.resolve(config.storage.path);
|
|
5903
|
+
if (!fs8.existsSync(dbPath)) {
|
|
5852
5904
|
console.log(`Database not found at: ${dbPath}`);
|
|
5853
5905
|
console.log("No audit log entries. Alfred has not been run yet, or the database path is incorrect.");
|
|
5854
5906
|
return;
|