augure 0.4.2 → 0.5.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/dist/bin.js +214 -97
- package/package.json +20 -20
package/dist/bin.js
CHANGED
|
@@ -50,9 +50,12 @@ var AppConfigSchema = z.object({
|
|
|
50
50
|
heartbeatInterval: z.string().min(1),
|
|
51
51
|
jobs: z.array(z.object({
|
|
52
52
|
id: z.string().min(1),
|
|
53
|
-
cron: z.string().min(1),
|
|
53
|
+
cron: z.string().min(1).optional(),
|
|
54
|
+
runAt: z.string().min(1).optional(),
|
|
54
55
|
prompt: z.string().min(1),
|
|
55
56
|
channel: z.string().min(1)
|
|
57
|
+
}).refine((j) => j.cron || j.runAt, {
|
|
58
|
+
message: "Job must have either cron or runAt"
|
|
56
59
|
}))
|
|
57
60
|
}),
|
|
58
61
|
sandbox: z.object({
|
|
@@ -582,62 +585,6 @@ function createOutgoingPipeline(middlewares, send) {
|
|
|
582
585
|
};
|
|
583
586
|
}
|
|
584
587
|
|
|
585
|
-
// ../channels/dist/middleware/escape-markdown.js
|
|
586
|
-
var SPECIAL_CHARS = /* @__PURE__ */ new Set([".", "!", ">", "#", "+", "-", "=", "|", "{", "}", "~"]);
|
|
587
|
-
function escapeMarkdownV2(text) {
|
|
588
|
-
if (!text)
|
|
589
|
-
return "";
|
|
590
|
-
const parts = [];
|
|
591
|
-
let i = 0;
|
|
592
|
-
while (i < text.length) {
|
|
593
|
-
if (text.startsWith("```", i)) {
|
|
594
|
-
const endIdx = text.indexOf("```", i + 3);
|
|
595
|
-
if (endIdx !== -1) {
|
|
596
|
-
parts.push(text.slice(i, endIdx + 3));
|
|
597
|
-
i = endIdx + 3;
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
if (text[i] === "`") {
|
|
602
|
-
const endIdx = text.indexOf("`", i + 1);
|
|
603
|
-
if (endIdx !== -1) {
|
|
604
|
-
parts.push(text.slice(i, endIdx + 1));
|
|
605
|
-
i = endIdx + 1;
|
|
606
|
-
continue;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
if (text[i] === "*" || text[i] === "_") {
|
|
610
|
-
parts.push(text[i]);
|
|
611
|
-
i++;
|
|
612
|
-
continue;
|
|
613
|
-
}
|
|
614
|
-
if (text[i] === "[" || text[i] === "(") {
|
|
615
|
-
parts.push(text[i]);
|
|
616
|
-
i++;
|
|
617
|
-
continue;
|
|
618
|
-
}
|
|
619
|
-
if (text[i] === "]") {
|
|
620
|
-
parts.push(text[i]);
|
|
621
|
-
i++;
|
|
622
|
-
continue;
|
|
623
|
-
}
|
|
624
|
-
const char = text[i];
|
|
625
|
-
if (SPECIAL_CHARS.has(char)) {
|
|
626
|
-
parts.push(`\\${char}`);
|
|
627
|
-
} else {
|
|
628
|
-
parts.push(char);
|
|
629
|
-
}
|
|
630
|
-
i++;
|
|
631
|
-
}
|
|
632
|
-
return parts.join("");
|
|
633
|
-
}
|
|
634
|
-
function createEscapeMarkdownMiddleware() {
|
|
635
|
-
return async (message, next) => {
|
|
636
|
-
message.text = escapeMarkdownV2(message.text);
|
|
637
|
-
await next();
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
|
|
641
588
|
// ../channels/dist/middleware/split-message.js
|
|
642
589
|
var TELEGRAM_MAX = 4096;
|
|
643
590
|
function splitText(text, maxLength) {
|
|
@@ -743,6 +690,38 @@ async function withRetry(fn, options) {
|
|
|
743
690
|
throw lastError;
|
|
744
691
|
}
|
|
745
692
|
|
|
693
|
+
// ../channels/dist/middleware/markdown-to-html.js
|
|
694
|
+
function markdownToTelegramHtml(text) {
|
|
695
|
+
if (!text)
|
|
696
|
+
return "";
|
|
697
|
+
const placeholders = [];
|
|
698
|
+
const PH_PREFIX = "\uFFFCPH";
|
|
699
|
+
const PH_SUFFIX = "\uFFFC";
|
|
700
|
+
function hold(html) {
|
|
701
|
+
const idx = placeholders.length;
|
|
702
|
+
placeholders.push(html);
|
|
703
|
+
return `${PH_PREFIX}${idx}${PH_SUFFIX}`;
|
|
704
|
+
}
|
|
705
|
+
let out = text;
|
|
706
|
+
out = out.replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) => hold(lang ? `<pre><code class="language-${escapeHtml(lang)}">${escapeHtml(code.trimEnd())}</code></pre>` : `<pre>${escapeHtml(code.trimEnd())}</pre>`));
|
|
707
|
+
out = out.replace(/`([^`\n]+)`/g, (_, code) => hold(`<code>${escapeHtml(code)}</code>`));
|
|
708
|
+
out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, linkText, url) => hold(`<a href="${escapeHtml(url)}">${escapeHtml(linkText)}</a>`));
|
|
709
|
+
out = escapeHtml(out);
|
|
710
|
+
out = out.replace(/\*\*\*(.+?)\*\*\*/g, "<b><i>$1</i></b>");
|
|
711
|
+
out = out.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
|
712
|
+
out = out.replace(/\*([^*\n]+?)\*/g, "<i>$1</i>");
|
|
713
|
+
out = out.replace(/~~(.+?)~~/g, "<s>$1</s>");
|
|
714
|
+
out = out.replace(/^#{1,6}\s+(.+)$/gm, "<b>$1</b>");
|
|
715
|
+
out = out.replace(/^>\s?(.*)$/gm, "<blockquote>$1</blockquote>");
|
|
716
|
+
out = out.replace(/<\/blockquote>\n<blockquote>/g, "\n");
|
|
717
|
+
const phPattern = new RegExp(`${PH_PREFIX}(\\d+)${PH_SUFFIX}`, "g");
|
|
718
|
+
out = out.replace(phPattern, (_, idx) => placeholders[Number(idx)]);
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
function escapeHtml(text) {
|
|
722
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
723
|
+
}
|
|
724
|
+
|
|
746
725
|
// ../channels/dist/telegram/media.js
|
|
747
726
|
function registerMediaHandlers(bot, isAllowed, handlers, onRejected) {
|
|
748
727
|
bot.on("message:photo", async (ctx) => {
|
|
@@ -832,23 +811,20 @@ var TelegramChannel = class {
|
|
|
832
811
|
}
|
|
833
812
|
});
|
|
834
813
|
registerMediaHandlers(this.bot, (id) => this.isUserAllowed(id), this.handlers, (userId, ts) => this.handleRejected(userId, Math.floor(ts.getTime() / 1e3), config.rejectMessage));
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
814
|
+
const convertAndSend = async (msg) => {
|
|
815
|
+
const htmlText = markdownToTelegramHtml(msg.text);
|
|
816
|
+
const replyOpts = msg.replyTo ? { reply_parameters: { message_id: Number(msg.replyTo) } } : {};
|
|
817
|
+
await withRetry(() => this.bot.api.sendMessage(Number(msg.userId), htmlText, {
|
|
818
|
+
parse_mode: "HTML",
|
|
819
|
+
...replyOpts
|
|
839
820
|
}), { maxRetries: 3, baseDelayMs: 500 }).catch(async () => {
|
|
840
|
-
await this.bot.api.sendMessage(Number(msg.userId), msg.text, {
|
|
841
|
-
...msg.replyTo ? { reply_parameters: { message_id: Number(msg.replyTo) } } : {}
|
|
842
|
-
}).catch((fallbackErr) => {
|
|
821
|
+
await this.bot.api.sendMessage(Number(msg.userId), msg.text, replyOpts).catch((fallbackErr) => {
|
|
843
822
|
console.error("[augure:telegram] Fallback send also failed:", fallbackErr);
|
|
844
823
|
throw fallbackErr;
|
|
845
824
|
});
|
|
846
825
|
});
|
|
847
826
|
};
|
|
848
|
-
this.sendPipeline = createOutgoingPipeline([
|
|
849
|
-
createEscapeMarkdownMiddleware(),
|
|
850
|
-
createSplitMessageMiddleware(rawSend)
|
|
851
|
-
], rawSend);
|
|
827
|
+
this.sendPipeline = createOutgoingPipeline([createSplitMessageMiddleware(convertAndSend)], convertAndSend);
|
|
852
828
|
}
|
|
853
829
|
isUserAllowed(userId) {
|
|
854
830
|
return this.allowedUsers.has(userId);
|
|
@@ -967,7 +943,7 @@ var memoryWriteTool = {
|
|
|
967
943
|
// ../tools/dist/schedule.js
|
|
968
944
|
var scheduleTool = {
|
|
969
945
|
name: "schedule",
|
|
970
|
-
description: "Manage scheduled tasks: create, delete, or list
|
|
946
|
+
description: "Manage scheduled tasks: create recurring (cron) or one-shot (runAt) jobs, delete, or list them",
|
|
971
947
|
parameters: {
|
|
972
948
|
type: "object",
|
|
973
949
|
properties: {
|
|
@@ -977,13 +953,14 @@ var scheduleTool = {
|
|
|
977
953
|
description: "The scheduling action to perform"
|
|
978
954
|
},
|
|
979
955
|
id: { type: "string", description: "The schedule ID (for create/delete)" },
|
|
980
|
-
cron: { type: "string", description: "Cron expression (for create)" },
|
|
956
|
+
cron: { type: "string", description: "Cron expression for recurring jobs (for create)" },
|
|
957
|
+
runAt: { type: "string", description: "ISO 8601 date for one-shot jobs, e.g. 2025-03-15T14:00:00Z (for create)" },
|
|
981
958
|
prompt: { type: "string", description: "The prompt to execute on schedule (for create)" }
|
|
982
959
|
},
|
|
983
960
|
required: ["action"]
|
|
984
961
|
},
|
|
985
962
|
execute: async (params, ctx) => {
|
|
986
|
-
const { action, id, cron, prompt } = params;
|
|
963
|
+
const { action, id, cron, runAt, prompt } = params;
|
|
987
964
|
try {
|
|
988
965
|
switch (action) {
|
|
989
966
|
case "list": {
|
|
@@ -991,22 +968,29 @@ var scheduleTool = {
|
|
|
991
968
|
if (jobs.length === 0) {
|
|
992
969
|
return { success: true, output: "No scheduled jobs." };
|
|
993
970
|
}
|
|
994
|
-
const lines = jobs.map((j) =>
|
|
971
|
+
const lines = jobs.map((j) => {
|
|
972
|
+
const schedule = j.cron ? `cron: ${j.cron}` : `runAt: ${j.runAt}`;
|
|
973
|
+
return `- ${j.id}: "${j.prompt}" @ ${schedule} (${j.enabled ? "enabled" : "disabled"})`;
|
|
974
|
+
});
|
|
995
975
|
return { success: true, output: lines.join("\n") };
|
|
996
976
|
}
|
|
997
977
|
case "create": {
|
|
998
|
-
if (!
|
|
999
|
-
return { success: false, output: "Missing required
|
|
978
|
+
if (!prompt) {
|
|
979
|
+
return { success: false, output: "Missing required field: prompt" };
|
|
980
|
+
}
|
|
981
|
+
if (!cron && !runAt) {
|
|
982
|
+
return { success: false, output: "Must provide either cron (recurring) or runAt (one-shot)" };
|
|
1000
983
|
}
|
|
1001
984
|
const jobId = id ?? `job-${Date.now()}`;
|
|
1002
985
|
ctx.scheduler.addJob({
|
|
1003
986
|
id: jobId,
|
|
1004
987
|
cron,
|
|
988
|
+
runAt,
|
|
1005
989
|
prompt,
|
|
1006
990
|
channel: "default",
|
|
1007
991
|
enabled: true
|
|
1008
992
|
});
|
|
1009
|
-
return { success: true, output: `Created job ${jobId}` };
|
|
993
|
+
return { success: true, output: `Created job ${jobId} (${cron ? "recurring" : `one-shot at ${runAt}`})` };
|
|
1010
994
|
}
|
|
1011
995
|
case "delete": {
|
|
1012
996
|
if (!id) {
|
|
@@ -1665,6 +1649,63 @@ var DockerContainerPool = class {
|
|
|
1665
1649
|
}
|
|
1666
1650
|
};
|
|
1667
1651
|
|
|
1652
|
+
// ../sandbox/dist/ensure-image.js
|
|
1653
|
+
import { Readable } from "stream";
|
|
1654
|
+
var DOCKERFILE = `FROM node:22-slim
|
|
1655
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
1656
|
+
python3 curl jq git \\
|
|
1657
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
1658
|
+
WORKDIR /workspace
|
|
1659
|
+
`;
|
|
1660
|
+
function buildTar(content) {
|
|
1661
|
+
const data = Buffer.from(content, "utf-8");
|
|
1662
|
+
const name = "Dockerfile";
|
|
1663
|
+
const header = Buffer.alloc(512, 0);
|
|
1664
|
+
header.write(name, 0, 100, "utf-8");
|
|
1665
|
+
header.write("0000644\0", 100, 8, "utf-8");
|
|
1666
|
+
header.write("0000000\0", 108, 8, "utf-8");
|
|
1667
|
+
header.write("0000000\0", 116, 8, "utf-8");
|
|
1668
|
+
header.write(data.length.toString(8).padStart(11, "0") + "\0", 124, 12, "utf-8");
|
|
1669
|
+
header.write(Math.floor(Date.now() / 1e3).toString(8).padStart(11, "0") + "\0", 136, 12, "utf-8");
|
|
1670
|
+
header.write("0", 156, 1, "utf-8");
|
|
1671
|
+
header.fill(32, 148, 156);
|
|
1672
|
+
let checksum = 0;
|
|
1673
|
+
for (let i = 0; i < 512; i++)
|
|
1674
|
+
checksum += header[i];
|
|
1675
|
+
header.write(checksum.toString(8).padStart(6, "0") + "\0 ", 148, 8, "utf-8");
|
|
1676
|
+
const padding = 512 - (data.length % 512 || 512);
|
|
1677
|
+
const dataPadded = padding > 0 && padding < 512 ? Buffer.concat([data, Buffer.alloc(padding, 0)]) : data;
|
|
1678
|
+
const end = Buffer.alloc(1024, 0);
|
|
1679
|
+
return Buffer.concat([header, dataPadded, end]);
|
|
1680
|
+
}
|
|
1681
|
+
async function ensureImage(docker, imageName) {
|
|
1682
|
+
try {
|
|
1683
|
+
await docker.getImage(imageName).inspect();
|
|
1684
|
+
return;
|
|
1685
|
+
} catch (err2) {
|
|
1686
|
+
const statusCode = err2.statusCode;
|
|
1687
|
+
if (statusCode !== void 0 && statusCode !== 404)
|
|
1688
|
+
throw err2;
|
|
1689
|
+
}
|
|
1690
|
+
console.log(`[augure] Image "${imageName}" not found, building...`);
|
|
1691
|
+
const tar = buildTar(DOCKERFILE);
|
|
1692
|
+
const stream = await docker.buildImage(Readable.from(tar), {
|
|
1693
|
+
t: imageName
|
|
1694
|
+
});
|
|
1695
|
+
await new Promise((resolve5, reject) => {
|
|
1696
|
+
docker.modem.followProgress(stream, (err2) => {
|
|
1697
|
+
if (err2)
|
|
1698
|
+
reject(err2);
|
|
1699
|
+
else
|
|
1700
|
+
resolve5();
|
|
1701
|
+
}, (event) => {
|
|
1702
|
+
if (event.stream)
|
|
1703
|
+
process.stdout.write(event.stream);
|
|
1704
|
+
});
|
|
1705
|
+
});
|
|
1706
|
+
console.log(`[augure] Image "${imageName}" built successfully`);
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1668
1709
|
// ../memory/dist/store.js
|
|
1669
1710
|
import { readFile as readFile3, writeFile, mkdir as mkdir2, readdir as readdir2, access } from "fs/promises";
|
|
1670
1711
|
import { join as join3, dirname, relative } from "path";
|
|
@@ -1828,6 +1869,7 @@ var CronScheduler = class {
|
|
|
1828
1869
|
store;
|
|
1829
1870
|
jobs = /* @__PURE__ */ new Map();
|
|
1830
1871
|
tasks = /* @__PURE__ */ new Map();
|
|
1872
|
+
timers = /* @__PURE__ */ new Map();
|
|
1831
1873
|
handlers = [];
|
|
1832
1874
|
persistChain = Promise.resolve();
|
|
1833
1875
|
constructor(store) {
|
|
@@ -1837,11 +1879,17 @@ var CronScheduler = class {
|
|
|
1837
1879
|
this.handlers.push(handler);
|
|
1838
1880
|
}
|
|
1839
1881
|
addJob(job) {
|
|
1840
|
-
if (!
|
|
1882
|
+
if (!job.cron && !job.runAt) {
|
|
1883
|
+
throw new Error(`Job ${job.id} must have either cron or runAt`);
|
|
1884
|
+
}
|
|
1885
|
+
if (job.cron && !validate(job.cron)) {
|
|
1841
1886
|
throw new Error(`Invalid cron expression: ${job.cron}`);
|
|
1842
1887
|
}
|
|
1888
|
+
if (job.runAt && isNaN(Date.parse(job.runAt))) {
|
|
1889
|
+
throw new Error(`Invalid runAt date: ${job.runAt}`);
|
|
1890
|
+
}
|
|
1843
1891
|
this.jobs.set(job.id, job);
|
|
1844
|
-
if (job.enabled) {
|
|
1892
|
+
if (job.enabled && job.cron) {
|
|
1845
1893
|
const task = createTask(job.cron, () => {
|
|
1846
1894
|
void this.executeHandlers(job);
|
|
1847
1895
|
});
|
|
@@ -1855,6 +1903,11 @@ var CronScheduler = class {
|
|
|
1855
1903
|
task.stop();
|
|
1856
1904
|
this.tasks.delete(id);
|
|
1857
1905
|
}
|
|
1906
|
+
const timer = this.timers.get(id);
|
|
1907
|
+
if (timer) {
|
|
1908
|
+
clearTimeout(timer);
|
|
1909
|
+
this.timers.delete(id);
|
|
1910
|
+
}
|
|
1858
1911
|
this.jobs.delete(id);
|
|
1859
1912
|
this.persist();
|
|
1860
1913
|
}
|
|
@@ -1873,6 +1926,9 @@ var CronScheduler = class {
|
|
|
1873
1926
|
return;
|
|
1874
1927
|
const jobs = await this.store.load();
|
|
1875
1928
|
for (const job of jobs) {
|
|
1929
|
+
if (job.runAt && Date.parse(job.runAt) <= Date.now()) {
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1876
1932
|
this.addJob(job);
|
|
1877
1933
|
}
|
|
1878
1934
|
}
|
|
@@ -1880,11 +1936,32 @@ var CronScheduler = class {
|
|
|
1880
1936
|
for (const task of this.tasks.values()) {
|
|
1881
1937
|
task.start();
|
|
1882
1938
|
}
|
|
1939
|
+
for (const job of this.jobs.values()) {
|
|
1940
|
+
if (job.enabled && job.runAt && !job.cron) {
|
|
1941
|
+
this.scheduleOneShot(job);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1883
1944
|
}
|
|
1884
1945
|
stop() {
|
|
1885
1946
|
for (const task of this.tasks.values()) {
|
|
1886
1947
|
task.stop();
|
|
1887
1948
|
}
|
|
1949
|
+
for (const timer of this.timers.values()) {
|
|
1950
|
+
clearTimeout(timer);
|
|
1951
|
+
}
|
|
1952
|
+
this.timers.clear();
|
|
1953
|
+
}
|
|
1954
|
+
scheduleOneShot(job) {
|
|
1955
|
+
const delayMs = Date.parse(job.runAt) - Date.now();
|
|
1956
|
+
if (delayMs <= 0)
|
|
1957
|
+
return;
|
|
1958
|
+
const timer = setTimeout(() => {
|
|
1959
|
+
this.timers.delete(job.id);
|
|
1960
|
+
void this.executeHandlers(job).then(() => {
|
|
1961
|
+
this.removeJob(job.id);
|
|
1962
|
+
});
|
|
1963
|
+
}, delayMs);
|
|
1964
|
+
this.timers.set(job.id, timer);
|
|
1888
1965
|
}
|
|
1889
1966
|
persist() {
|
|
1890
1967
|
if (!this.store)
|
|
@@ -3222,6 +3299,17 @@ var SkillUpdater = class {
|
|
|
3222
3299
|
};
|
|
3223
3300
|
}
|
|
3224
3301
|
const toVersion = newSkill.meta.version;
|
|
3302
|
+
if (!newSkill.meta.sandbox) {
|
|
3303
|
+
await this.config.manager.save(backup);
|
|
3304
|
+
return {
|
|
3305
|
+
skillId,
|
|
3306
|
+
success: false,
|
|
3307
|
+
rolledBack: true,
|
|
3308
|
+
fromVersion,
|
|
3309
|
+
toVersion,
|
|
3310
|
+
error: "Downloaded skill has sandbox disabled \u2014 rejected for security"
|
|
3311
|
+
};
|
|
3312
|
+
}
|
|
3225
3313
|
const testResult = await this.config.tester.test(newSkill);
|
|
3226
3314
|
if (testResult.success) {
|
|
3227
3315
|
await this.config.manager.save(newSkill);
|
|
@@ -3295,10 +3383,11 @@ var VersionChecker = class _VersionChecker {
|
|
|
3295
3383
|
};
|
|
3296
3384
|
}
|
|
3297
3385
|
}
|
|
3298
|
-
/** Compare two semver strings. Returns -1 if a < b, 0 if equal, 1 if a > b */
|
|
3386
|
+
/** Compare two semver strings (MAJOR.MINOR.PATCH only, pre-release suffixes stripped). Returns -1 if a < b, 0 if equal, 1 if a > b */
|
|
3299
3387
|
static compareVersions(a, b) {
|
|
3300
|
-
const
|
|
3301
|
-
const
|
|
3388
|
+
const clean = (v) => v.replace(/^v/, "").split("-")[0];
|
|
3389
|
+
const pa = clean(a).split(".").map(Number);
|
|
3390
|
+
const pb = clean(b).split(".").map(Number);
|
|
3302
3391
|
for (let i = 0; i < 3; i++) {
|
|
3303
3392
|
const va = pa[i] ?? 0;
|
|
3304
3393
|
const vb = pb[i] ?? 0;
|
|
@@ -3356,8 +3445,10 @@ async function startAgent(configPath) {
|
|
|
3356
3445
|
}
|
|
3357
3446
|
}
|
|
3358
3447
|
const docker = new Dockerode();
|
|
3448
|
+
const sandboxImage = config.sandbox.image ?? "augure-sandbox:latest";
|
|
3449
|
+
await ensureImage(docker, sandboxImage);
|
|
3359
3450
|
const pool = new DockerContainerPool(docker, {
|
|
3360
|
-
image:
|
|
3451
|
+
image: sandboxImage,
|
|
3361
3452
|
maxTotal: config.security.maxConcurrentSandboxes
|
|
3362
3453
|
});
|
|
3363
3454
|
console.log(`[augure] Container pool created (max: ${config.security.maxConcurrentSandboxes})`);
|
|
@@ -3433,13 +3524,17 @@ async function startAgent(configPath) {
|
|
|
3433
3524
|
await personaResolver.loadAll();
|
|
3434
3525
|
console.log(`[augure] Personas loaded from ${personaPath}`);
|
|
3435
3526
|
}
|
|
3436
|
-
|
|
3527
|
+
let cliVersion;
|
|
3528
|
+
try {
|
|
3437
3529
|
const require3 = createRequire(import.meta.url);
|
|
3438
|
-
const
|
|
3530
|
+
const pkg = require3("augure/package.json");
|
|
3531
|
+
cliVersion = pkg.version;
|
|
3532
|
+
} catch {
|
|
3533
|
+
}
|
|
3534
|
+
if (cliVersion && config.updates?.cli?.enabled !== false) {
|
|
3439
3535
|
const versionChecker = new VersionChecker({
|
|
3440
|
-
currentVersion:
|
|
3441
|
-
packageName: "augure"
|
|
3442
|
-
githubRepo: "FaureAlexis/augure"
|
|
3536
|
+
currentVersion: cliVersion,
|
|
3537
|
+
packageName: "augure"
|
|
3443
3538
|
});
|
|
3444
3539
|
const versionResult = await versionChecker.check();
|
|
3445
3540
|
if (versionResult.updateAvailable) {
|
|
@@ -3526,14 +3621,37 @@ async function startAgent(configPath) {
|
|
|
3526
3621
|
console.log(`[augure] Heartbeat response: ${response}`);
|
|
3527
3622
|
}
|
|
3528
3623
|
});
|
|
3624
|
+
scheduler.onJobTrigger(async (job) => {
|
|
3625
|
+
console.log(`[augure] Job triggered: ${job.id}`);
|
|
3626
|
+
const response = await agent.handleMessage({
|
|
3627
|
+
id: `job-${job.id}-${Date.now()}`,
|
|
3628
|
+
channelType: "system",
|
|
3629
|
+
userId: "system",
|
|
3630
|
+
text: job.prompt,
|
|
3631
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
3632
|
+
});
|
|
3633
|
+
if (telegram && config.channels.telegram?.enabled) {
|
|
3634
|
+
const userId = config.channels.telegram.allowedUsers[0];
|
|
3635
|
+
if (userId !== void 0) {
|
|
3636
|
+
await telegram.send({
|
|
3637
|
+
channelType: "telegram",
|
|
3638
|
+
userId: String(userId),
|
|
3639
|
+
text: response
|
|
3640
|
+
});
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
console.log(`[augure] Job ${job.id} completed`);
|
|
3644
|
+
});
|
|
3529
3645
|
scheduler.start();
|
|
3530
3646
|
heartbeat.start();
|
|
3531
3647
|
console.log(`[augure] Scheduler started with ${scheduler.listJobs().length} jobs. Heartbeat every ${config.scheduler.heartbeatInterval}.`);
|
|
3648
|
+
const updateTimers = [];
|
|
3532
3649
|
if (skillUpdater && config.updates?.skills?.checkInterval) {
|
|
3650
|
+
const su = skillUpdater;
|
|
3533
3651
|
const skillCheckMs = parseInterval(config.updates.skills.checkInterval);
|
|
3534
|
-
setInterval(async () => {
|
|
3652
|
+
updateTimers.push(setInterval(async () => {
|
|
3535
3653
|
try {
|
|
3536
|
-
const results = await
|
|
3654
|
+
const results = await su.checkAndApply();
|
|
3537
3655
|
for (const r of results) {
|
|
3538
3656
|
if (r.success) {
|
|
3539
3657
|
console.log(`[augure] Skill auto-updated: ${r.skillId} v${r.fromVersion}\u2192v${r.toVersion}`);
|
|
@@ -3544,18 +3662,15 @@ async function startAgent(configPath) {
|
|
|
3544
3662
|
} catch (err2) {
|
|
3545
3663
|
console.error("[augure] Periodic skill update check failed:", err2);
|
|
3546
3664
|
}
|
|
3547
|
-
}, skillCheckMs);
|
|
3665
|
+
}, skillCheckMs));
|
|
3548
3666
|
}
|
|
3549
|
-
if (config.updates?.cli?.enabled !== false && config.channels.telegram?.enabled) {
|
|
3667
|
+
if (cliVersion && config.updates?.cli?.enabled !== false && config.channels.telegram?.enabled) {
|
|
3550
3668
|
const cliCheckMs = parseInterval(config.updates?.cli?.checkInterval ?? "24h");
|
|
3551
|
-
const require3 = createRequire(import.meta.url);
|
|
3552
|
-
const { version: version2 } = require3("augure/package.json");
|
|
3553
3669
|
const versionChecker = new VersionChecker({
|
|
3554
|
-
currentVersion:
|
|
3555
|
-
packageName: "augure"
|
|
3556
|
-
githubRepo: "FaureAlexis/augure"
|
|
3670
|
+
currentVersion: cliVersion,
|
|
3671
|
+
packageName: "augure"
|
|
3557
3672
|
});
|
|
3558
|
-
setInterval(async () => {
|
|
3673
|
+
updateTimers.push(setInterval(async () => {
|
|
3559
3674
|
try {
|
|
3560
3675
|
const result = await versionChecker.check();
|
|
3561
3676
|
if (result.updateAvailable && telegram) {
|
|
@@ -3572,10 +3687,12 @@ Run: \`npm update -g augure\``
|
|
|
3572
3687
|
} catch (err2) {
|
|
3573
3688
|
console.error("[augure] CLI version check failed:", err2);
|
|
3574
3689
|
}
|
|
3575
|
-
}, cliCheckMs);
|
|
3690
|
+
}, cliCheckMs));
|
|
3576
3691
|
}
|
|
3577
3692
|
const shutdown = async () => {
|
|
3578
3693
|
console.log("\n[augure] Shutting down...");
|
|
3694
|
+
for (const timer of updateTimers)
|
|
3695
|
+
clearInterval(timer);
|
|
3579
3696
|
heartbeat.stop();
|
|
3580
3697
|
scheduler.stop();
|
|
3581
3698
|
if (telegram)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "augure",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Augure — your proactive AI agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,15 +12,6 @@
|
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=22.0.0"
|
|
14
14
|
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsup",
|
|
17
|
-
"dev": "tsup --watch",
|
|
18
|
-
"test": "vitest run",
|
|
19
|
-
"test:unit": "vitest run",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
21
|
-
"lint": "eslint src/",
|
|
22
|
-
"clean": "rm -rf dist .turbo"
|
|
23
|
-
},
|
|
24
15
|
"dependencies": {
|
|
25
16
|
"citty": "^0.2.1",
|
|
26
17
|
"dockerode": "^4.0.9",
|
|
@@ -33,17 +24,17 @@
|
|
|
33
24
|
"zod": "^4.3.6"
|
|
34
25
|
},
|
|
35
26
|
"devDependencies": {
|
|
36
|
-
"@augure/channels": "workspace:*",
|
|
37
|
-
"@augure/core": "workspace:*",
|
|
38
|
-
"@augure/memory": "workspace:*",
|
|
39
|
-
"@augure/sandbox": "workspace:*",
|
|
40
|
-
"@augure/scheduler": "workspace:*",
|
|
41
|
-
"@augure/skills": "workspace:*",
|
|
42
|
-
"@augure/tools": "workspace:*",
|
|
43
|
-
"@augure/types": "workspace:*",
|
|
44
27
|
"@types/dockerode": "^4.0.1",
|
|
45
28
|
"@types/node-cron": "^3.0.11",
|
|
46
|
-
"tsup": "^8.5.1"
|
|
29
|
+
"tsup": "^8.5.1",
|
|
30
|
+
"@augure/channels": "0.1.1",
|
|
31
|
+
"@augure/core": "0.2.0",
|
|
32
|
+
"@augure/memory": "0.0.3",
|
|
33
|
+
"@augure/sandbox": "0.1.0",
|
|
34
|
+
"@augure/scheduler": "0.1.0",
|
|
35
|
+
"@augure/skills": "0.1.1",
|
|
36
|
+
"@augure/types": "0.1.1",
|
|
37
|
+
"@augure/tools": "0.0.3"
|
|
47
38
|
},
|
|
48
39
|
"keywords": [
|
|
49
40
|
"ai",
|
|
@@ -61,5 +52,14 @@
|
|
|
61
52
|
},
|
|
62
53
|
"publishConfig": {
|
|
63
54
|
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup",
|
|
58
|
+
"dev": "tsup --watch",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:unit": "vitest run",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"lint": "eslint src/",
|
|
63
|
+
"clean": "rm -rf dist .turbo"
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|