omnius 1.0.24 → 1.0.26
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/README.md +22 -14
- package/dist/index.js +1224 -95
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1483,7 +1483,7 @@ var init_security_classifier = __esm({
|
|
|
1483
1483
|
// ── Local writes (fs mutation)
|
|
1484
1484
|
{ match: /^(file_write|file_edit|file_patch|batch_edit|notebook_edit|structured_file|create_structured_file|image_resize)$/, info: LOCAL_WRITE },
|
|
1485
1485
|
{ match: /^(working_notes|todo_write)$/, info: LOCAL_WRITE },
|
|
1486
|
-
{ match: /^(scheduler|reminder|agenda)$/, info: SCHEDULER_REMINDER },
|
|
1486
|
+
{ match: /^(scheduler|cronjob|reminder|remind|reminders|agenda)$/, info: SCHEDULER_REMINDER },
|
|
1487
1487
|
{ match: /^(exploration_culture|explore)$/, info: LOCAL_WRITE },
|
|
1488
1488
|
// ── Task control
|
|
1489
1489
|
{ match: /^(task_status|task_output|task_stop)$/, info: TASK_CONTROL },
|
|
@@ -5763,7 +5763,10 @@ var init_explore_tools = __esm({
|
|
|
5763
5763
|
browser_action: "Interactive browser: login, fill forms, click buttons, screenshot — session persists between calls",
|
|
5764
5764
|
carbonyl_browser: "Terminal-rendered real browser automation via Carbonyl: navigate, read rendered text, click/type, sessions, daemon mode",
|
|
5765
5765
|
scheduler: "Schedule tasks for automatic future execution via OS cron",
|
|
5766
|
-
|
|
5766
|
+
cronjob: "Alias for scheduler: OS cron-backed time triggers",
|
|
5767
|
+
reminder: "Set scoped minimal reminders or scheduled action triggers",
|
|
5768
|
+
remind: "Alias for reminder: create or list scoped reminders",
|
|
5769
|
+
reminders: "Alias for reminder: list and manage scoped reminders",
|
|
5767
5770
|
agenda: "View all pending reminders, scheduled tasks, and attention items",
|
|
5768
5771
|
background_run: "Run a shell command in the background",
|
|
5769
5772
|
task_status: "Check status of background tasks",
|
|
@@ -74631,12 +74634,12 @@ var require_x509_cjs = __commonJS({
|
|
|
74631
74634
|
var require_crypto = __commonJS({
|
|
74632
74635
|
"../node_modules/acme-client/src/crypto/index.js"(exports) {
|
|
74633
74636
|
var net5 = __require("net");
|
|
74634
|
-
var { promisify:
|
|
74637
|
+
var { promisify: promisify7 } = __require("util");
|
|
74635
74638
|
var crypto14 = __require("crypto");
|
|
74636
74639
|
var asn1js4 = require_build2();
|
|
74637
74640
|
var x5093 = require_x509_cjs();
|
|
74638
|
-
var randomInt2 =
|
|
74639
|
-
var generateKeyPair2 =
|
|
74641
|
+
var randomInt2 = promisify7(crypto14.randomInt);
|
|
74642
|
+
var generateKeyPair2 = promisify7(crypto14.generateKeyPair);
|
|
74640
74643
|
x5093.cryptoProvider.set(crypto14.webcrypto);
|
|
74641
74644
|
var subjectAltNameOID = "2.5.29.17";
|
|
74642
74645
|
var alpnAcmeIdentifierOID = "1.3.6.1.5.5.7.1.31";
|
|
@@ -109481,9 +109484,9 @@ var require_lib = __commonJS({
|
|
|
109481
109484
|
var require_forge2 = __commonJS({
|
|
109482
109485
|
"../node_modules/acme-client/src/crypto/forge.js"(exports) {
|
|
109483
109486
|
var net5 = __require("net");
|
|
109484
|
-
var { promisify:
|
|
109487
|
+
var { promisify: promisify7 } = __require("util");
|
|
109485
109488
|
var forge = require_lib();
|
|
109486
|
-
var generateKeyPair2 =
|
|
109489
|
+
var generateKeyPair2 = promisify7(forge.pki.rsa.generateKeyPair);
|
|
109487
109490
|
function forgeObjectFromPem(input) {
|
|
109488
109491
|
const msg = forge.pem.decode(input)[0];
|
|
109489
109492
|
let result;
|
|
@@ -126709,7 +126712,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
126709
126712
|
var require_mock_client = __commonJS({
|
|
126710
126713
|
"../node_modules/undici/lib/mock/mock-client.js"(exports, module) {
|
|
126711
126714
|
"use strict";
|
|
126712
|
-
var { promisify:
|
|
126715
|
+
var { promisify: promisify7 } = __require("node:util");
|
|
126713
126716
|
var Client2 = require_client2();
|
|
126714
126717
|
var { buildMockDispatch } = require_mock_utils();
|
|
126715
126718
|
var {
|
|
@@ -126757,7 +126760,7 @@ var require_mock_client = __commonJS({
|
|
|
126757
126760
|
this[kDispatches] = [];
|
|
126758
126761
|
}
|
|
126759
126762
|
async [kClose]() {
|
|
126760
|
-
await
|
|
126763
|
+
await promisify7(this[kOriginalClose])();
|
|
126761
126764
|
this[kConnected] = 0;
|
|
126762
126765
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
126763
126766
|
}
|
|
@@ -126970,7 +126973,7 @@ var require_mock_call_history = __commonJS({
|
|
|
126970
126973
|
var require_mock_pool = __commonJS({
|
|
126971
126974
|
"../node_modules/undici/lib/mock/mock-pool.js"(exports, module) {
|
|
126972
126975
|
"use strict";
|
|
126973
|
-
var { promisify:
|
|
126976
|
+
var { promisify: promisify7 } = __require("node:util");
|
|
126974
126977
|
var Pool = require_pool();
|
|
126975
126978
|
var { buildMockDispatch } = require_mock_utils();
|
|
126976
126979
|
var {
|
|
@@ -127018,7 +127021,7 @@ var require_mock_pool = __commonJS({
|
|
|
127018
127021
|
this[kDispatches] = [];
|
|
127019
127022
|
}
|
|
127020
127023
|
async [kClose]() {
|
|
127021
|
-
await
|
|
127024
|
+
await promisify7(this[kOriginalClose])();
|
|
127022
127025
|
this[kConnected] = 0;
|
|
127023
127026
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
127024
127027
|
}
|
|
@@ -257491,6 +257494,58 @@ function resolveSchedule(schedule) {
|
|
|
257491
257494
|
const lower = schedule.toLowerCase().trim();
|
|
257492
257495
|
if (SCHEDULE_PRESETS[lower])
|
|
257493
257496
|
return SCHEDULE_PRESETS[lower];
|
|
257497
|
+
const dailyAt = lower.match(/^(?:daily|every\s+day)\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
257498
|
+
if (dailyAt) {
|
|
257499
|
+
const hour2 = parseInt(dailyAt[1], 10);
|
|
257500
|
+
const minute3 = parseInt(dailyAt[2], 10);
|
|
257501
|
+
if (isClockTime(hour2, minute3))
|
|
257502
|
+
return `${minute3} ${hour2} * * *`;
|
|
257503
|
+
}
|
|
257504
|
+
const weeklyAt = lower.match(/^weekly(?:\s+on)?\s+([a-z]+|\d)\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
257505
|
+
if (weeklyAt) {
|
|
257506
|
+
const dow = parseWeekday(weeklyAt[1]);
|
|
257507
|
+
const hour2 = parseInt(weeklyAt[2], 10);
|
|
257508
|
+
const minute3 = parseInt(weeklyAt[3], 10);
|
|
257509
|
+
if (dow !== null && isClockTime(hour2, minute3))
|
|
257510
|
+
return `${minute3} ${hour2} * * ${dow}`;
|
|
257511
|
+
}
|
|
257512
|
+
const monthlyAt = lower.match(/^monthly(?:\s+(?:on|day))?\s+(\d{1,2})(?:st|nd|rd|th)?\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
257513
|
+
if (monthlyAt) {
|
|
257514
|
+
const day = parseInt(monthlyAt[1], 10);
|
|
257515
|
+
const hour2 = parseInt(monthlyAt[2], 10);
|
|
257516
|
+
const minute3 = parseInt(monthlyAt[3], 10);
|
|
257517
|
+
if (day >= 1 && day <= 31 && isClockTime(hour2, minute3))
|
|
257518
|
+
return `${minute3} ${hour2} ${day} * *`;
|
|
257519
|
+
}
|
|
257520
|
+
const yearlyNumeric = lower.match(/^(?:yearly|annually|every\s+year)\s+(?:on\s+)?(\d{1,2})-(\d{1,2})\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
257521
|
+
if (yearlyNumeric) {
|
|
257522
|
+
const month = parseInt(yearlyNumeric[1], 10);
|
|
257523
|
+
const day = parseInt(yearlyNumeric[2], 10);
|
|
257524
|
+
const hour2 = parseInt(yearlyNumeric[3], 10);
|
|
257525
|
+
const minute3 = parseInt(yearlyNumeric[4], 10);
|
|
257526
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && isClockTime(hour2, minute3)) {
|
|
257527
|
+
return `${minute3} ${hour2} ${day} ${month} *`;
|
|
257528
|
+
}
|
|
257529
|
+
}
|
|
257530
|
+
const yearlyNamed = lower.match(/^(?:yearly|annually|every\s+year)\s+(?:on\s+)?([a-z]+)\s+(\d{1,2})(?:st|nd|rd|th)?\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
257531
|
+
if (yearlyNamed) {
|
|
257532
|
+
const month = parseMonth(yearlyNamed[1]);
|
|
257533
|
+
const day = parseInt(yearlyNamed[2], 10);
|
|
257534
|
+
const hour2 = parseInt(yearlyNamed[3], 10);
|
|
257535
|
+
const minute3 = parseInt(yearlyNamed[4], 10);
|
|
257536
|
+
if (month !== null && day >= 1 && day <= 31 && isClockTime(hour2, minute3)) {
|
|
257537
|
+
return `${minute3} ${hour2} ${day} ${month} *`;
|
|
257538
|
+
}
|
|
257539
|
+
}
|
|
257540
|
+
const everyLong = lower.match(/^every\s+(\d+)\s*(w|wk|wks|weeks?|mo|mos|months?)$/);
|
|
257541
|
+
if (everyLong) {
|
|
257542
|
+
const amount = parseInt(everyLong[1], 10);
|
|
257543
|
+
const unit = everyLong[2].charAt(0);
|
|
257544
|
+
if (amount > 0 && unit === "w")
|
|
257545
|
+
return `0 9 */${amount * 7} * *`;
|
|
257546
|
+
if (amount > 0 && unit === "m")
|
|
257547
|
+
return `0 9 1 */${amount} *`;
|
|
257548
|
+
}
|
|
257494
257549
|
const inMatch = lower.match(/^in\s+(\d+)\s*(m|min|mins|minutes?|h|hr|hrs|hours?|d|days?)$/);
|
|
257495
257550
|
if (inMatch) {
|
|
257496
257551
|
const amount = parseInt(inMatch[1], 10);
|
|
@@ -257516,6 +257571,65 @@ function resolveSchedule(schedule) {
|
|
|
257516
257571
|
return schedule.trim();
|
|
257517
257572
|
return null;
|
|
257518
257573
|
}
|
|
257574
|
+
function isClockTime(hour2, minute3) {
|
|
257575
|
+
return hour2 >= 0 && hour2 <= 23 && minute3 >= 0 && minute3 <= 59;
|
|
257576
|
+
}
|
|
257577
|
+
function parseWeekday(raw) {
|
|
257578
|
+
const value2 = raw.toLowerCase();
|
|
257579
|
+
if (/^[0-6]$/.test(value2))
|
|
257580
|
+
return Number(value2);
|
|
257581
|
+
const days = {
|
|
257582
|
+
sunday: 0,
|
|
257583
|
+
sun: 0,
|
|
257584
|
+
monday: 1,
|
|
257585
|
+
mon: 1,
|
|
257586
|
+
tuesday: 2,
|
|
257587
|
+
tue: 2,
|
|
257588
|
+
tues: 2,
|
|
257589
|
+
wednesday: 3,
|
|
257590
|
+
wed: 3,
|
|
257591
|
+
thursday: 4,
|
|
257592
|
+
thu: 4,
|
|
257593
|
+
thurs: 4,
|
|
257594
|
+
friday: 5,
|
|
257595
|
+
fri: 5,
|
|
257596
|
+
saturday: 6,
|
|
257597
|
+
sat: 6
|
|
257598
|
+
};
|
|
257599
|
+
return days[value2] ?? null;
|
|
257600
|
+
}
|
|
257601
|
+
function parseMonth(raw) {
|
|
257602
|
+
const value2 = raw.toLowerCase();
|
|
257603
|
+
if (/^(?:[1-9]|1[0-2])$/.test(value2))
|
|
257604
|
+
return Number(value2);
|
|
257605
|
+
const months = {
|
|
257606
|
+
january: 1,
|
|
257607
|
+
jan: 1,
|
|
257608
|
+
february: 2,
|
|
257609
|
+
feb: 2,
|
|
257610
|
+
march: 3,
|
|
257611
|
+
mar: 3,
|
|
257612
|
+
april: 4,
|
|
257613
|
+
apr: 4,
|
|
257614
|
+
may: 5,
|
|
257615
|
+
june: 6,
|
|
257616
|
+
jun: 6,
|
|
257617
|
+
july: 7,
|
|
257618
|
+
jul: 7,
|
|
257619
|
+
august: 8,
|
|
257620
|
+
aug: 8,
|
|
257621
|
+
september: 9,
|
|
257622
|
+
sep: 9,
|
|
257623
|
+
sept: 9,
|
|
257624
|
+
october: 10,
|
|
257625
|
+
oct: 10,
|
|
257626
|
+
november: 11,
|
|
257627
|
+
nov: 11,
|
|
257628
|
+
december: 12,
|
|
257629
|
+
dec: 12
|
|
257630
|
+
};
|
|
257631
|
+
return months[value2] ?? null;
|
|
257632
|
+
}
|
|
257519
257633
|
function describeCron(expr) {
|
|
257520
257634
|
const parts = expr.split(/\s+/);
|
|
257521
257635
|
if (parts.length !== 5)
|
|
@@ -257705,12 +257819,14 @@ var init_scheduler = __esm({
|
|
|
257705
257819
|
"daily evening": "0 18 * * *",
|
|
257706
257820
|
"weekly": "0 9 * * 1",
|
|
257707
257821
|
"monthly": "0 9 1 * *",
|
|
257822
|
+
"yearly": "0 9 1 1 *",
|
|
257823
|
+
"annually": "0 9 1 1 *",
|
|
257708
257824
|
"hourly": "0 * * * *"
|
|
257709
257825
|
};
|
|
257710
257826
|
CRON_MARKER = "# OMNIUS-SCHEDULED:";
|
|
257711
257827
|
SchedulerTool = class {
|
|
257712
257828
|
name = "scheduler";
|
|
257713
|
-
description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', '
|
|
257829
|
+
description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', 'weekly', 'monthly', 'yearly'), intervals ('every 5 minutes'), 24-hour times ('at 14:30', 'weekly friday at 17:45', 'monthly on 15 at 08:30'), or raw cron expressions ('0 */2 * * *'). Scope: 'local' (default, stored in .omnius/) or 'global' (stored in ~/.omnius/, visible from all projects). Tasks launch the agent automatically at the scheduled time.";
|
|
257714
257830
|
parameters = {
|
|
257715
257831
|
type: "object",
|
|
257716
257832
|
properties: {
|
|
@@ -257725,7 +257841,7 @@ var init_scheduler = __esm({
|
|
|
257725
257841
|
},
|
|
257726
257842
|
schedule: {
|
|
257727
257843
|
type: "string",
|
|
257728
|
-
description: "When to run: preset ('daily', 'every 5 minutes'),
|
|
257844
|
+
description: "When to run: preset ('daily', 'weekly', 'monthly', 'yearly'), interval ('every 5 minutes'), 24-hour time ('at 14:30', 'weekly friday at 17:45'), or cron ('0 */2 * * *')"
|
|
257729
257845
|
},
|
|
257730
257846
|
id: {
|
|
257731
257847
|
type: "string",
|
|
@@ -258027,6 +258143,219 @@ function parseDueTime(due) {
|
|
|
258027
258143
|
}
|
|
258028
258144
|
return null;
|
|
258029
258145
|
}
|
|
258146
|
+
function parseDurationMs(input) {
|
|
258147
|
+
const lower = input.toLowerCase().trim();
|
|
258148
|
+
const match = lower.match(/^(?:every\s+)?(\d+)\s*(m|min|mins|minutes?|h|hr|hrs|hours?|d|days?|w|wk|wks|weeks?)$/);
|
|
258149
|
+
if (!match)
|
|
258150
|
+
return null;
|
|
258151
|
+
const amount = parseInt(match[1], 10);
|
|
258152
|
+
if (!Number.isFinite(amount) || amount <= 0)
|
|
258153
|
+
return null;
|
|
258154
|
+
const unit = match[2].charAt(0);
|
|
258155
|
+
const ms = unit === "m" ? amount * 6e4 : unit === "h" ? amount * 36e5 : unit === "d" ? amount * 864e5 : amount * 7 * 864e5;
|
|
258156
|
+
return {
|
|
258157
|
+
ms,
|
|
258158
|
+
description: `every ${amount} ${unit === "m" ? "minute" : unit === "h" ? "hour" : unit === "d" ? "day" : "week"}${amount === 1 ? "" : "s"}`
|
|
258159
|
+
};
|
|
258160
|
+
}
|
|
258161
|
+
function parseTimeOfDay(value2) {
|
|
258162
|
+
const raw = String(value2 ?? "").trim();
|
|
258163
|
+
const match = raw.match(/^(\d{1,2}):(\d{2})$/);
|
|
258164
|
+
if (!match)
|
|
258165
|
+
return void 0;
|
|
258166
|
+
const hour2 = parseInt(match[1], 10);
|
|
258167
|
+
const minute3 = parseInt(match[2], 10);
|
|
258168
|
+
if (hour2 < 0 || hour2 > 23 || minute3 < 0 || minute3 > 59)
|
|
258169
|
+
return void 0;
|
|
258170
|
+
return `${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}`;
|
|
258171
|
+
}
|
|
258172
|
+
function parseWeekday2(value2) {
|
|
258173
|
+
if (typeof value2 === "number" && Number.isFinite(value2)) {
|
|
258174
|
+
const day = Math.trunc(value2);
|
|
258175
|
+
return day >= 0 && day <= 6 ? day : void 0;
|
|
258176
|
+
}
|
|
258177
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
258178
|
+
if (!raw)
|
|
258179
|
+
return void 0;
|
|
258180
|
+
const names = {
|
|
258181
|
+
sunday: 0,
|
|
258182
|
+
sun: 0,
|
|
258183
|
+
monday: 1,
|
|
258184
|
+
mon: 1,
|
|
258185
|
+
tuesday: 2,
|
|
258186
|
+
tue: 2,
|
|
258187
|
+
tues: 2,
|
|
258188
|
+
wednesday: 3,
|
|
258189
|
+
wed: 3,
|
|
258190
|
+
thursday: 4,
|
|
258191
|
+
thu: 4,
|
|
258192
|
+
thurs: 4,
|
|
258193
|
+
friday: 5,
|
|
258194
|
+
fri: 5,
|
|
258195
|
+
saturday: 6,
|
|
258196
|
+
sat: 6
|
|
258197
|
+
};
|
|
258198
|
+
if (/^[0-6]$/.test(raw))
|
|
258199
|
+
return Number(raw);
|
|
258200
|
+
return names[raw];
|
|
258201
|
+
}
|
|
258202
|
+
function parseMonth2(value2) {
|
|
258203
|
+
if (typeof value2 === "number" && Number.isFinite(value2)) {
|
|
258204
|
+
const month = Math.trunc(value2);
|
|
258205
|
+
return month >= 1 && month <= 12 ? month : void 0;
|
|
258206
|
+
}
|
|
258207
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
258208
|
+
if (!raw)
|
|
258209
|
+
return void 0;
|
|
258210
|
+
const names = {
|
|
258211
|
+
january: 1,
|
|
258212
|
+
jan: 1,
|
|
258213
|
+
february: 2,
|
|
258214
|
+
feb: 2,
|
|
258215
|
+
march: 3,
|
|
258216
|
+
mar: 3,
|
|
258217
|
+
april: 4,
|
|
258218
|
+
apr: 4,
|
|
258219
|
+
may: 5,
|
|
258220
|
+
june: 6,
|
|
258221
|
+
jun: 6,
|
|
258222
|
+
july: 7,
|
|
258223
|
+
jul: 7,
|
|
258224
|
+
august: 8,
|
|
258225
|
+
aug: 8,
|
|
258226
|
+
september: 9,
|
|
258227
|
+
sep: 9,
|
|
258228
|
+
sept: 9,
|
|
258229
|
+
october: 10,
|
|
258230
|
+
oct: 10,
|
|
258231
|
+
november: 11,
|
|
258232
|
+
nov: 11,
|
|
258233
|
+
december: 12,
|
|
258234
|
+
dec: 12
|
|
258235
|
+
};
|
|
258236
|
+
if (/^(?:[1-9]|1[0-2])$/.test(raw))
|
|
258237
|
+
return Number(raw);
|
|
258238
|
+
return names[raw];
|
|
258239
|
+
}
|
|
258240
|
+
function parseRecurrence(args) {
|
|
258241
|
+
const repeatRaw = String(args["repeat"] ?? args["recurrence"] ?? "").trim();
|
|
258242
|
+
if (!repeatRaw)
|
|
258243
|
+
return void 0;
|
|
258244
|
+
const lower = repeatRaw.toLowerCase();
|
|
258245
|
+
if (["none", "off", "false", "no"].includes(lower))
|
|
258246
|
+
return void 0;
|
|
258247
|
+
const maxOccurrences = typeof args["max_occurrences"] === "number" && Number.isFinite(args["max_occurrences"]) ? Math.max(1, Math.floor(args["max_occurrences"])) : typeof args["max_runs"] === "number" && Number.isFinite(args["max_runs"]) ? Math.max(1, Math.floor(args["max_runs"])) : void 0;
|
|
258248
|
+
const intervalInput = lower.startsWith("every ") ? lower : String(args["every"] ?? "").trim().toLowerCase();
|
|
258249
|
+
const interval = parseDurationMs(intervalInput);
|
|
258250
|
+
if (interval) {
|
|
258251
|
+
return {
|
|
258252
|
+
kind: "interval",
|
|
258253
|
+
everyMs: interval.ms,
|
|
258254
|
+
intervalDescription: interval.description,
|
|
258255
|
+
...maxOccurrences ? { maxOccurrences } : {}
|
|
258256
|
+
};
|
|
258257
|
+
}
|
|
258258
|
+
const repeatTime = lower.match(/\bat\s+(\d{1,2}:\d{2})\b/)?.[1];
|
|
258259
|
+
const timeOfDay = parseTimeOfDay(args["time"]) ?? parseTimeOfDay(args["at"]) ?? parseTimeOfDay(repeatTime);
|
|
258260
|
+
const withMax = (recurrence) => maxOccurrences ? { ...recurrence, maxOccurrences } : recurrence;
|
|
258261
|
+
if (lower === "daily" || lower === "every day") {
|
|
258262
|
+
return withMax({ kind: "daily", timeOfDay: timeOfDay ?? "09:00" });
|
|
258263
|
+
}
|
|
258264
|
+
if (lower.startsWith("weekly") || lower === "every week") {
|
|
258265
|
+
const dayFromText = lower.match(/\b(sun(?:day)?|mon(?:day)?|tue(?:s|sday)?|wed(?:nesday)?|thu(?:rs|rsday)?|fri(?:day)?|sat(?:urday)?)\b/i)?.[1];
|
|
258266
|
+
return withMax({
|
|
258267
|
+
kind: "weekly",
|
|
258268
|
+
weekday: parseWeekday2(args["weekday"] ?? dayFromText) ?? 1,
|
|
258269
|
+
timeOfDay: timeOfDay ?? "09:00"
|
|
258270
|
+
});
|
|
258271
|
+
}
|
|
258272
|
+
if (lower.startsWith("monthly") || lower === "every month") {
|
|
258273
|
+
const dayRaw = args["day_of_month"] ?? args["day"] ?? lower.match(/\b(?:day|on)\s+(\d{1,2})\b/)?.[1];
|
|
258274
|
+
const day = typeof dayRaw === "number" ? Math.trunc(dayRaw) : parseInt(String(dayRaw ?? "1"), 10);
|
|
258275
|
+
return withMax({
|
|
258276
|
+
kind: "monthly",
|
|
258277
|
+
dayOfMonth: Math.max(1, Math.min(31, Number.isFinite(day) ? day : 1)),
|
|
258278
|
+
timeOfDay: timeOfDay ?? "09:00"
|
|
258279
|
+
});
|
|
258280
|
+
}
|
|
258281
|
+
if (lower.startsWith("yearly") || lower === "annually" || lower === "every year") {
|
|
258282
|
+
const yearlyText = lower.match(/\b(jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:t|tember)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?|\d{1,2})\s+(\d{1,2})(?:st|nd|rd|th)?\b/i);
|
|
258283
|
+
const month = parseMonth2(args["month"] ?? yearlyText?.[1]) ?? 1;
|
|
258284
|
+
const dayRaw = args["day_of_month"] ?? args["day"] ?? yearlyText?.[2] ?? 1;
|
|
258285
|
+
const day = typeof dayRaw === "number" ? Math.trunc(dayRaw) : parseInt(String(dayRaw), 10);
|
|
258286
|
+
return withMax({
|
|
258287
|
+
kind: "yearly",
|
|
258288
|
+
month,
|
|
258289
|
+
dayOfMonth: Math.max(1, Math.min(31, Number.isFinite(day) ? day : 1)),
|
|
258290
|
+
timeOfDay: timeOfDay ?? "09:00"
|
|
258291
|
+
});
|
|
258292
|
+
}
|
|
258293
|
+
return null;
|
|
258294
|
+
}
|
|
258295
|
+
function setLocalTime(target, timeOfDay, fallback = "09:00") {
|
|
258296
|
+
const [hourRaw, minuteRaw] = (timeOfDay ?? fallback).split(":");
|
|
258297
|
+
target.setHours(parseInt(hourRaw ?? "9", 10), parseInt(minuteRaw ?? "0", 10), 0, 0);
|
|
258298
|
+
}
|
|
258299
|
+
function clampDateToMonth(target, dayOfMonth) {
|
|
258300
|
+
target.setDate(1);
|
|
258301
|
+
const maxDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
|
|
258302
|
+
target.setDate(Math.min(Math.max(1, dayOfMonth), maxDay));
|
|
258303
|
+
}
|
|
258304
|
+
function nextDueFromRecurrence(recurrence, after = /* @__PURE__ */ new Date()) {
|
|
258305
|
+
const target = new Date(after);
|
|
258306
|
+
switch (recurrence.kind) {
|
|
258307
|
+
case "interval":
|
|
258308
|
+
return new Date(after.getTime() + Math.max(6e4, recurrence.everyMs ?? 864e5));
|
|
258309
|
+
case "daily":
|
|
258310
|
+
setLocalTime(target, recurrence.timeOfDay);
|
|
258311
|
+
if (target <= after)
|
|
258312
|
+
target.setDate(target.getDate() + 1);
|
|
258313
|
+
return target;
|
|
258314
|
+
case "weekly": {
|
|
258315
|
+
setLocalTime(target, recurrence.timeOfDay);
|
|
258316
|
+
const weekday = recurrence.weekday ?? 1;
|
|
258317
|
+
const daysAhead = (weekday - target.getDay() + 7) % 7;
|
|
258318
|
+
target.setDate(target.getDate() + daysAhead);
|
|
258319
|
+
if (target <= after)
|
|
258320
|
+
target.setDate(target.getDate() + 7);
|
|
258321
|
+
return target;
|
|
258322
|
+
}
|
|
258323
|
+
case "monthly":
|
|
258324
|
+
setLocalTime(target, recurrence.timeOfDay);
|
|
258325
|
+
clampDateToMonth(target, recurrence.dayOfMonth ?? 1);
|
|
258326
|
+
if (target <= after) {
|
|
258327
|
+
target.setMonth(target.getMonth() + 1);
|
|
258328
|
+
clampDateToMonth(target, recurrence.dayOfMonth ?? 1);
|
|
258329
|
+
}
|
|
258330
|
+
return target;
|
|
258331
|
+
case "yearly":
|
|
258332
|
+
target.setMonth((recurrence.month ?? 1) - 1, 1);
|
|
258333
|
+
clampDateToMonth(target, recurrence.dayOfMonth ?? 1);
|
|
258334
|
+
setLocalTime(target, recurrence.timeOfDay);
|
|
258335
|
+
if (target <= after) {
|
|
258336
|
+
target.setFullYear(target.getFullYear() + 1);
|
|
258337
|
+
target.setMonth((recurrence.month ?? 1) - 1, 1);
|
|
258338
|
+
clampDateToMonth(target, recurrence.dayOfMonth ?? 1);
|
|
258339
|
+
}
|
|
258340
|
+
return target;
|
|
258341
|
+
}
|
|
258342
|
+
}
|
|
258343
|
+
function describeRecurrence(recurrence) {
|
|
258344
|
+
if (!recurrence)
|
|
258345
|
+
return void 0;
|
|
258346
|
+
switch (recurrence.kind) {
|
|
258347
|
+
case "interval":
|
|
258348
|
+
return recurrence.intervalDescription ?? `every ${Math.round((recurrence.everyMs ?? 0) / 6e4)} minutes`;
|
|
258349
|
+
case "daily":
|
|
258350
|
+
return `daily at ${recurrence.timeOfDay ?? "09:00"}`;
|
|
258351
|
+
case "weekly":
|
|
258352
|
+
return `weekly on day ${recurrence.weekday ?? 1} at ${recurrence.timeOfDay ?? "09:00"}`;
|
|
258353
|
+
case "monthly":
|
|
258354
|
+
return `monthly on day ${recurrence.dayOfMonth ?? 1} at ${recurrence.timeOfDay ?? "09:00"}`;
|
|
258355
|
+
case "yearly":
|
|
258356
|
+
return `yearly on ${String(recurrence.month ?? 1).padStart(2, "0")}-${String(recurrence.dayOfMonth ?? 1).padStart(2, "0")} at ${recurrence.timeOfDay ?? "09:00"}`;
|
|
258357
|
+
}
|
|
258358
|
+
}
|
|
258030
258359
|
async function getStorePath(workingDir) {
|
|
258031
258360
|
const dir = resolve26(workingDir, ".omnius", "scheduled");
|
|
258032
258361
|
await mkdir14(dir, { recursive: true });
|
|
@@ -258046,28 +258375,77 @@ async function saveReminderStore(workingDir, store2) {
|
|
|
258046
258375
|
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
258047
258376
|
await writeFile19(storePath, JSON.stringify(store2, null, 2), "utf-8");
|
|
258048
258377
|
}
|
|
258049
|
-
async function getDueReminders(workingDir) {
|
|
258378
|
+
async function getDueReminders(workingDir, query = {}) {
|
|
258050
258379
|
const store2 = await loadReminderStore(workingDir);
|
|
258051
|
-
const now = /* @__PURE__ */ new Date();
|
|
258380
|
+
const now = query.now ?? /* @__PURE__ */ new Date();
|
|
258052
258381
|
return store2.reminders.filter((r2) => {
|
|
258053
258382
|
if (r2.status !== "pending")
|
|
258054
258383
|
return false;
|
|
258055
|
-
if (
|
|
258056
|
-
return
|
|
258057
|
-
|
|
258384
|
+
if (r2.dueAt && new Date(r2.dueAt) > now)
|
|
258385
|
+
return false;
|
|
258386
|
+
if (query.deliveryMode && query.deliveryMode !== "any" && (r2.delivery?.mode ?? "minimal") !== query.deliveryMode)
|
|
258387
|
+
return false;
|
|
258388
|
+
if (query.scope && !reminderScopeMatches(r2.scope, query.scope, query.includeUnscoped === true))
|
|
258389
|
+
return false;
|
|
258390
|
+
return true;
|
|
258058
258391
|
});
|
|
258059
258392
|
}
|
|
258060
258393
|
async function markRemindersSeen(workingDir, ids) {
|
|
258394
|
+
await markRemindersTriggered(workingDir, ids);
|
|
258395
|
+
}
|
|
258396
|
+
async function markRemindersTriggered(workingDir, ids, now = /* @__PURE__ */ new Date()) {
|
|
258061
258397
|
const store2 = await loadReminderStore(workingDir);
|
|
258062
258398
|
const idSet = new Set(ids);
|
|
258063
258399
|
for (const r2 of store2.reminders) {
|
|
258064
258400
|
if (idSet.has(r2.id) && r2.status === "pending") {
|
|
258065
|
-
r2.
|
|
258066
|
-
r2.
|
|
258401
|
+
r2.lastTriggeredAt = now.toISOString();
|
|
258402
|
+
r2.triggerCount = (r2.triggerCount ?? 0) + 1;
|
|
258403
|
+
const max = r2.recurrence?.maxOccurrences;
|
|
258404
|
+
if (r2.recurrence && (!max || r2.triggerCount < max)) {
|
|
258405
|
+
r2.dueAt = nextDueFromRecurrence(r2.recurrence, now).toISOString();
|
|
258406
|
+
r2.dueDescription = describeRecurrence(r2.recurrence);
|
|
258407
|
+
r2.seenAt = void 0;
|
|
258408
|
+
} else {
|
|
258409
|
+
r2.status = "seen";
|
|
258410
|
+
r2.seenAt = now.toISOString();
|
|
258411
|
+
}
|
|
258067
258412
|
}
|
|
258068
258413
|
}
|
|
258069
258414
|
await saveReminderStore(workingDir, store2);
|
|
258070
258415
|
}
|
|
258416
|
+
function reminderScopeMatches(scope, query, includeUnscoped) {
|
|
258417
|
+
if (!scope)
|
|
258418
|
+
return includeUnscoped;
|
|
258419
|
+
const keys = ["surface", "visibility", "targetId", "sessionId", "chatId", "threadId", "userId", "username", "label"];
|
|
258420
|
+
for (const key of keys) {
|
|
258421
|
+
const expected = query[key];
|
|
258422
|
+
if (expected !== void 0 && scope[key] !== expected)
|
|
258423
|
+
return false;
|
|
258424
|
+
}
|
|
258425
|
+
return true;
|
|
258426
|
+
}
|
|
258427
|
+
function normalizeDeliveryKind(value2) {
|
|
258428
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
258429
|
+
if (raw === "action" || raw === "agent" || raw === "agent_action")
|
|
258430
|
+
return "action";
|
|
258431
|
+
return "minimal";
|
|
258432
|
+
}
|
|
258433
|
+
function normalizeSurface(value2) {
|
|
258434
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
258435
|
+
return raw === "tui" || raw === "gui" || raw === "telegram" || raw === "api" || raw === "global" ? raw : void 0;
|
|
258436
|
+
}
|
|
258437
|
+
function normalizeVisibility(value2) {
|
|
258438
|
+
const raw = String(value2 ?? "").trim().toLowerCase();
|
|
258439
|
+
return raw === "private" || raw === "public" ? raw : void 0;
|
|
258440
|
+
}
|
|
258441
|
+
function stringValue(value2) {
|
|
258442
|
+
const raw = String(value2 ?? "").trim();
|
|
258443
|
+
return raw || void 0;
|
|
258444
|
+
}
|
|
258445
|
+
function formatScope(scope) {
|
|
258446
|
+
const label = scope.label ? ` (${scope.label})` : "";
|
|
258447
|
+
return `${scope.surface}/${scope.visibility}/${scope.targetId}${label}`;
|
|
258448
|
+
}
|
|
258071
258449
|
var STORE_FILE, ReminderTool;
|
|
258072
258450
|
var init_reminder = __esm({
|
|
258073
258451
|
"packages/execution/dist/tools/reminder.js"() {
|
|
@@ -258075,7 +258453,7 @@ var init_reminder = __esm({
|
|
|
258075
258453
|
STORE_FILE = "reminders.json";
|
|
258076
258454
|
ReminderTool = class {
|
|
258077
258455
|
name = "reminder";
|
|
258078
|
-
description = "Set reminders
|
|
258456
|
+
description = "Set scoped reminders and time-triggered action requests. Use kind='minimal' for raw text/content delivery and kind='action' when the trigger should start inference/tool-calling from a task_description. Actions: 'set' a new reminder, 'list' all reminders, 'complete' or 'dismiss' a reminder, 'snooze' to postpone. Reminders can have due dates, recurrence, priority, tags, and per-platform scopes.";
|
|
258079
258457
|
parameters = {
|
|
258080
258458
|
type: "object",
|
|
258081
258459
|
properties: {
|
|
@@ -258097,6 +258475,43 @@ var init_reminder = __esm({
|
|
|
258097
258475
|
enum: ["low", "normal", "high", "critical"],
|
|
258098
258476
|
description: "Priority level (default: normal)"
|
|
258099
258477
|
},
|
|
258478
|
+
kind: {
|
|
258479
|
+
type: "string",
|
|
258480
|
+
enum: ["minimal", "action"],
|
|
258481
|
+
description: "minimal sends raw reminder text/content only. action triggers an inference/tool-call task using task_description."
|
|
258482
|
+
},
|
|
258483
|
+
task_description: {
|
|
258484
|
+
type: "string",
|
|
258485
|
+
description: "For kind='action': the task the agent should perform when the trigger fires."
|
|
258486
|
+
},
|
|
258487
|
+
content: {
|
|
258488
|
+
type: "string",
|
|
258489
|
+
description: "For kind='minimal': raw text/content to deliver. Defaults to message."
|
|
258490
|
+
},
|
|
258491
|
+
repeat: {
|
|
258492
|
+
type: "string",
|
|
258493
|
+
description: "Optional recurrence: 'every 30m', 'daily', 'weekly monday', 'monthly', 'yearly'."
|
|
258494
|
+
},
|
|
258495
|
+
time: {
|
|
258496
|
+
type: "string",
|
|
258497
|
+
description: "24-hour local time HH:MM for daily/weekly/monthly/yearly recurrence."
|
|
258498
|
+
},
|
|
258499
|
+
weekday: {
|
|
258500
|
+
type: "string",
|
|
258501
|
+
description: "Weekday for weekly recurrence, e.g. 'monday' or 1."
|
|
258502
|
+
},
|
|
258503
|
+
day_of_month: {
|
|
258504
|
+
type: "number",
|
|
258505
|
+
description: "Day of month for monthly/yearly recurrence."
|
|
258506
|
+
},
|
|
258507
|
+
month: {
|
|
258508
|
+
type: "string",
|
|
258509
|
+
description: "Month for yearly recurrence, e.g. 'january' or 1."
|
|
258510
|
+
},
|
|
258511
|
+
max_occurrences: {
|
|
258512
|
+
type: "number",
|
|
258513
|
+
description: "Optional cap for recurring reminders."
|
|
258514
|
+
},
|
|
258100
258515
|
tags: {
|
|
258101
258516
|
type: "string",
|
|
258102
258517
|
description: "Comma-separated tags for categorization (e.g. 'deploy,auth,urgent')"
|
|
@@ -258112,13 +258527,29 @@ var init_reminder = __esm({
|
|
|
258112
258527
|
filter: {
|
|
258113
258528
|
type: "string",
|
|
258114
258529
|
description: "Filter by status: 'pending', 'seen', 'all' (for 'list', default: 'pending')"
|
|
258530
|
+
},
|
|
258531
|
+
surface: {
|
|
258532
|
+
type: "string",
|
|
258533
|
+
enum: ["tui", "gui", "telegram", "api", "global"],
|
|
258534
|
+
description: "Optional scope surface. Ignored when this tool is context-locked by a platform adapter."
|
|
258535
|
+
},
|
|
258536
|
+
visibility: {
|
|
258537
|
+
type: "string",
|
|
258538
|
+
enum: ["private", "public"],
|
|
258539
|
+
description: "Optional scope visibility. Ignored when context-locked."
|
|
258540
|
+
},
|
|
258541
|
+
target_id: {
|
|
258542
|
+
type: "string",
|
|
258543
|
+
description: "Optional scope target id. For Telegram this is the chat id. Ignored when context-locked."
|
|
258115
258544
|
}
|
|
258116
258545
|
},
|
|
258117
258546
|
required: ["action"]
|
|
258118
258547
|
};
|
|
258119
258548
|
workingDir;
|
|
258120
|
-
|
|
258549
|
+
options;
|
|
258550
|
+
constructor(workingDir, options2 = {}) {
|
|
258121
258551
|
this.workingDir = workingDir;
|
|
258552
|
+
this.options = options2;
|
|
258122
258553
|
}
|
|
258123
258554
|
async execute(args) {
|
|
258124
258555
|
const start2 = performance.now();
|
|
@@ -258161,6 +258592,33 @@ var init_reminder = __esm({
|
|
|
258161
258592
|
const tags = tagsStr ? tagsStr.split(",").map((t2) => t2.trim()).filter(Boolean) : [];
|
|
258162
258593
|
const context2 = args["context"] ?? void 0;
|
|
258163
258594
|
const dueStr = args["due"] ?? "";
|
|
258595
|
+
const recurrence = parseRecurrence(args);
|
|
258596
|
+
if (recurrence === null) {
|
|
258597
|
+
return {
|
|
258598
|
+
success: false,
|
|
258599
|
+
output: "",
|
|
258600
|
+
error: `Cannot parse repeat '${String(args["repeat"] ?? args["recurrence"])}'. Try: 'every 30m', 'daily', 'weekly monday', 'monthly', or 'yearly'.`,
|
|
258601
|
+
durationMs: performance.now() - start2
|
|
258602
|
+
};
|
|
258603
|
+
}
|
|
258604
|
+
const kind = normalizeDeliveryKind(args["kind"] ?? args["mode"] ?? args["delivery"]);
|
|
258605
|
+
if (kind === "action" && !this.options.allowActionDelivery) {
|
|
258606
|
+
return {
|
|
258607
|
+
success: false,
|
|
258608
|
+
output: "",
|
|
258609
|
+
error: "kind='action' is not allowed in this context. Use kind='minimal' for a plain reminder.",
|
|
258610
|
+
durationMs: performance.now() - start2
|
|
258611
|
+
};
|
|
258612
|
+
}
|
|
258613
|
+
const taskDescription = String(args["task_description"] ?? args["task"] ?? args["prompt"] ?? "").trim();
|
|
258614
|
+
if (kind === "action" && !taskDescription) {
|
|
258615
|
+
return {
|
|
258616
|
+
success: false,
|
|
258617
|
+
output: "",
|
|
258618
|
+
error: "task_description is required when kind='action'",
|
|
258619
|
+
durationMs: performance.now() - start2
|
|
258620
|
+
};
|
|
258621
|
+
}
|
|
258164
258622
|
let dueAt;
|
|
258165
258623
|
let dueDescription;
|
|
258166
258624
|
if (dueStr) {
|
|
@@ -258175,7 +258633,12 @@ var init_reminder = __esm({
|
|
|
258175
258633
|
}
|
|
258176
258634
|
dueAt = parsed.isoDate;
|
|
258177
258635
|
dueDescription = parsed.description;
|
|
258636
|
+
} else if (recurrence) {
|
|
258637
|
+
dueAt = nextDueFromRecurrence(recurrence).toISOString();
|
|
258638
|
+
dueDescription = describeRecurrence(recurrence);
|
|
258178
258639
|
}
|
|
258640
|
+
const scope = this.resolveScope(args);
|
|
258641
|
+
const content = String(args["content"] ?? message2).trim() || message2;
|
|
258179
258642
|
const id = `rem-${randomBytes12(4).toString("hex")}`;
|
|
258180
258643
|
const entry = {
|
|
258181
258644
|
id,
|
|
@@ -258187,7 +258650,14 @@ var init_reminder = __esm({
|
|
|
258187
258650
|
tags,
|
|
258188
258651
|
status: "pending",
|
|
258189
258652
|
context: context2,
|
|
258190
|
-
source: "agent"
|
|
258653
|
+
source: this.options.source ?? "agent",
|
|
258654
|
+
...scope ? { scope } : {},
|
|
258655
|
+
delivery: {
|
|
258656
|
+
mode: kind,
|
|
258657
|
+
...kind === "action" ? { taskDescription } : { content },
|
|
258658
|
+
...this.options.createdFrom ? { createdFrom: this.options.createdFrom } : {}
|
|
258659
|
+
},
|
|
258660
|
+
...recurrence ? { recurrence } : {}
|
|
258191
258661
|
};
|
|
258192
258662
|
const store2 = await loadReminderStore(this.workingDir);
|
|
258193
258663
|
store2.reminders.push(entry);
|
|
@@ -258199,11 +258669,15 @@ var init_reminder = __esm({
|
|
|
258199
258669
|
` ID: ${id}`,
|
|
258200
258670
|
` Message: ${message2}`,
|
|
258201
258671
|
` Priority: ${priority}`,
|
|
258672
|
+
` Kind: ${kind}`,
|
|
258673
|
+
kind === "action" ? ` Task: ${taskDescription}` : "",
|
|
258202
258674
|
dueDescription ? ` Due: ${dueDescription}` : ` Due: next startup`,
|
|
258675
|
+
describeRecurrence(recurrence) ? ` Repeats: ${describeRecurrence(recurrence)}` : "",
|
|
258676
|
+
scope ? ` Scope: ${formatScope(scope)}` : "",
|
|
258203
258677
|
tags.length > 0 ? ` Tags: ${tags.join(", ")}` : "",
|
|
258204
258678
|
context2 ? ` Context: ${context2.slice(0, 100)}` : "",
|
|
258205
258679
|
``,
|
|
258206
|
-
`This
|
|
258680
|
+
kind === "action" ? `This action will trigger when due${dueDescription ? ` (${dueDescription})` : ""}.` : `This reminder will surface when due${dueDescription ? ` (${dueDescription})` : ""}.`
|
|
258207
258681
|
].filter(Boolean).join("\n"),
|
|
258208
258682
|
durationMs: performance.now() - start2
|
|
258209
258683
|
};
|
|
@@ -258232,8 +258706,14 @@ var init_reminder = __esm({
|
|
|
258232
258706
|
const statusLabel = r2.status === "seen" ? " (seen)" : r2.status === "completed" ? " (done)" : r2.status === "dismissed" ? " (dismissed)" : "";
|
|
258233
258707
|
lines.push(` ${priorityIcon} [${r2.id}]${statusLabel}`);
|
|
258234
258708
|
lines.push(` ${r2.message}`);
|
|
258709
|
+
lines.push(` Kind: ${r2.delivery?.mode ?? "minimal"}`);
|
|
258235
258710
|
if (r2.dueDescription)
|
|
258236
258711
|
lines.push(` Due: ${r2.dueDescription}`);
|
|
258712
|
+
const recurrence = describeRecurrence(r2.recurrence);
|
|
258713
|
+
if (recurrence)
|
|
258714
|
+
lines.push(` Repeats: ${recurrence}`);
|
|
258715
|
+
if (r2.scope)
|
|
258716
|
+
lines.push(` Scope: ${formatScope(r2.scope)}`);
|
|
258237
258717
|
if (r2.tags.length > 0)
|
|
258238
258718
|
lines.push(` Tags: ${r2.tags.join(", ")}`);
|
|
258239
258719
|
if (r2.context)
|
|
@@ -258285,6 +258765,26 @@ var init_reminder = __esm({
|
|
|
258285
258765
|
durationMs: performance.now() - start2
|
|
258286
258766
|
};
|
|
258287
258767
|
}
|
|
258768
|
+
resolveScope(args) {
|
|
258769
|
+
if (this.options.lockScope)
|
|
258770
|
+
return this.options.defaultScope;
|
|
258771
|
+
const surface = normalizeSurface(args["surface"]) ?? this.options.defaultScope?.surface;
|
|
258772
|
+
const visibility = normalizeVisibility(args["visibility"]) ?? this.options.defaultScope?.visibility ?? "private";
|
|
258773
|
+
const targetId = String(args["target_id"] ?? args["targetId"] ?? this.options.defaultScope?.targetId ?? "").trim();
|
|
258774
|
+
if (!surface || !targetId)
|
|
258775
|
+
return this.options.defaultScope;
|
|
258776
|
+
return {
|
|
258777
|
+
surface,
|
|
258778
|
+
visibility,
|
|
258779
|
+
targetId,
|
|
258780
|
+
sessionId: stringValue(args["session_id"] ?? args["sessionId"] ?? this.options.defaultScope?.sessionId),
|
|
258781
|
+
chatId: stringValue(args["chat_id"] ?? args["chatId"] ?? this.options.defaultScope?.chatId),
|
|
258782
|
+
threadId: stringValue(args["thread_id"] ?? args["threadId"] ?? this.options.defaultScope?.threadId),
|
|
258783
|
+
userId: stringValue(args["user_id"] ?? args["userId"] ?? this.options.defaultScope?.userId),
|
|
258784
|
+
username: stringValue(args["username"] ?? this.options.defaultScope?.username),
|
|
258785
|
+
label: stringValue(args["label"] ?? this.options.defaultScope?.label)
|
|
258786
|
+
};
|
|
258787
|
+
}
|
|
258288
258788
|
};
|
|
258289
258789
|
}
|
|
258290
258790
|
});
|
|
@@ -258613,6 +259113,23 @@ ${sections.join("\n")}`,
|
|
|
258613
259113
|
}
|
|
258614
259114
|
});
|
|
258615
259115
|
|
|
259116
|
+
// packages/execution/dist/tools/tool-alias.js
|
|
259117
|
+
function aliasTool(tool, name10, description = `Alias for ${tool.name}: ${tool.description}`) {
|
|
259118
|
+
return {
|
|
259119
|
+
name: name10,
|
|
259120
|
+
description,
|
|
259121
|
+
parameters: tool.parameters,
|
|
259122
|
+
async execute(args) {
|
|
259123
|
+
return tool.execute(args);
|
|
259124
|
+
}
|
|
259125
|
+
};
|
|
259126
|
+
}
|
|
259127
|
+
var init_tool_alias = __esm({
|
|
259128
|
+
"packages/execution/dist/tools/tool-alias.js"() {
|
|
259129
|
+
"use strict";
|
|
259130
|
+
}
|
|
259131
|
+
});
|
|
259132
|
+
|
|
258616
259133
|
// packages/execution/dist/tools/opencode.js
|
|
258617
259134
|
import { execSync as execSync23, spawn as spawn14 } from "node:child_process";
|
|
258618
259135
|
import { existsSync as existsSync33 } from "node:fs";
|
|
@@ -259213,6 +259730,47 @@ function resolveSchedule2(schedule) {
|
|
|
259213
259730
|
if (LONG_HORIZON_PRESETS[lower]) {
|
|
259214
259731
|
return { cron: LONG_HORIZON_PRESETS[lower], description: lower };
|
|
259215
259732
|
}
|
|
259733
|
+
const dailyAt = lower.match(/^(?:daily|every\s+day)\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
259734
|
+
if (dailyAt) {
|
|
259735
|
+
const hour2 = parseInt(dailyAt[1], 10);
|
|
259736
|
+
const minute3 = parseInt(dailyAt[2], 10);
|
|
259737
|
+
if (isClockTime2(hour2, minute3))
|
|
259738
|
+
return { cron: `${minute3} ${hour2} * * *`, description: `daily at ${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}` };
|
|
259739
|
+
}
|
|
259740
|
+
const weeklyAt = lower.match(/^weekly(?:\s+on)?\s+([a-z]+|\d)\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
259741
|
+
if (weeklyAt) {
|
|
259742
|
+
const dow = parseWeekday3(weeklyAt[1]);
|
|
259743
|
+
const hour2 = parseInt(weeklyAt[2], 10);
|
|
259744
|
+
const minute3 = parseInt(weeklyAt[3], 10);
|
|
259745
|
+
if (dow !== null && isClockTime2(hour2, minute3))
|
|
259746
|
+
return { cron: `${minute3} ${hour2} * * ${dow}`, description: `weekly on day ${dow} at ${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}` };
|
|
259747
|
+
}
|
|
259748
|
+
const monthlyAt = lower.match(/^monthly(?:\s+(?:on|day))?\s+(\d{1,2})(?:st|nd|rd|th)?\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
259749
|
+
if (monthlyAt) {
|
|
259750
|
+
const day = parseInt(monthlyAt[1], 10);
|
|
259751
|
+
const hour2 = parseInt(monthlyAt[2], 10);
|
|
259752
|
+
const minute3 = parseInt(monthlyAt[3], 10);
|
|
259753
|
+
if (day >= 1 && day <= 31 && isClockTime2(hour2, minute3))
|
|
259754
|
+
return { cron: `${minute3} ${hour2} ${day} * *`, description: `monthly on day ${day} at ${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}` };
|
|
259755
|
+
}
|
|
259756
|
+
const yearlyNumeric = lower.match(/^(?:yearly|annually|every\s+year)\s+(?:on\s+)?(\d{1,2})-(\d{1,2})\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
259757
|
+
if (yearlyNumeric) {
|
|
259758
|
+
const month = parseInt(yearlyNumeric[1], 10);
|
|
259759
|
+
const day = parseInt(yearlyNumeric[2], 10);
|
|
259760
|
+
const hour2 = parseInt(yearlyNumeric[3], 10);
|
|
259761
|
+
const minute3 = parseInt(yearlyNumeric[4], 10);
|
|
259762
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && isClockTime2(hour2, minute3))
|
|
259763
|
+
return { cron: `${minute3} ${hour2} ${day} ${month} *`, description: `yearly on ${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")} at ${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}` };
|
|
259764
|
+
}
|
|
259765
|
+
const yearlyNamed = lower.match(/^(?:yearly|annually|every\s+year)\s+(?:on\s+)?([a-z]+)\s+(\d{1,2})(?:st|nd|rd|th)?\s+(?:at\s+)?(\d{1,2}):(\d{2})$/);
|
|
259766
|
+
if (yearlyNamed) {
|
|
259767
|
+
const month = parseMonth3(yearlyNamed[1]);
|
|
259768
|
+
const day = parseInt(yearlyNamed[2], 10);
|
|
259769
|
+
const hour2 = parseInt(yearlyNamed[3], 10);
|
|
259770
|
+
const minute3 = parseInt(yearlyNamed[4], 10);
|
|
259771
|
+
if (month !== null && day >= 1 && day <= 31 && isClockTime2(hour2, minute3))
|
|
259772
|
+
return { cron: `${minute3} ${hour2} ${day} ${month} *`, description: `yearly on ${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")} at ${String(hour2).padStart(2, "0")}:${String(minute3).padStart(2, "0")}` };
|
|
259773
|
+
}
|
|
259216
259774
|
const everyMatch = lower.match(/^every\s+(\d+)\s*(h|hr|hrs|hours?|d|days?|w|wk|wks|weeks?|m|mo|mos|months?)$/);
|
|
259217
259775
|
if (everyMatch) {
|
|
259218
259776
|
const amount = parseInt(everyMatch[1], 10);
|
|
@@ -259260,6 +259818,65 @@ function resolveSchedule2(schedule) {
|
|
|
259260
259818
|
}
|
|
259261
259819
|
return null;
|
|
259262
259820
|
}
|
|
259821
|
+
function isClockTime2(hour2, minute3) {
|
|
259822
|
+
return hour2 >= 0 && hour2 <= 23 && minute3 >= 0 && minute3 <= 59;
|
|
259823
|
+
}
|
|
259824
|
+
function parseWeekday3(raw) {
|
|
259825
|
+
const value2 = raw.toLowerCase();
|
|
259826
|
+
if (/^[0-6]$/.test(value2))
|
|
259827
|
+
return Number(value2);
|
|
259828
|
+
const days = {
|
|
259829
|
+
sunday: 0,
|
|
259830
|
+
sun: 0,
|
|
259831
|
+
monday: 1,
|
|
259832
|
+
mon: 1,
|
|
259833
|
+
tuesday: 2,
|
|
259834
|
+
tue: 2,
|
|
259835
|
+
tues: 2,
|
|
259836
|
+
wednesday: 3,
|
|
259837
|
+
wed: 3,
|
|
259838
|
+
thursday: 4,
|
|
259839
|
+
thu: 4,
|
|
259840
|
+
thurs: 4,
|
|
259841
|
+
friday: 5,
|
|
259842
|
+
fri: 5,
|
|
259843
|
+
saturday: 6,
|
|
259844
|
+
sat: 6
|
|
259845
|
+
};
|
|
259846
|
+
return days[value2] ?? null;
|
|
259847
|
+
}
|
|
259848
|
+
function parseMonth3(raw) {
|
|
259849
|
+
const value2 = raw.toLowerCase();
|
|
259850
|
+
if (/^(?:[1-9]|1[0-2])$/.test(value2))
|
|
259851
|
+
return Number(value2);
|
|
259852
|
+
const months = {
|
|
259853
|
+
january: 1,
|
|
259854
|
+
jan: 1,
|
|
259855
|
+
february: 2,
|
|
259856
|
+
feb: 2,
|
|
259857
|
+
march: 3,
|
|
259858
|
+
mar: 3,
|
|
259859
|
+
april: 4,
|
|
259860
|
+
apr: 4,
|
|
259861
|
+
may: 5,
|
|
259862
|
+
june: 6,
|
|
259863
|
+
jun: 6,
|
|
259864
|
+
july: 7,
|
|
259865
|
+
jul: 7,
|
|
259866
|
+
august: 8,
|
|
259867
|
+
aug: 8,
|
|
259868
|
+
september: 9,
|
|
259869
|
+
sep: 9,
|
|
259870
|
+
sept: 9,
|
|
259871
|
+
october: 10,
|
|
259872
|
+
oct: 10,
|
|
259873
|
+
november: 11,
|
|
259874
|
+
nov: 11,
|
|
259875
|
+
december: 12,
|
|
259876
|
+
dec: 12
|
|
259877
|
+
};
|
|
259878
|
+
return months[value2] ?? null;
|
|
259879
|
+
}
|
|
259263
259880
|
function getCurrentCrontab2() {
|
|
259264
259881
|
try {
|
|
259265
259882
|
return execSync25("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
|
|
@@ -259376,12 +259993,14 @@ var init_cron_agent = __esm({
|
|
|
259376
259993
|
"weekly": "0 9 * * 1",
|
|
259377
259994
|
"biweekly": "0 9 1,15 * *",
|
|
259378
259995
|
"monthly": "0 9 1 * *",
|
|
259379
|
-
"quarterly": "0 9 1 1,4,7,10 *"
|
|
259996
|
+
"quarterly": "0 9 1 1,4,7,10 *",
|
|
259997
|
+
"yearly": "0 9 1 1 *",
|
|
259998
|
+
"annually": "0 9 1 1 *"
|
|
259380
259999
|
};
|
|
259381
260000
|
CRON_AGENT_MARKER = "# Omnius-CRON-AGENT:";
|
|
259382
260001
|
CronAgentTool = class {
|
|
259383
260002
|
name = "cron_agent";
|
|
259384
|
-
description = "Schedule long-horizon autonomous agent tasks that execute on a cron schedule. Unlike one-shot scheduler tasks, cron_agent jobs have goals, completion criteria, and execution history tracking. Actions: 'create' a monitored cron job, 'list' all jobs, 'check' a job's status and history, 'cancel' a job, 'logs' view execution output, 'evaluate' check if goal is met. Schedules: 'every 2 hours', 'daily', 'weekly', 'monthly', '
|
|
260003
|
+
description = "Schedule long-horizon autonomous agent tasks that execute on a cron schedule. Unlike one-shot scheduler tasks, cron_agent jobs have goals, completion criteria, and execution history tracking. Actions: 'create' a monitored cron job, 'list' all jobs, 'check' a job's status and history, 'cancel' a job, 'logs' view execution output, 'evaluate' check if goal is met. Schedules: 'every 2 hours', 'daily at 14:30', 'weekly friday at 17:45', 'monthly', 'yearly', or raw cron. Use this for long-running autonomous workflows: periodic code reviews, test monitoring, dependency updates, performance tracking, log analysis, or any recurring agent task.";
|
|
259385
260004
|
parameters = {
|
|
259386
260005
|
type: "object",
|
|
259387
260006
|
properties: {
|
|
@@ -259400,7 +260019,7 @@ var init_cron_agent = __esm({
|
|
|
259400
260019
|
},
|
|
259401
260020
|
schedule: {
|
|
259402
260021
|
type: "string",
|
|
259403
|
-
description: "When to run: 'every 2 hours', 'daily', 'weekly', 'monthly', '
|
|
260022
|
+
description: "When to run: 'every 2 hours', 'daily at 14:30', 'weekly friday at 17:45', 'monthly', 'yearly', or cron expression"
|
|
259404
260023
|
},
|
|
259405
260024
|
completion_criteria: {
|
|
259406
260025
|
type: "string",
|
|
@@ -287360,9 +287979,9 @@ ${lanes.join("\n")}
|
|
|
287360
287979
|
function isJsonEqual(a2, b) {
|
|
287361
287980
|
return a2 === b || typeof a2 === "object" && a2 !== null && typeof b === "object" && b !== null && equalOwnProperties(a2, b, isJsonEqual);
|
|
287362
287981
|
}
|
|
287363
|
-
function parsePseudoBigInt(
|
|
287982
|
+
function parsePseudoBigInt(stringValue2) {
|
|
287364
287983
|
let log2Base;
|
|
287365
|
-
switch (
|
|
287984
|
+
switch (stringValue2.charCodeAt(1)) {
|
|
287366
287985
|
// "x" in "0x123"
|
|
287367
287986
|
case 98:
|
|
287368
287987
|
case 66:
|
|
@@ -287377,19 +287996,19 @@ ${lanes.join("\n")}
|
|
|
287377
287996
|
log2Base = 4;
|
|
287378
287997
|
break;
|
|
287379
287998
|
default:
|
|
287380
|
-
const nIndex =
|
|
287999
|
+
const nIndex = stringValue2.length - 1;
|
|
287381
288000
|
let nonZeroStart = 0;
|
|
287382
|
-
while (
|
|
288001
|
+
while (stringValue2.charCodeAt(nonZeroStart) === 48) {
|
|
287383
288002
|
nonZeroStart++;
|
|
287384
288003
|
}
|
|
287385
|
-
return
|
|
288004
|
+
return stringValue2.slice(nonZeroStart, nIndex) || "0";
|
|
287386
288005
|
}
|
|
287387
|
-
const startIndex = 2, endIndex =
|
|
288006
|
+
const startIndex = 2, endIndex = stringValue2.length - 1;
|
|
287388
288007
|
const bitsNeeded = (endIndex - startIndex) * log2Base;
|
|
287389
288008
|
const segments = new Uint16Array((bitsNeeded >>> 4) + (bitsNeeded & 15 ? 1 : 0));
|
|
287390
288009
|
for (let i2 = endIndex - 1, bitOffset = 0; i2 >= startIndex; i2--, bitOffset += log2Base) {
|
|
287391
288010
|
const segment = bitOffset >>> 4;
|
|
287392
|
-
const digitChar =
|
|
288011
|
+
const digitChar = stringValue2.charCodeAt(i2);
|
|
287393
288012
|
const digit = digitChar <= 57 ? digitChar - 48 : 10 + digitChar - (digitChar <= 70 ? 65 : 97);
|
|
287394
288013
|
const shiftedDigit = digit << (bitOffset & 15);
|
|
287395
288014
|
segments[segment] |= shiftedDigit;
|
|
@@ -515039,14 +515658,17 @@ function collectSnapshot(workingDir) {
|
|
|
515039
515658
|
}
|
|
515040
515659
|
} catch {
|
|
515041
515660
|
}
|
|
515042
|
-
let disk = { availableGB: 0, totalGB: 0, usedPercent: 0 };
|
|
515661
|
+
let disk = { path: workingDir || "/", availableGB: 0, usedGB: 0, totalGB: 0, usedPercent: 0 };
|
|
515043
515662
|
try {
|
|
515044
515663
|
const stats = statfsSync(workingDir || "/");
|
|
515045
515664
|
const totalBytes = stats.blocks * stats.bsize;
|
|
515046
515665
|
const availBytes = stats.bavail * stats.bsize;
|
|
515666
|
+
const usedBytes = totalBytes - availBytes;
|
|
515047
515667
|
disk = {
|
|
515668
|
+
path: workingDir || "/",
|
|
515048
515669
|
totalGB: Math.round(totalBytes / 1024 ** 3),
|
|
515049
515670
|
availableGB: Math.round(availBytes / 1024 ** 3),
|
|
515671
|
+
usedGB: Math.round(usedBytes / 1024 ** 3),
|
|
515050
515672
|
usedPercent: Math.round((1 - availBytes / totalBytes) * 100)
|
|
515051
515673
|
};
|
|
515052
515674
|
} catch {
|
|
@@ -515119,7 +515741,7 @@ function formatSnapshotForContext(snap) {
|
|
|
515119
515741
|
const icon = snap.battery.charging ? "⚡" : snap.battery.percent < 20 ? "🪫" : "🔋";
|
|
515120
515742
|
lines.push(`Battery: ${icon} ${snap.battery.percent}% ${snap.battery.charging ? "(charging)" : "(discharging)"}`);
|
|
515121
515743
|
}
|
|
515122
|
-
lines.push(`Disk:
|
|
515744
|
+
lines.push(`Disk: disk_available_gb=${snap.disk.availableGB} disk_used_gb=${snap.disk.usedGB} disk_total_gb=${snap.disk.totalGB} disk_used_pct=${snap.disk.usedPercent} path=${snap.disk.path}`);
|
|
515123
515745
|
lines.push(`Processes: ${snap.processes.total} total | ${snap.processes.nodeCount} node | ${snap.processes.omniusSpawned} Omnius-spawned`);
|
|
515124
515746
|
lines.push(`Uptime: ${snap.uptime}`);
|
|
515125
515747
|
if (snap.processes.topCpu.length > 0) {
|
|
@@ -516402,6 +517024,7 @@ __export(dist_exports, {
|
|
|
516402
517024
|
YouTubeDownloadTool: () => YouTubeDownloadTool,
|
|
516403
517025
|
addProjectConstraint: () => addProjectConstraint,
|
|
516404
517026
|
addSessionConstraint: () => addSessionConstraint,
|
|
517027
|
+
aliasTool: () => aliasTool,
|
|
516405
517028
|
applyPatch: () => applyPatch,
|
|
516406
517029
|
audioGenerationDir: () => audioGenerationDir,
|
|
516407
517030
|
audioGenerationSetupPlan: () => audioGenerationSetupPlan,
|
|
@@ -516493,6 +517116,7 @@ __export(dist_exports, {
|
|
|
516493
517116
|
loadSkillContent: () => loadSkillContent,
|
|
516494
517117
|
logsDir: () => logsDir,
|
|
516495
517118
|
markRemindersSeen: () => markRemindersSeen,
|
|
517119
|
+
markRemindersTriggered: () => markRemindersTriggered,
|
|
516496
517120
|
markReverted: () => markReverted,
|
|
516497
517121
|
markSessionValidated: () => markSessionValidated,
|
|
516498
517122
|
normalizeMcpName: () => normalizeMcpName,
|
|
@@ -516612,6 +517236,7 @@ var init_dist5 = __esm({
|
|
|
516612
517236
|
init_scheduler();
|
|
516613
517237
|
init_reminder();
|
|
516614
517238
|
init_agenda();
|
|
517239
|
+
init_tool_alias();
|
|
516615
517240
|
init_opencode();
|
|
516616
517241
|
init_factory();
|
|
516617
517242
|
init_cron_agent();
|
|
@@ -518049,9 +518674,9 @@ var init_verifierRunner = __esm({
|
|
|
518049
518674
|
async executeTests(patch, repoRoot) {
|
|
518050
518675
|
if (patch.testsToRun.length === 0)
|
|
518051
518676
|
return "(no tests specified)";
|
|
518052
|
-
const { execFile:
|
|
518053
|
-
const { promisify:
|
|
518054
|
-
const
|
|
518677
|
+
const { execFile: execFile7 } = await import("node:child_process");
|
|
518678
|
+
const { promisify: promisify7 } = await import("node:util");
|
|
518679
|
+
const execFileAsync5 = promisify7(execFile7);
|
|
518055
518680
|
const outputs = [];
|
|
518056
518681
|
const workDir = this.options.workingDir || repoRoot;
|
|
518057
518682
|
for (const cmd of patch.testsToRun.slice(0, 3)) {
|
|
@@ -518060,7 +518685,7 @@ var init_verifierRunner = __esm({
|
|
|
518060
518685
|
const [bin, ...args] = parts;
|
|
518061
518686
|
if (!bin)
|
|
518062
518687
|
continue;
|
|
518063
|
-
const { stdout, stderr } = await
|
|
518688
|
+
const { stdout, stderr } = await execFileAsync5(bin, args, {
|
|
518064
518689
|
cwd: workDir,
|
|
518065
518690
|
timeout: 6e4,
|
|
518066
518691
|
maxBuffer: 1024 * 1024
|
|
@@ -553801,9 +554426,14 @@ var init_command_registry = __esm({
|
|
|
553801
554426
|
["/access <loopback|lan|any>", "Set access policy (OMNIUS_ACCESS) and restart daemon"],
|
|
553802
554427
|
["/k <any|lan|loopback|config>", "Quick network access helper"],
|
|
553803
554428
|
["/scheduler", "Scheduled tasks control panel (list/kill/toggle)"],
|
|
554429
|
+
["/cron", "Alias for /scheduler"],
|
|
553804
554430
|
["/scheduler menu", "Interactive scheduler menu (toggle/kill)"],
|
|
553805
554431
|
["/scheduler list", "List all scheduled tasks and timers"],
|
|
553806
554432
|
["/scheduler kill", "Kill schedulers + active runs (with escalation if needed)"],
|
|
554433
|
+
["/reminder [list|all]", "List scoped TUI reminders"],
|
|
554434
|
+
["/remind <message>", "Set a scoped minimal reminder for this TUI session"],
|
|
554435
|
+
["/remind in 30m <message>", "Set a scoped minimal reminder with a relative due time"],
|
|
554436
|
+
["/reminders", "Alias for /reminder"],
|
|
553807
554437
|
["/daemon", "Show or manage the local API daemon"],
|
|
553808
554438
|
["/daemon <start|stop|restart|takeover>", "Control the local API daemon"],
|
|
553809
554439
|
["/apikey", "Show current API key (for pasting into Web UI / clients)"],
|
|
@@ -553858,7 +554488,6 @@ var init_command_registry = __esm({
|
|
|
553858
554488
|
["/skin", "Configure the visual skin/theme bundle"],
|
|
553859
554489
|
["/toolsets", "Show or select tool exposure sets"],
|
|
553860
554490
|
["/browser connect|disconnect|status", "Manage browser-agent connectivity"],
|
|
553861
|
-
["/cron", "Scheduled/cron agent controls"],
|
|
553862
554491
|
["/reload-mcp", "Reload MCP servers and tools"],
|
|
553863
554492
|
["/plugins", "List or manage plugins"],
|
|
553864
554493
|
["/usage", "Show usage and quota details"],
|
|
@@ -553929,6 +554558,7 @@ var init_command_registry = __esm({
|
|
|
553929
554558
|
network: "network",
|
|
553930
554559
|
k: "network",
|
|
553931
554560
|
scheduler: "runtime",
|
|
554561
|
+
reminder: "runtime",
|
|
553932
554562
|
daemon: "runtime",
|
|
553933
554563
|
apikey: "secret",
|
|
553934
554564
|
key: "secret",
|
|
@@ -553995,6 +554625,8 @@ var init_command_registry = __esm({
|
|
|
553995
554625
|
emojis: ["emoji"],
|
|
553996
554626
|
compact: ["gc"],
|
|
553997
554627
|
network: ["k"],
|
|
554628
|
+
scheduler: ["cron"],
|
|
554629
|
+
reminder: ["remind", "reminders"],
|
|
553998
554630
|
statusbar: ["sb"],
|
|
553999
554631
|
platforms: ["gateway"]
|
|
554000
554632
|
};
|
|
@@ -554053,6 +554685,7 @@ var init_command_registry = __esm({
|
|
|
554053
554685
|
"network",
|
|
554054
554686
|
"k",
|
|
554055
554687
|
"scheduler",
|
|
554688
|
+
"cron",
|
|
554056
554689
|
"daemon",
|
|
554057
554690
|
"fortemi",
|
|
554058
554691
|
"mouse",
|
|
@@ -556518,7 +557151,7 @@ import { EventEmitter as EventEmitter6 } from "node:events";
|
|
|
556518
557151
|
import { randomBytes as randomBytes18 } from "node:crypto";
|
|
556519
557152
|
import { URL as URL2 } from "node:url";
|
|
556520
557153
|
import { loadavg, cpus as cpus2, totalmem as totalmem3, freemem as freemem3 } from "node:os";
|
|
556521
|
-
import { existsSync as existsSync80, readFileSync as readFileSync63, writeFileSync as writeFileSync42, unlinkSync as unlinkSync13, mkdirSync as mkdirSync45, readdirSync as readdirSync25, statSync as statSync28 } from "node:fs";
|
|
557154
|
+
import { existsSync as existsSync80, readFileSync as readFileSync63, writeFileSync as writeFileSync42, unlinkSync as unlinkSync13, mkdirSync as mkdirSync45, readdirSync as readdirSync25, statSync as statSync28, statfsSync as statfsSync2 } from "node:fs";
|
|
556522
557155
|
import { join as join96 } from "node:path";
|
|
556523
557156
|
function cleanForwardHeaders(raw, targetHost) {
|
|
556524
557157
|
const out = {};
|
|
@@ -556608,6 +557241,27 @@ async function collectSystemMetricsAsync() {
|
|
|
556608
557241
|
const totalMem = totalmem3();
|
|
556609
557242
|
const freeMem = freemem3();
|
|
556610
557243
|
const usedMem = totalMem - freeMem;
|
|
557244
|
+
let disk = {
|
|
557245
|
+
path: process.cwd(),
|
|
557246
|
+
totalGB: 0,
|
|
557247
|
+
freeGB: 0,
|
|
557248
|
+
usedGB: 0,
|
|
557249
|
+
utilization: -1
|
|
557250
|
+
};
|
|
557251
|
+
try {
|
|
557252
|
+
const fs10 = statfsSync2(process.cwd());
|
|
557253
|
+
const totalBytes = fs10.blocks * fs10.bsize;
|
|
557254
|
+
const freeBytes = fs10.bavail * fs10.bsize;
|
|
557255
|
+
const usedBytes = totalBytes - freeBytes;
|
|
557256
|
+
disk = {
|
|
557257
|
+
path: process.cwd(),
|
|
557258
|
+
totalGB: Math.round(totalBytes / 1024 ** 3 * 10) / 10,
|
|
557259
|
+
freeGB: Math.round(freeBytes / 1024 ** 3 * 10) / 10,
|
|
557260
|
+
usedGB: Math.round(usedBytes / 1024 ** 3 * 10) / 10,
|
|
557261
|
+
utilization: totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : -1
|
|
557262
|
+
};
|
|
557263
|
+
} catch {
|
|
557264
|
+
}
|
|
556611
557265
|
const gpu = {
|
|
556612
557266
|
available: false,
|
|
556613
557267
|
name: "",
|
|
@@ -556650,6 +557304,7 @@ async function collectSystemMetricsAsync() {
|
|
|
556650
557304
|
usedGB: Math.round(usedMem / 1024 ** 3 * 10) / 10,
|
|
556651
557305
|
utilization: Math.round(usedMem / totalMem * 100)
|
|
556652
557306
|
},
|
|
557307
|
+
disk,
|
|
556653
557308
|
gpu,
|
|
556654
557309
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
556655
557310
|
};
|
|
@@ -561458,6 +562113,60 @@ var init_braille_spinner = __esm({
|
|
|
561458
562113
|
}
|
|
561459
562114
|
});
|
|
561460
562115
|
|
|
562116
|
+
// packages/cli/src/tui/disk-monitor.ts
|
|
562117
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
562118
|
+
import { promisify as promisify5 } from "node:util";
|
|
562119
|
+
function unavailableDiskMetrics(path11 = process.cwd()) {
|
|
562120
|
+
return {
|
|
562121
|
+
path: path11,
|
|
562122
|
+
mount: "",
|
|
562123
|
+
totalGB: 0,
|
|
562124
|
+
usedGB: 0,
|
|
562125
|
+
freeGB: 0,
|
|
562126
|
+
util: -1
|
|
562127
|
+
};
|
|
562128
|
+
}
|
|
562129
|
+
async function collectDiskMetrics(path11 = process.cwd()) {
|
|
562130
|
+
if (process.platform === "win32") return unavailableDiskMetrics(path11);
|
|
562131
|
+
try {
|
|
562132
|
+
const { stdout } = await execFileAsync4("df", ["-Pk", path11], {
|
|
562133
|
+
encoding: "utf8",
|
|
562134
|
+
timeout: 3e3,
|
|
562135
|
+
maxBuffer: 128 * 1024
|
|
562136
|
+
});
|
|
562137
|
+
const lines = stdout.trim().split("\n").filter(Boolean);
|
|
562138
|
+
const line = lines[lines.length - 1];
|
|
562139
|
+
if (!line) return unavailableDiskMetrics(path11);
|
|
562140
|
+
const parts = line.trim().split(/\s+/);
|
|
562141
|
+
if (parts.length < 6) return unavailableDiskMetrics(path11);
|
|
562142
|
+
const totalKB = Number(parts[1] ?? 0);
|
|
562143
|
+
const usedKB = Number(parts[2] ?? 0);
|
|
562144
|
+
const freeKB = Number(parts[3] ?? 0);
|
|
562145
|
+
if (!Number.isFinite(totalKB) || totalKB <= 0) return unavailableDiskMetrics(path11);
|
|
562146
|
+
const totalGB = totalKB / (1024 * 1024);
|
|
562147
|
+
const usedGB = usedKB / (1024 * 1024);
|
|
562148
|
+
const freeGB = freeKB / (1024 * 1024);
|
|
562149
|
+
const util2 = Math.max(0, Math.min(100, Math.round(usedKB / totalKB * 100)));
|
|
562150
|
+
return {
|
|
562151
|
+
path: path11,
|
|
562152
|
+
mount: parts.slice(5).join(" "),
|
|
562153
|
+
totalGB: Math.round(totalGB * 10) / 10,
|
|
562154
|
+
usedGB: Math.round(usedGB * 10) / 10,
|
|
562155
|
+
freeGB: Math.round(freeGB * 10) / 10,
|
|
562156
|
+
util: util2
|
|
562157
|
+
};
|
|
562158
|
+
} catch {
|
|
562159
|
+
return unavailableDiskMetrics(path11);
|
|
562160
|
+
}
|
|
562161
|
+
}
|
|
562162
|
+
var execFileAsync4;
|
|
562163
|
+
var init_disk_monitor = __esm({
|
|
562164
|
+
"packages/cli/src/tui/disk-monitor.ts"() {
|
|
562165
|
+
"use strict";
|
|
562166
|
+
execFileAsync4 = promisify5(execFile5);
|
|
562167
|
+
}
|
|
562168
|
+
});
|
|
562169
|
+
|
|
561461
562170
|
// packages/cli/src/tui/system-metrics.ts
|
|
561462
562171
|
var system_metrics_exports = {};
|
|
561463
562172
|
__export(system_metrics_exports, {
|
|
@@ -561575,6 +562284,7 @@ async function collectGpuMetrics() {
|
|
|
561575
562284
|
}
|
|
561576
562285
|
function getInstantSnapshot() {
|
|
561577
562286
|
const cr = collectCpuRam();
|
|
562287
|
+
const disk = unavailableDiskMetrics();
|
|
561578
562288
|
return {
|
|
561579
562289
|
source: "local",
|
|
561580
562290
|
hardware: {
|
|
@@ -561588,7 +562298,12 @@ function getInstantSnapshot() {
|
|
|
561588
562298
|
vramTotalMB: 0,
|
|
561589
562299
|
memUtil: cr.memUtil,
|
|
561590
562300
|
memUsedGB: cr.memUsedGB,
|
|
561591
|
-
memTotalGB: cr.memTotalGB
|
|
562301
|
+
memTotalGB: cr.memTotalGB,
|
|
562302
|
+
diskUtil: disk.util,
|
|
562303
|
+
diskUsedGB: disk.usedGB,
|
|
562304
|
+
diskTotalGB: disk.totalGB,
|
|
562305
|
+
diskFreeGB: disk.freeGB,
|
|
562306
|
+
diskPath: disk.path
|
|
561592
562307
|
},
|
|
561593
562308
|
network: { rxBytesPerSec: 0, txBytesPerSec: 0 }
|
|
561594
562309
|
};
|
|
@@ -561635,8 +562350,9 @@ function collectCpuRam() {
|
|
|
561635
562350
|
}
|
|
561636
562351
|
async function collectLocalMetrics() {
|
|
561637
562352
|
const cpuRam = collectCpuRam();
|
|
561638
|
-
const [gpu, network] = await Promise.all([
|
|
562353
|
+
const [gpu, disk, network] = await Promise.all([
|
|
561639
562354
|
collectGpuMetrics(),
|
|
562355
|
+
collectDiskMetrics(),
|
|
561640
562356
|
collectNetworkMetrics()
|
|
561641
562357
|
]);
|
|
561642
562358
|
return {
|
|
@@ -561652,7 +562368,12 @@ async function collectLocalMetrics() {
|
|
|
561652
562368
|
vramTotalMB: gpu.vramTotalMB,
|
|
561653
562369
|
memUtil: cpuRam.memUtil,
|
|
561654
562370
|
memUsedGB: cpuRam.memUsedGB,
|
|
561655
|
-
memTotalGB: cpuRam.memTotalGB
|
|
562371
|
+
memTotalGB: cpuRam.memTotalGB,
|
|
562372
|
+
diskUtil: disk.util,
|
|
562373
|
+
diskUsedGB: disk.usedGB,
|
|
562374
|
+
diskTotalGB: disk.totalGB,
|
|
562375
|
+
diskFreeGB: disk.freeGB,
|
|
562376
|
+
diskPath: disk.path
|
|
561656
562377
|
},
|
|
561657
562378
|
network
|
|
561658
562379
|
};
|
|
@@ -561661,6 +562382,7 @@ var _lastNetSnapshot, _nvidiaSmiAvailable, _cpuPrevSnapshot, SystemMetricsCollec
|
|
|
561661
562382
|
var init_system_metrics = __esm({
|
|
561662
562383
|
"packages/cli/src/tui/system-metrics.ts"() {
|
|
561663
562384
|
"use strict";
|
|
562385
|
+
init_disk_monitor();
|
|
561664
562386
|
_lastNetSnapshot = null;
|
|
561665
562387
|
_nvidiaSmiAvailable = null;
|
|
561666
562388
|
_cpuPrevSnapshot = null;
|
|
@@ -561721,7 +562443,12 @@ var init_system_metrics = __esm({
|
|
|
561721
562443
|
vramTotalMB: hw.vramTotalMB ?? 0,
|
|
561722
562444
|
memUtil: hw.memUtil ?? -1,
|
|
561723
562445
|
memUsedGB: hw.memUsedGB ?? 0,
|
|
561724
|
-
memTotalGB: hw.memTotalGB ?? 0
|
|
562446
|
+
memTotalGB: hw.memTotalGB ?? 0,
|
|
562447
|
+
diskUtil: hw.diskUtil ?? -1,
|
|
562448
|
+
diskUsedGB: hw.diskUsedGB ?? 0,
|
|
562449
|
+
diskTotalGB: hw.diskTotalGB ?? 0,
|
|
562450
|
+
diskFreeGB: hw.diskFreeGB ?? 0,
|
|
562451
|
+
diskPath: hw.diskPath ?? ""
|
|
561725
562452
|
};
|
|
561726
562453
|
this._latest = {
|
|
561727
562454
|
source: "remote",
|
|
@@ -563781,7 +564508,12 @@ var init_status_bar = __esm({
|
|
|
563781
564508
|
vramTotalMB: metrics2.vramTotalMB ?? 0,
|
|
563782
564509
|
memUtil: metrics2.memUtil,
|
|
563783
564510
|
memTotalGB: metrics2.memTotalGB ?? 0,
|
|
563784
|
-
memUsedGB: metrics2.memUsedGB ?? 0
|
|
564511
|
+
memUsedGB: metrics2.memUsedGB ?? 0,
|
|
564512
|
+
diskUtil: metrics2.diskUtil ?? -1,
|
|
564513
|
+
diskUsedGB: metrics2.diskUsedGB ?? 0,
|
|
564514
|
+
diskTotalGB: metrics2.diskTotalGB ?? 0,
|
|
564515
|
+
diskFreeGB: metrics2.diskFreeGB ?? 0,
|
|
564516
|
+
diskPath: metrics2.diskPath ?? ""
|
|
563785
564517
|
});
|
|
563786
564518
|
}
|
|
563787
564519
|
/** Clear remote metrics and switch back to local collection */
|
|
@@ -563839,7 +564571,12 @@ var init_status_bar = __esm({
|
|
|
563839
564571
|
gpuUtil: data.gpu?.available ? data.gpu.utilization ?? 0 : -1,
|
|
563840
564572
|
gpuName: data.gpu?.name ?? "",
|
|
563841
564573
|
vramUtil: data.gpu?.available ? data.gpu.vramUtilization ?? 0 : -1,
|
|
563842
|
-
memUtil: data.memory?.utilization ?? 0
|
|
564574
|
+
memUtil: data.memory?.utilization ?? 0,
|
|
564575
|
+
diskUtil: data.disk?.utilization ?? -1,
|
|
564576
|
+
diskUsedGB: data.disk?.usedGB ?? 0,
|
|
564577
|
+
diskTotalGB: data.disk?.totalGB ?? 0,
|
|
564578
|
+
diskFreeGB: data.disk?.freeGB ?? 0,
|
|
564579
|
+
diskPath: data.disk?.path ?? ""
|
|
563843
564580
|
});
|
|
563844
564581
|
}
|
|
563845
564582
|
} catch {
|
|
@@ -563938,7 +564675,12 @@ var init_status_bar = __esm({
|
|
|
563938
564675
|
vramTotalMB: m2.gpu?.vramTotalMB ?? 0,
|
|
563939
564676
|
memUtil: m2.memory?.utilization ?? 0,
|
|
563940
564677
|
memTotalGB: m2.memory?.totalGB ?? 0,
|
|
563941
|
-
memUsedGB: m2.memory?.usedGB ?? 0
|
|
564678
|
+
memUsedGB: m2.memory?.usedGB ?? 0,
|
|
564679
|
+
diskUtil: m2.disk?.utilization ?? -1,
|
|
564680
|
+
diskTotalGB: m2.disk?.totalGB ?? 0,
|
|
564681
|
+
diskUsedGB: m2.disk?.usedGB ?? 0,
|
|
564682
|
+
diskFreeGB: m2.disk?.freeGB ?? 0,
|
|
564683
|
+
diskPath: m2.disk?.path ?? ""
|
|
563942
564684
|
});
|
|
563943
564685
|
return;
|
|
563944
564686
|
}
|
|
@@ -565407,6 +566149,14 @@ ${CONTENT_BG_SEQ}`);
|
|
|
565407
566149
|
hwExpW += 5 + `${rm3.memUtil}%`.length + memDetail.length;
|
|
565408
566150
|
hwCompW += 5 + `${rm3.memUtil}%`.length;
|
|
565409
566151
|
}
|
|
566152
|
+
if (rm3.diskUtil >= 0) {
|
|
566153
|
+
const diskColor = rm3.diskUtil > 90 ? c3.red : rm3.diskUtil > 75 ? c3.yellow : c3.green;
|
|
566154
|
+
const diskDetail = rm3.diskTotalGB > 0 ? ` (${rm3.diskFreeGB.toFixed(rm3.diskFreeGB < 10 ? 1 : 0)}GB free)` : "";
|
|
566155
|
+
hwExpStr += ` Disk ${diskColor(rm3.diskUtil + "%")}${c3.dim(diskDetail)}`;
|
|
566156
|
+
hwCompStr += ` Disk ${diskColor(rm3.diskUtil + "%")}`;
|
|
566157
|
+
hwExpW += 6 + `${rm3.diskUtil}%`.length + diskDetail.length;
|
|
566158
|
+
hwCompW += 6 + `${rm3.diskUtil}%`.length;
|
|
566159
|
+
}
|
|
565410
566160
|
if (rm3.gpuUtil >= 0) {
|
|
565411
566161
|
const gpuColor = rm3.gpuUtil > 80 ? c3.red : rm3.gpuUtil > 50 ? c3.yellow : c3.green;
|
|
565412
566162
|
const gpuNameShort = rm3.gpuName ? ` (${rm3.gpuName.slice(0, 20)})` : "";
|
|
@@ -567849,7 +568599,7 @@ __export(setup_exports, {
|
|
|
567849
568599
|
});
|
|
567850
568600
|
import * as readline from "node:readline";
|
|
567851
568601
|
import { execSync as execSync50, spawn as spawn25, exec as exec4 } from "node:child_process";
|
|
567852
|
-
import { promisify as
|
|
568602
|
+
import { promisify as promisify6 } from "node:util";
|
|
567853
568603
|
import { existsSync as existsSync86, writeFileSync as writeFileSync46, readFileSync as readFileSync70, appendFileSync as appendFileSync4, mkdirSync as mkdirSync49 } from "node:fs";
|
|
567854
568604
|
import { join as join103 } from "node:path";
|
|
567855
568605
|
import { homedir as homedir30, platform as platform4 } from "node:os";
|
|
@@ -570231,7 +570981,7 @@ var init_setup = __esm({
|
|
|
570231
570981
|
init_config();
|
|
570232
570982
|
init_dist();
|
|
570233
570983
|
init_tui_select();
|
|
570234
|
-
execAsync2 =
|
|
570984
|
+
execAsync2 = promisify6(exec4);
|
|
570235
570985
|
OMNIUS_FIRST_RUN_BANNER = [
|
|
570236
570986
|
" ░▒▓██████▓▒░░▒▓██████████████▓▒░░▒▓███████▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓███████▓▒░ ",
|
|
570237
570987
|
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
|
|
@@ -579756,6 +580506,7 @@ import {
|
|
|
579756
580506
|
writeFileSync as writeFileSync50,
|
|
579757
580507
|
mkdirSync as mkdirSync53,
|
|
579758
580508
|
readdirSync as readdirSync30,
|
|
580509
|
+
lstatSync,
|
|
579759
580510
|
statSync as statSync34,
|
|
579760
580511
|
rmSync as rmSync3,
|
|
579761
580512
|
appendFileSync as appendFileSync5
|
|
@@ -579868,6 +580619,69 @@ function safeLog(text) {
|
|
|
579868
580619
|
process.stdout.write(text + "\n");
|
|
579869
580620
|
}
|
|
579870
580621
|
}
|
|
580622
|
+
function createSlashReminderTool(ctx3) {
|
|
580623
|
+
const sessionId = process.env["OMNIUS_SESSION_ID"] || "terminal";
|
|
580624
|
+
return new ReminderTool(ctx3.repoRoot, {
|
|
580625
|
+
defaultScope: {
|
|
580626
|
+
surface: "tui",
|
|
580627
|
+
visibility: "private",
|
|
580628
|
+
targetId: sessionId,
|
|
580629
|
+
sessionId,
|
|
580630
|
+
label: "terminal"
|
|
580631
|
+
},
|
|
580632
|
+
lockScope: true,
|
|
580633
|
+
allowActionDelivery: false,
|
|
580634
|
+
source: "user",
|
|
580635
|
+
createdFrom: "tui-slash"
|
|
580636
|
+
});
|
|
580637
|
+
}
|
|
580638
|
+
function splitReminderDue(raw) {
|
|
580639
|
+
const text = raw.trim().replace(/^set\s+/i, "").trim();
|
|
580640
|
+
const dueMatch = text.match(
|
|
580641
|
+
/^((?:in\s+\d+\s*(?:m|min|mins|minutes?|h|hr|hrs|hours?|d|days?|w|weeks?))|tomorrow|next week|next startup|startup|now|(?:today\s+)?at\s+\d{1,2}:\d{2})\s+(.+)$/i
|
|
580642
|
+
);
|
|
580643
|
+
if (!dueMatch) return { message: text };
|
|
580644
|
+
return { due: dueMatch[1].trim(), message: dueMatch[2].trim() };
|
|
580645
|
+
}
|
|
580646
|
+
async function handleReminderSlash(cmd, arg, ctx3) {
|
|
580647
|
+
const tool = createSlashReminderTool(ctx3);
|
|
580648
|
+
const trimmed = arg.trim();
|
|
580649
|
+
const lower = trimmed.toLowerCase();
|
|
580650
|
+
let args;
|
|
580651
|
+
if (!trimmed || lower === "list" || lower === "pending" || lower === "all" || lower === "seen") {
|
|
580652
|
+
args = { action: "list", filter: lower === "all" || lower === "seen" ? lower : "pending" };
|
|
580653
|
+
} else if (lower === "completed" || lower === "dismissed") {
|
|
580654
|
+
args = { action: "list", filter: lower };
|
|
580655
|
+
} else if (lower.startsWith("complete ")) {
|
|
580656
|
+
args = { action: "complete", id: trimmed.slice("complete ".length).trim() };
|
|
580657
|
+
} else if (lower.startsWith("dismiss ")) {
|
|
580658
|
+
args = { action: "dismiss", id: trimmed.slice("dismiss ".length).trim() };
|
|
580659
|
+
} else if (lower.startsWith("snooze ")) {
|
|
580660
|
+
const rest = trimmed.slice("snooze ".length).trim();
|
|
580661
|
+
const [id, ...dueParts] = rest.split(/\s+/);
|
|
580662
|
+
args = { action: "snooze", id, due: dueParts.join(" ").trim() || "in 1h" };
|
|
580663
|
+
} else {
|
|
580664
|
+
const { due, message: message2 } = splitReminderDue(trimmed);
|
|
580665
|
+
if (!message2) {
|
|
580666
|
+
renderInfo("Usage: /remind [in 30m|tomorrow|at 14:30] <message>");
|
|
580667
|
+
return "handled";
|
|
580668
|
+
}
|
|
580669
|
+
args = {
|
|
580670
|
+
action: "set",
|
|
580671
|
+
kind: "minimal",
|
|
580672
|
+
message: message2,
|
|
580673
|
+
content: message2,
|
|
580674
|
+
...due ? { due } : {}
|
|
580675
|
+
};
|
|
580676
|
+
}
|
|
580677
|
+
const result = await tool.execute(args);
|
|
580678
|
+
if (!result.success) {
|
|
580679
|
+
renderError(result.error || `/${cmd} failed`);
|
|
580680
|
+
} else if (result.output) {
|
|
580681
|
+
safeLog(result.output);
|
|
580682
|
+
}
|
|
580683
|
+
return "handled";
|
|
580684
|
+
}
|
|
579871
580685
|
function parseTelegramChatTarget(value2) {
|
|
579872
580686
|
if (!value2) return null;
|
|
579873
580687
|
if (/^-?\d+$/.test(value2)) return Number(value2);
|
|
@@ -580244,6 +581058,10 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
580244
581058
|
case "?":
|
|
580245
581059
|
await showHelpMenu(ctx3);
|
|
580246
581060
|
return "handled";
|
|
581061
|
+
case "reminder":
|
|
581062
|
+
case "remind":
|
|
581063
|
+
case "reminders":
|
|
581064
|
+
return handleReminderSlash(cmd, arg, ctx3);
|
|
580247
581065
|
case "queue": {
|
|
580248
581066
|
if (!arg) {
|
|
580249
581067
|
const count2 = ctx3.queuedPromptCount?.() ?? 0;
|
|
@@ -583052,7 +583870,8 @@ sleep 1
|
|
|
583052
583870
|
}
|
|
583053
583871
|
return "handled";
|
|
583054
583872
|
}
|
|
583055
|
-
case "scheduler":
|
|
583873
|
+
case "scheduler":
|
|
583874
|
+
case "cron": {
|
|
583056
583875
|
const tokens = (arg || "").trim().length ? (arg || "").trim().split(/\s+/) : [];
|
|
583057
583876
|
const sub = (tokens[0] || "menu").toLowerCase();
|
|
583058
583877
|
const base3 = `http://127.0.0.1:${process.env["OMNIUS_PORT"] || "11435"}`;
|
|
@@ -586370,8 +587189,9 @@ function renderImagePresetDetail(prefix, text) {
|
|
|
586370
587189
|
renderInfo(`${prefix}${first2}`);
|
|
586371
587190
|
for (const line of rest) renderInfo(`${" ".repeat(prefix.length)}${line}`);
|
|
586372
587191
|
}
|
|
586373
|
-
function renderImageModelList() {
|
|
587192
|
+
async function renderImageModelList(ctx3) {
|
|
586374
587193
|
const specs = detectSystemSpecs();
|
|
587194
|
+
const ollamaSizes = ctx3 ? await fetchOllamaModelSizes(ctx3).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
|
|
586375
587195
|
const hardware = `${specs.totalRamGB.toFixed(0)}GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)}GB VRAM (${specs.gpuName || "NVIDIA GPU"})` : " + no NVIDIA VRAM detected");
|
|
586376
587196
|
renderInfo(`Image models for this hardware: ${hardware}`);
|
|
586377
587197
|
renderInfo("Fit legend: 85+ excellent, 60+ comfortable, 40+ offload/quantized, below 40 heavy/cloud.");
|
|
@@ -586389,7 +587209,9 @@ function renderImageModelList() {
|
|
|
586389
587209
|
for (const preset of presets) {
|
|
586390
587210
|
const fit2 = rateImagePresetForHardware(preset, specs);
|
|
586391
587211
|
const primary = category === "Primary hyper-realistic baseline" ? c3.cyan(" ★") : "";
|
|
586392
|
-
|
|
587212
|
+
const disk = ctx3 ? imageModelDiskStats(ctx3, preset, ollamaSizes) : { downloaded: false, bytes: 0, paths: [] };
|
|
587213
|
+
const diskInfo = disk.downloaded ? ` ${c3.green("✓")} ${formatFileSize(disk.bytes)}` : "";
|
|
587214
|
+
renderInfo(`${imageFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${c3.bold(preset.label)}${primary}${diskInfo}`);
|
|
586393
587215
|
renderInfo(` id: ${preset.id}`);
|
|
586394
587216
|
renderInfo(` type: ${preset.backend} · ${preset.sizeClass ?? "unknown size"} · ${fit2.label}`);
|
|
586395
587217
|
renderImagePresetDetail(" quality: ", preset.quality ?? preset.note);
|
|
@@ -586412,6 +587234,32 @@ function cacheCandidatePaths(root, model) {
|
|
|
586412
587234
|
join110(root, "cache", "huggingface", "hub", slug)
|
|
586413
587235
|
];
|
|
586414
587236
|
}
|
|
587237
|
+
function directorySizeBytes2(path11, seen = /* @__PURE__ */ new Set()) {
|
|
587238
|
+
try {
|
|
587239
|
+
const stat5 = lstatSync(path11);
|
|
587240
|
+
if (stat5.isSymbolicLink()) return 0;
|
|
587241
|
+
if (stat5.isFile()) return stat5.size;
|
|
587242
|
+
if (!stat5.isDirectory()) return 0;
|
|
587243
|
+
const realKey = `${stat5.dev}:${stat5.ino}`;
|
|
587244
|
+
if (seen.has(realKey)) return 0;
|
|
587245
|
+
seen.add(realKey);
|
|
587246
|
+
let total = 0;
|
|
587247
|
+
for (const entry of readdirSync30(path11)) {
|
|
587248
|
+
total += directorySizeBytes2(join110(path11, entry), seen);
|
|
587249
|
+
}
|
|
587250
|
+
return total;
|
|
587251
|
+
} catch {
|
|
587252
|
+
return 0;
|
|
587253
|
+
}
|
|
587254
|
+
}
|
|
587255
|
+
function cachedModelDiskStats(root, model) {
|
|
587256
|
+
const paths = cacheCandidatePaths(root, model).filter((path11) => existsSync96(path11));
|
|
587257
|
+
const bytes = paths.reduce((sum, path11) => sum + directorySizeBytes2(path11), 0);
|
|
587258
|
+
return { downloaded: paths.length > 0, bytes, paths };
|
|
587259
|
+
}
|
|
587260
|
+
function downloadedModelSuffix(stats) {
|
|
587261
|
+
return stats.downloaded ? ` · downloaded ${formatFileSize(stats.bytes)}` : "";
|
|
587262
|
+
}
|
|
586415
587263
|
function removeCachedModelPaths(root, model) {
|
|
586416
587264
|
const removed = [];
|
|
586417
587265
|
for (const path11 of cacheCandidatePaths(root, model)) {
|
|
@@ -586424,6 +587272,37 @@ function removeCachedModelPaths(root, model) {
|
|
|
586424
587272
|
function ollamaApiBase(ctx3) {
|
|
586425
587273
|
return String(ctx3.config.backendUrl || "http://localhost:11434").replace(/\/v1\/?$/, "").replace(/\/$/, "");
|
|
586426
587274
|
}
|
|
587275
|
+
async function fetchOllamaModelSizes(ctx3) {
|
|
587276
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
587277
|
+
const resp = await fetch(`${ollamaApiBase(ctx3)}/api/tags`, {
|
|
587278
|
+
signal: AbortSignal.timeout(5e3)
|
|
587279
|
+
});
|
|
587280
|
+
if (!resp.ok) return sizes;
|
|
587281
|
+
const data = await resp.json().catch(() => null);
|
|
587282
|
+
for (const entry of data?.models ?? []) {
|
|
587283
|
+
const size = Number(entry.size ?? 0);
|
|
587284
|
+
if (!Number.isFinite(size) || size <= 0) continue;
|
|
587285
|
+
for (const raw of [entry.name, entry.model]) {
|
|
587286
|
+
if (!raw) continue;
|
|
587287
|
+
sizes.set(raw, size);
|
|
587288
|
+
sizes.set(raw.replace(/:latest$/, ""), size);
|
|
587289
|
+
}
|
|
587290
|
+
}
|
|
587291
|
+
return sizes;
|
|
587292
|
+
}
|
|
587293
|
+
function ollamaModelDiskStats(model, sizes) {
|
|
587294
|
+
const bytes = sizes.get(model) ?? sizes.get(`${model}:latest`) ?? sizes.get(model.replace(/:latest$/, "")) ?? 0;
|
|
587295
|
+
return { downloaded: bytes > 0, bytes, paths: [] };
|
|
587296
|
+
}
|
|
587297
|
+
function imageModelDiskStats(ctx3, preset, ollamaSizes) {
|
|
587298
|
+
if (preset.backend === "ollama") return ollamaModelDiskStats(preset.id, ollamaSizes);
|
|
587299
|
+
if (preset.backend === "diffusers") return cachedModelDiskStats(imageGenerationDir(ctx3.repoRoot), preset.id);
|
|
587300
|
+
return { downloaded: false, bytes: 0, paths: [] };
|
|
587301
|
+
}
|
|
587302
|
+
function audioModelDiskStats(ctx3, preset) {
|
|
587303
|
+
if (preset.backend === "project") return { downloaded: false, bytes: 0, paths: [] };
|
|
587304
|
+
return cachedModelDiskStats(audioGenerationDir(ctx3.repoRoot), preset.id);
|
|
587305
|
+
}
|
|
586427
587306
|
async function deleteOllamaWeights(ctx3, model) {
|
|
586428
587307
|
const resp = await fetch(`${ollamaApiBase(ctx3)}/api/delete`, {
|
|
586429
587308
|
method: "DELETE",
|
|
@@ -586453,19 +587332,23 @@ async function deleteImageModelWeights(ctx3, preset) {
|
|
|
586453
587332
|
async function showImageModelsMenu(ctx3, hasLocal) {
|
|
586454
587333
|
const settings = resolveSettings(ctx3.repoRoot);
|
|
586455
587334
|
const specs = detectSystemSpecs();
|
|
587335
|
+
const ollamaSizes = await fetchOllamaModelSizes(ctx3).catch(() => /* @__PURE__ */ new Map());
|
|
587336
|
+
const buildModelItem = (preset) => {
|
|
587337
|
+
const fit2 = rateImagePresetForHardware(preset, specs);
|
|
587338
|
+
const disk = imageModelDiskStats(ctx3, preset, ollamaSizes);
|
|
587339
|
+
const downloaded = disk.downloaded ? `${c3.green("✓")} ` : "";
|
|
587340
|
+
return {
|
|
587341
|
+
key: `model:${preset.id}`,
|
|
587342
|
+
label: `${downloaded}${imageFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${preset.label}`,
|
|
587343
|
+
detail: `${fit2.score}/100 ${fit2.label} · ${preset.category ?? preset.backend} · ${preset.sizeClass ?? preset.id}${downloadedModelSuffix(disk)}`
|
|
587344
|
+
};
|
|
587345
|
+
};
|
|
586456
587346
|
const items = [
|
|
586457
587347
|
{ key: "setup:ollama", label: "Setup Ollama", detail: "Pull x/z-image-turbo or x/flux2-klein" },
|
|
586458
587348
|
{ key: "setup:diffusers", label: "Setup Diffusers", detail: "Auto-installs SDXL Turbo under .omnius/image-gen/.venv" },
|
|
586459
587349
|
{ key: "setup:sdcpp", label: "Setup stable-diffusion.cpp", detail: "CPU/GGUF/checkpoint route" },
|
|
586460
587350
|
{ key: "hdr:models", label: selectColors.dim("─── Models ───") },
|
|
586461
|
-
...IMAGE_GENERATION_MODEL_PRESETS.map(
|
|
586462
|
-
const fit2 = rateImagePresetForHardware(preset, specs);
|
|
586463
|
-
return {
|
|
586464
|
-
key: `model:${preset.id}`,
|
|
586465
|
-
label: `${imageFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${preset.label}`,
|
|
586466
|
-
detail: `${fit2.score}/100 ${fit2.label} · ${preset.category ?? preset.backend} · ${preset.sizeClass ?? preset.id}`
|
|
586467
|
-
};
|
|
586468
|
-
})
|
|
587351
|
+
...IMAGE_GENERATION_MODEL_PRESETS.map(buildModelItem)
|
|
586469
587352
|
];
|
|
586470
587353
|
const result = await tuiSelect({
|
|
586471
587354
|
items,
|
|
@@ -586491,6 +587374,11 @@ async function showImageModelsMenu(ctx3, hasLocal) {
|
|
|
586491
587374
|
}
|
|
586492
587375
|
deleteImageModelWeights(ctx3, preset).then((messages2) => {
|
|
586493
587376
|
for (const message2 of messages2) renderInfo(message2);
|
|
587377
|
+
if (preset.backend === "ollama") {
|
|
587378
|
+
ollamaSizes.delete(preset.id);
|
|
587379
|
+
ollamaSizes.delete(`${preset.id}:latest`);
|
|
587380
|
+
}
|
|
587381
|
+
Object.assign(item, buildModelItem(preset));
|
|
586494
587382
|
done(false);
|
|
586495
587383
|
}).catch((err) => {
|
|
586496
587384
|
renderError(`Image weight delete failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -586548,7 +587436,7 @@ async function handleImageCommand(ctx3, arg, hasLocal) {
|
|
|
586548
587436
|
return "handled";
|
|
586549
587437
|
}
|
|
586550
587438
|
if (parsed.subcommand === "models" || parsed.subcommand === "list") {
|
|
586551
|
-
renderImageModelList();
|
|
587439
|
+
await renderImageModelList(ctx3);
|
|
586552
587440
|
return "handled";
|
|
586553
587441
|
}
|
|
586554
587442
|
if (parsed.subcommand === "setup") {
|
|
@@ -586683,7 +587571,7 @@ function rateAudioPresetForHardware(preset, specs) {
|
|
|
586683
587571
|
function audioFitIcon(score) {
|
|
586684
587572
|
return imageFitIcon(score);
|
|
586685
587573
|
}
|
|
586686
|
-
function renderAudioModelList(kind) {
|
|
587574
|
+
async function renderAudioModelList(ctx3, kind) {
|
|
586687
587575
|
const specs = detectSystemSpecs();
|
|
586688
587576
|
const title = kind === "music" ? "Music" : "Sound";
|
|
586689
587577
|
const hardware = `${specs.totalRamGB.toFixed(0)}GB RAM` + (specs.gpuVramGB > 0 ? ` + ${specs.gpuVramGB.toFixed(0)}GB VRAM (${specs.gpuName || "NVIDIA GPU"})` : " + no NVIDIA VRAM detected");
|
|
@@ -586706,7 +587594,9 @@ function renderAudioModelList(kind) {
|
|
|
586706
587594
|
renderInfo(c3.bold(category));
|
|
586707
587595
|
for (const preset of presets) {
|
|
586708
587596
|
const fit2 = rateAudioPresetForHardware(preset, specs);
|
|
586709
|
-
|
|
587597
|
+
const disk = audioModelDiskStats(ctx3, preset);
|
|
587598
|
+
const diskInfo = disk.downloaded ? ` ${c3.green("✓")} ${formatFileSize(disk.bytes)}` : "";
|
|
587599
|
+
renderInfo(`${audioFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${c3.bold(preset.label)}${diskInfo}`);
|
|
586710
587600
|
renderInfo(` id: ${preset.id}`);
|
|
586711
587601
|
renderInfo(` type: ${preset.backend} · ${preset.sizeClass} · ${fit2.label}`);
|
|
586712
587602
|
renderImagePresetDetail(" quality: ", preset.quality);
|
|
@@ -586728,6 +587618,16 @@ async function showAudioGenerationMenu(ctx3, hasLocal, kind) {
|
|
|
586728
587618
|
const specs = detectSystemSpecs();
|
|
586729
587619
|
const activeModel = activeAudioModel(settings, kind);
|
|
586730
587620
|
const title = kind === "music" ? "Music Generation" : "Sound Generation";
|
|
587621
|
+
const buildModelItem = (preset) => {
|
|
587622
|
+
const fit2 = rateAudioPresetForHardware(preset, specs);
|
|
587623
|
+
const disk = audioModelDiskStats(ctx3, preset);
|
|
587624
|
+
const downloaded = disk.downloaded ? `${c3.green("✓")} ` : "";
|
|
587625
|
+
return {
|
|
587626
|
+
key: `model:${preset.id}`,
|
|
587627
|
+
label: `${downloaded}${audioFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${preset.label}`,
|
|
587628
|
+
detail: `${fit2.label} · ${preset.category} · ${preset.sizeClass}${downloadedModelSuffix(disk)}`
|
|
587629
|
+
};
|
|
587630
|
+
};
|
|
586731
587631
|
const setupItems = kind === "music" ? [
|
|
586732
587632
|
{ key: "setup:transformers", label: "Setup Transformers", detail: "Default MusicGen path; avoids AudioCraft/PyAV headers" },
|
|
586733
587633
|
{ key: "setup:audiocraft", label: "Setup AudioCraft", detail: "Optional MusicGen/AudioGen upstream runtime" },
|
|
@@ -586742,14 +587642,7 @@ async function showAudioGenerationMenu(ctx3, hasLocal, kind) {
|
|
|
586742
587642
|
const items = [
|
|
586743
587643
|
...setupItems,
|
|
586744
587644
|
{ key: "hdr:models", label: selectColors.dim("─── Models ───") },
|
|
586745
|
-
...AUDIO_GENERATION_MODEL_PRESETS.filter((preset) => preset.kind === kind).map(
|
|
586746
|
-
const fit2 = rateAudioPresetForHardware(preset, specs);
|
|
586747
|
-
return {
|
|
586748
|
-
key: `model:${preset.id}`,
|
|
586749
|
-
label: `${audioFitIcon(fit2.score)} ${String(fit2.score).padStart(3)}/100 ${preset.label}`,
|
|
586750
|
-
detail: `${fit2.label} · ${preset.category} · ${preset.sizeClass}`
|
|
586751
|
-
};
|
|
586752
|
-
})
|
|
587645
|
+
...AUDIO_GENERATION_MODEL_PRESETS.filter((preset) => preset.kind === kind).map(buildModelItem)
|
|
586753
587646
|
];
|
|
586754
587647
|
const result = await tuiSelect({
|
|
586755
587648
|
items,
|
|
@@ -586775,6 +587668,7 @@ async function showAudioGenerationMenu(ctx3, hasLocal, kind) {
|
|
|
586775
587668
|
}
|
|
586776
587669
|
deleteAudioModelWeights(ctx3, preset).then((messages2) => {
|
|
586777
587670
|
for (const message2 of messages2) renderInfo(message2);
|
|
587671
|
+
Object.assign(item, buildModelItem(preset));
|
|
586778
587672
|
done(false);
|
|
586779
587673
|
}).catch((err) => {
|
|
586780
587674
|
renderError(`${kind} weight delete failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -586835,7 +587729,7 @@ async function handleAudioGenerationCommand(ctx3, arg, hasLocal, kind) {
|
|
|
586835
587729
|
return "handled";
|
|
586836
587730
|
}
|
|
586837
587731
|
if (parsed.subcommand === "models" || parsed.subcommand === "list") {
|
|
586838
|
-
renderAudioModelList(kind);
|
|
587732
|
+
await renderAudioModelList(ctx3, kind);
|
|
586839
587733
|
return "handled";
|
|
586840
587734
|
}
|
|
586841
587735
|
if (parsed.subcommand === "setup") {
|
|
@@ -587355,7 +588249,9 @@ async function showModelPicker(ctx3, local = false) {
|
|
|
587355
588249
|
function formatFileSize(bytes) {
|
|
587356
588250
|
if (bytes < 1024) return `${bytes}B`;
|
|
587357
588251
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`;
|
|
587358
|
-
return `${(bytes /
|
|
588252
|
+
if (bytes < 1024 ** 3) return `${(bytes / 1024 ** 2).toFixed(1)}MB`;
|
|
588253
|
+
if (bytes < 1024 ** 4) return `${(bytes / 1024 ** 3).toFixed(1)}GB`;
|
|
588254
|
+
return `${(bytes / 1024 ** 4).toFixed(1)}TB`;
|
|
587359
588255
|
}
|
|
587360
588256
|
async function handleVoiceMenu(ctx3, save2, hasLocal) {
|
|
587361
588257
|
const modeLabels = {
|
|
@@ -595432,10 +596328,14 @@ var init_bless_engine = __esm({
|
|
|
595432
596328
|
* Priority queue is checked first, then reminders/attention items are ingested. */
|
|
595433
596329
|
async getNextTask() {
|
|
595434
596330
|
try {
|
|
595435
|
-
const dueReminders = await getDueReminders(this.repoRoot
|
|
596331
|
+
const dueReminders = await getDueReminders(this.repoRoot, {
|
|
596332
|
+
deliveryMode: "action",
|
|
596333
|
+
includeUnscoped: true
|
|
596334
|
+
});
|
|
595436
596335
|
for (const r2 of dueReminders.filter((r3) => r3.status === "pending")) {
|
|
595437
596336
|
const priority = r2.priority === "critical" ? "critical" : r2.priority === "high" ? "high" : "moderate";
|
|
595438
|
-
const
|
|
596337
|
+
const task2 = r2.delivery?.taskDescription || r2.message;
|
|
596338
|
+
const prompt = `${priority === "critical" ? "URGENT " : ""}REMINDER ACTION: ${task2}${r2.tags?.length ? ` [tags: ${r2.tags.join(", ")}]` : ""}. Check the agenda for full context and take appropriate action.`;
|
|
595439
596339
|
this.priorityEngine.ingest(prompt, "internal", "reminder", { reminderId: r2.id }, priority);
|
|
595440
596340
|
}
|
|
595441
596341
|
} catch {
|
|
@@ -597144,7 +598044,7 @@ var init_tool_policy = __esm({
|
|
|
597144
598044
|
"aiwg_workflow",
|
|
597145
598045
|
"autoresearch",
|
|
597146
598046
|
"scheduler",
|
|
597147
|
-
"
|
|
598047
|
+
"cronjob",
|
|
597148
598048
|
"agenda"
|
|
597149
598049
|
]);
|
|
597150
598050
|
SAFE_PUBLIC_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -597164,6 +598064,9 @@ var init_tool_policy = __esm({
|
|
|
597164
598064
|
"transcribe_file",
|
|
597165
598065
|
"video_understand",
|
|
597166
598066
|
"audio_analyze",
|
|
598067
|
+
"reminder",
|
|
598068
|
+
"remind",
|
|
598069
|
+
"reminders",
|
|
597167
598070
|
"explore_tools",
|
|
597168
598071
|
"telegram_media_recent",
|
|
597169
598072
|
"generate_image",
|
|
@@ -597191,6 +598094,9 @@ var init_tool_policy = __esm({
|
|
|
597191
598094
|
"transcribe_file",
|
|
597192
598095
|
"video_understand",
|
|
597193
598096
|
"audio_analyze",
|
|
598097
|
+
"reminder",
|
|
598098
|
+
"remind",
|
|
598099
|
+
"reminders",
|
|
597194
598100
|
"explore_tools",
|
|
597195
598101
|
"telegram_media_recent",
|
|
597196
598102
|
"generate_image",
|
|
@@ -597926,7 +598832,7 @@ var init_vision_ingress = __esm({
|
|
|
597926
598832
|
});
|
|
597927
598833
|
|
|
597928
598834
|
// packages/cli/src/tui/telegram-bridge.ts
|
|
597929
|
-
import { mkdirSync as mkdirSync60, existsSync as existsSync106, unlinkSync as unlinkSync21, readdirSync as readdirSync36, statSync as statSync36, readFileSync as readFileSync87, writeFileSync as writeFileSync57 } from "node:fs";
|
|
598835
|
+
import { mkdirSync as mkdirSync60, existsSync as existsSync106, unlinkSync as unlinkSync21, readdirSync as readdirSync36, statSync as statSync36, statfsSync as statfsSync3, readFileSync as readFileSync87, writeFileSync as writeFileSync57 } from "node:fs";
|
|
597930
598836
|
import { join as join121, resolve as resolve39, basename as basename23, relative as relative13, isAbsolute as isAbsolute7, extname as extname15 } from "node:path";
|
|
597931
598837
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
597932
598838
|
import { createHash as createHash19, randomInt } from "node:crypto";
|
|
@@ -598194,12 +599100,28 @@ function buildTelegramRuntimeContext(now = /* @__PURE__ */ new Date(), repoRoot)
|
|
|
598194
599100
|
timeZoneName: "short"
|
|
598195
599101
|
}).format(now);
|
|
598196
599102
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
|
|
599103
|
+
let diskLine = "";
|
|
599104
|
+
if (repoRoot) {
|
|
599105
|
+
try {
|
|
599106
|
+
const stats = statfsSync3(repoRoot);
|
|
599107
|
+
const totalBytes = stats.blocks * stats.bsize;
|
|
599108
|
+
const freeBytes = stats.bavail * stats.bsize;
|
|
599109
|
+
const usedBytes = totalBytes - freeBytes;
|
|
599110
|
+
const totalGB = Math.round(totalBytes / 1024 ** 3);
|
|
599111
|
+
const freeGB = Math.round(freeBytes / 1024 ** 3);
|
|
599112
|
+
const usedGB = Math.round(usedBytes / 1024 ** 3);
|
|
599113
|
+
const usedPct = totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : 0;
|
|
599114
|
+
diskLine = `Disk: disk_available_gb=${freeGB} disk_used_gb=${usedGB} disk_total_gb=${totalGB} disk_used_pct=${usedPct} path=${repoRoot}`;
|
|
599115
|
+
} catch {
|
|
599116
|
+
}
|
|
599117
|
+
}
|
|
598197
599118
|
return [
|
|
598198
599119
|
`Current date: ${date}`,
|
|
598199
599120
|
`Current time: ${time}`,
|
|
598200
599121
|
`Current ISO timestamp: ${now.toISOString()}`,
|
|
598201
599122
|
`Timezone: ${timezone}`,
|
|
598202
|
-
repoRoot ? `Working directory: ${repoRoot}` : ""
|
|
599123
|
+
repoRoot ? `Working directory: ${repoRoot}` : "",
|
|
599124
|
+
diskLine
|
|
598203
599125
|
].filter(Boolean).join("\n");
|
|
598204
599126
|
}
|
|
598205
599127
|
function telegramSessionIdFromKey(sessionKey) {
|
|
@@ -598251,6 +599173,14 @@ function renderTelegramLiveProgressHTML(progressLines, accumulated) {
|
|
|
598251
599173
|
}
|
|
598252
599174
|
return progressLines.slice(-6).map((line) => line.trim()).filter((line) => !isTelegramInternalStatusText(line)).filter(Boolean).join("\n");
|
|
598253
599175
|
}
|
|
599176
|
+
function splitTelegramReminderDue(raw) {
|
|
599177
|
+
const text = raw.trim().replace(/^set\s+/i, "").trim();
|
|
599178
|
+
const dueMatch = text.match(
|
|
599179
|
+
/^((?:in\s+\d+\s*(?:m|min|mins|minutes?|h|hr|hrs|hours?|d|days?|w|weeks?))|tomorrow|next week|next startup|startup|now|(?:today\s+)?at\s+\d{1,2}:\d{2})\s+(.+)$/i
|
|
599180
|
+
);
|
|
599181
|
+
if (!dueMatch) return { message: text };
|
|
599182
|
+
return { due: dueMatch[1].trim(), message: dueMatch[2].trim() };
|
|
599183
|
+
}
|
|
598254
599184
|
function telegramSyntheticHelpSignatures() {
|
|
598255
599185
|
return [
|
|
598256
599186
|
{ signature: "/help", description: "Show Telegram command help" },
|
|
@@ -598740,7 +599670,7 @@ function renderTelegramSubAgentError(username, error) {
|
|
|
598740
599670
|
process.stdout.write(` ${c3.dim("⎿")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
|
|
598741
599671
|
`);
|
|
598742
599672
|
}
|
|
598743
|
-
var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TelegramBridge;
|
|
599673
|
+
var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TelegramBridge;
|
|
598744
599674
|
var init_telegram_bridge = __esm({
|
|
598745
599675
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
598746
599676
|
"use strict";
|
|
@@ -598936,6 +599866,7 @@ Telegram response contract:
|
|
|
598936
599866
|
"your"
|
|
598937
599867
|
]);
|
|
598938
599868
|
TELEGRAM_PUBLIC_HELP_COMMANDS = /* @__PURE__ */ new Set(["help", "start", "auth", "call"]);
|
|
599869
|
+
TELEGRAM_REMINDER_SLASH_COMMANDS = /* @__PURE__ */ new Set(["remind", "reminder", "reminders"]);
|
|
598939
599870
|
TELEGRAM_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".tif", ".svg"]);
|
|
598940
599871
|
MEDIA_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
598941
599872
|
TelegramBridge = class {
|
|
@@ -599136,6 +600067,49 @@ Telegram response contract:
|
|
|
599136
600067
|
const botless = first2.startsWith("/") ? first2.slice(1).split("@")[0]?.toLowerCase() : "";
|
|
599137
600068
|
return !!botless && this.telegramCommandMap.has(botless);
|
|
599138
600069
|
}
|
|
600070
|
+
async handleTelegramReminderSlash(msg, commandText, context2) {
|
|
600071
|
+
if (!this.repoRoot) {
|
|
600072
|
+
await this.replyToTelegramMessage(msg, "Reminder storage is not available yet.");
|
|
600073
|
+
return;
|
|
600074
|
+
}
|
|
600075
|
+
const first2 = commandText.trim().split(/\s+/)[0] ?? "";
|
|
600076
|
+
const cmd = first2.slice(1).split("@")[0]?.toLowerCase() || "reminder";
|
|
600077
|
+
const arg = commandText.trim().slice(first2.length).trim();
|
|
600078
|
+
const lower = arg.toLowerCase();
|
|
600079
|
+
const tool = this.buildTelegramReminderTool(context2, this.repoRoot, msg.chatId, msg);
|
|
600080
|
+
let args;
|
|
600081
|
+
if (!arg || lower === "list" || lower === "pending" || lower === "all" || lower === "seen") {
|
|
600082
|
+
args = { action: "list", filter: lower === "all" || lower === "seen" ? lower : "pending" };
|
|
600083
|
+
} else if (lower === "completed" || lower === "dismissed") {
|
|
600084
|
+
args = { action: "list", filter: lower };
|
|
600085
|
+
} else if (lower.startsWith("complete ")) {
|
|
600086
|
+
args = { action: "complete", id: arg.slice("complete ".length).trim() };
|
|
600087
|
+
} else if (lower.startsWith("dismiss ")) {
|
|
600088
|
+
args = { action: "dismiss", id: arg.slice("dismiss ".length).trim() };
|
|
600089
|
+
} else if (lower.startsWith("snooze ")) {
|
|
600090
|
+
const rest = arg.slice("snooze ".length).trim();
|
|
600091
|
+
const [id, ...dueParts] = rest.split(/\s+/);
|
|
600092
|
+
args = { action: "snooze", id, due: dueParts.join(" ").trim() || "in 1h" };
|
|
600093
|
+
} else {
|
|
600094
|
+
const { due, message: message2 } = splitTelegramReminderDue(arg);
|
|
600095
|
+
if (!message2) {
|
|
600096
|
+
await this.replyToTelegramMessage(msg, "Usage: /remind [in 30m|tomorrow|at 14:30] <message>");
|
|
600097
|
+
return;
|
|
600098
|
+
}
|
|
600099
|
+
args = {
|
|
600100
|
+
action: "set",
|
|
600101
|
+
kind: "minimal",
|
|
600102
|
+
message: message2,
|
|
600103
|
+
content: message2,
|
|
600104
|
+
...due ? { due } : {}
|
|
600105
|
+
};
|
|
600106
|
+
}
|
|
600107
|
+
const result = await tool.execute(args);
|
|
600108
|
+
await this.replyToTelegramMessage(
|
|
600109
|
+
msg,
|
|
600110
|
+
result.success ? result.output || "Reminder updated." : result.error || `/${cmd} failed`
|
|
600111
|
+
);
|
|
600112
|
+
}
|
|
599139
600113
|
/** Write to the scrollable TUI waterfall area (respects status bar scroll region) */
|
|
599140
600114
|
tuiWrite(fn) {
|
|
599141
600115
|
if (this.writeContent) {
|
|
@@ -600210,6 +601184,11 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
600210
601184
|
const toolContext = this.resolveToolContext(msg, isAdmin);
|
|
600211
601185
|
const isAdminDM = toolContext === "telegram-admin-dm";
|
|
600212
601186
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
601187
|
+
const telegramSlash = this.telegramSlashName(normalizedCommandText);
|
|
601188
|
+
if (msg.text.trim().startsWith("/") && TELEGRAM_REMINDER_SLASH_COMMANDS.has(telegramSlash)) {
|
|
601189
|
+
await this.handleTelegramReminderSlash(msg, normalizedCommandText, toolContext);
|
|
601190
|
+
return;
|
|
601191
|
+
}
|
|
600213
601192
|
if (msg.text.trim().toLowerCase() === "/hangup" && isAdmin && this.callStopper) {
|
|
600214
601193
|
const callUrl = this.callUrlGetter?.();
|
|
600215
601194
|
if (callUrl) {
|
|
@@ -600264,7 +601243,6 @@ Join: ${newUrl}`);
|
|
|
600264
601243
|
return;
|
|
600265
601244
|
}
|
|
600266
601245
|
}
|
|
600267
|
-
const telegramSlash = this.telegramSlashName(normalizedCommandText);
|
|
600268
601246
|
const publicCreativeSlash = telegramSlash === "image";
|
|
600269
601247
|
if (!isAdmin && msg.text.trim().startsWith("/") && this.isKnownTelegramSlash(normalizedCommandText) && !publicCreativeSlash) {
|
|
600270
601248
|
await this.replyToTelegramMessage(
|
|
@@ -601357,7 +602335,8 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
601357
602335
|
new VideoUnderstandTool(repoRoot),
|
|
601358
602336
|
new AudioAnalyzeTool(),
|
|
601359
602337
|
new ExploreToolsTool(),
|
|
601360
|
-
this.buildTelegramMediaRecentTool(chatId, msg)
|
|
602338
|
+
this.buildTelegramMediaRecentTool(chatId, msg),
|
|
602339
|
+
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg)
|
|
601361
602340
|
];
|
|
601362
602341
|
const adminTools = [
|
|
601363
602342
|
new ShellTool(repoRoot),
|
|
@@ -601415,6 +602394,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
601415
602394
|
new ImpactAnalysisTool(repoRoot),
|
|
601416
602395
|
new CodeNeighborsTool(repoRoot),
|
|
601417
602396
|
new ProcessHealthTool(),
|
|
602397
|
+
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg),
|
|
601418
602398
|
fullSubAgentTool,
|
|
601419
602399
|
this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg)
|
|
601420
602400
|
];
|
|
@@ -601460,6 +602440,34 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
601460
602440
|
]);
|
|
601461
602441
|
return tools.filter((tool) => !blocked.has(tool.name));
|
|
601462
602442
|
}
|
|
602443
|
+
buildTelegramReminderTool(context2, repoRoot, chatId, currentMsg) {
|
|
602444
|
+
const rawChatId = String(chatId ?? currentMsg?.chatId ?? "unknown");
|
|
602445
|
+
const isPrivate2 = currentMsg?.chatType === "private";
|
|
602446
|
+
const username = currentMsg?.username ? currentMsg.username.replace(/^@/, "") : void 0;
|
|
602447
|
+
return new ReminderTool(repoRoot, {
|
|
602448
|
+
defaultScope: {
|
|
602449
|
+
surface: "telegram",
|
|
602450
|
+
visibility: isPrivate2 ? "private" : "public",
|
|
602451
|
+
targetId: rawChatId,
|
|
602452
|
+
chatId: rawChatId,
|
|
602453
|
+
...currentMsg?.fromUserId !== void 0 ? { userId: String(currentMsg.fromUserId) } : {},
|
|
602454
|
+
...username ? { username } : {},
|
|
602455
|
+
label: isPrivate2 ? `telegram dm${username ? ` @${username}` : ""}` : `telegram group ${currentMsg?.chatTitle ?? rawChatId}`
|
|
602456
|
+
},
|
|
602457
|
+
lockScope: true,
|
|
602458
|
+
allowActionDelivery: context2 === "telegram-admin-dm",
|
|
602459
|
+
source: "user",
|
|
602460
|
+
createdFrom: context2
|
|
602461
|
+
});
|
|
602462
|
+
}
|
|
602463
|
+
buildTelegramReminderTools(context2, repoRoot, chatId, currentMsg) {
|
|
602464
|
+
const reminder = this.buildTelegramReminderTool(context2, repoRoot, chatId, currentMsg);
|
|
602465
|
+
return [
|
|
602466
|
+
reminder,
|
|
602467
|
+
aliasTool(reminder, "remind", "Alias for reminder: set scoped Telegram reminders."),
|
|
602468
|
+
aliasTool(reminder, "reminders", "Alias for reminder: list and manage scoped Telegram reminders.")
|
|
602469
|
+
];
|
|
602470
|
+
}
|
|
601463
602471
|
buildTelegramMediaRecentTool(chatId, currentMsg) {
|
|
601464
602472
|
const bridge = this;
|
|
601465
602473
|
return {
|
|
@@ -626570,6 +627578,33 @@ function adaptTool6(tool) {
|
|
|
626570
627578
|
}
|
|
626571
627579
|
};
|
|
626572
627580
|
}
|
|
627581
|
+
function createTuiReminderOptions(allowActionDelivery = true) {
|
|
627582
|
+
const sessionId = process.env["OMNIUS_SESSION_ID"] || "terminal";
|
|
627583
|
+
return {
|
|
627584
|
+
defaultScope: {
|
|
627585
|
+
surface: "tui",
|
|
627586
|
+
visibility: "private",
|
|
627587
|
+
targetId: sessionId,
|
|
627588
|
+
sessionId,
|
|
627589
|
+
label: "terminal"
|
|
627590
|
+
},
|
|
627591
|
+
allowActionDelivery,
|
|
627592
|
+
createdFrom: "tui"
|
|
627593
|
+
};
|
|
627594
|
+
}
|
|
627595
|
+
function withReminderAliases(reminder) {
|
|
627596
|
+
return [
|
|
627597
|
+
reminder,
|
|
627598
|
+
aliasTool(reminder, "remind", "Alias for reminder: set or list scoped minimal reminders and action triggers."),
|
|
627599
|
+
aliasTool(reminder, "reminders", "Alias for reminder: list and manage scoped reminders.")
|
|
627600
|
+
];
|
|
627601
|
+
}
|
|
627602
|
+
function withSchedulerAliases(scheduler) {
|
|
627603
|
+
return [
|
|
627604
|
+
scheduler,
|
|
627605
|
+
aliasTool(scheduler, "cronjob", "Alias for scheduler: create, list, and manage OS cron-backed time triggers.")
|
|
627606
|
+
];
|
|
627607
|
+
}
|
|
626573
627608
|
function scanForSessionSignals(toolOutput) {
|
|
626574
627609
|
if (/SESSION_ACTIVE\s*=\s*true/i.test(toolOutput)) {
|
|
626575
627610
|
_interactiveSessionActive = true;
|
|
@@ -626910,8 +627945,8 @@ function buildSubAgentTools(repoRoot, config) {
|
|
|
626910
627945
|
new AiwgHealthTool(repoRoot),
|
|
626911
627946
|
new AiwgWorkflowTool(repoRoot),
|
|
626912
627947
|
// Scheduler + agenda (time-based tooling)
|
|
626913
|
-
new SchedulerTool(repoRoot),
|
|
626914
|
-
new ReminderTool(repoRoot),
|
|
627948
|
+
...withSchedulerAliases(new SchedulerTool(repoRoot)),
|
|
627949
|
+
...withReminderAliases(new ReminderTool(repoRoot, createTuiReminderOptions())),
|
|
626915
627950
|
new AgendaTool(repoRoot),
|
|
626916
627951
|
// Vision + multimodal memory
|
|
626917
627952
|
new VisionTool(repoRoot),
|
|
@@ -627024,8 +628059,8 @@ function buildTools(repoRoot, config, contextWindowSize, modelTier) {
|
|
|
627024
628059
|
// Autoresearch (autonomous ML experiment loop)
|
|
627025
628060
|
new AutoresearchTool(repoRoot),
|
|
627026
628061
|
// Temporal agency (scheduling, reminders, attention steering)
|
|
627027
|
-
new SchedulerTool(repoRoot),
|
|
627028
|
-
new ReminderTool(repoRoot),
|
|
628062
|
+
...withSchedulerAliases(new SchedulerTool(repoRoot)),
|
|
628063
|
+
...withReminderAliases(new ReminderTool(repoRoot, createTuiReminderOptions())),
|
|
627029
628064
|
new AgendaTool(repoRoot),
|
|
627030
628065
|
// OpenCode + Factory AI delegation + long-horizon cron agent
|
|
627031
628066
|
new OpenCodeTool(repoRoot),
|
|
@@ -630341,6 +631376,7 @@ ${result.summary}`
|
|
|
630341
631376
|
let telegramBridge = null;
|
|
630342
631377
|
let activeTelegramChatId = null;
|
|
630343
631378
|
let dmnRetriggerTimer = null;
|
|
631379
|
+
let reminderDispatchTimer = null;
|
|
630344
631380
|
function scheduleDMNRetrigger(delayMs) {
|
|
630345
631381
|
if (dmnRetriggerTimer) clearTimeout(dmnRetriggerTimer);
|
|
630346
631382
|
dmnRetriggerTimer = setTimeout(async () => {
|
|
@@ -630415,10 +631451,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
630415
631451
|
const turnQueue = [];
|
|
630416
631452
|
let queueDrainScheduled = false;
|
|
630417
631453
|
let sessionTitle = null;
|
|
630418
|
-
const queuePrompt = (prompt, source = "user") => {
|
|
631454
|
+
const queuePrompt = (prompt, source = "user", options2 = {}) => {
|
|
630419
631455
|
const trimmed = prompt.trim();
|
|
630420
631456
|
if (!trimmed) return turnQueue.length;
|
|
630421
|
-
turnQueue.push({ prompt: trimmed, source, enqueuedAt: Date.now() });
|
|
631457
|
+
turnQueue.push({ prompt: trimmed, source, enqueuedAt: Date.now(), ...options2 });
|
|
630422
631458
|
return turnQueue.length;
|
|
630423
631459
|
};
|
|
630424
631460
|
const clearQueuedPrompts = () => {
|
|
@@ -630443,9 +631479,103 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
630443
631479
|
`Starting queued prompt from ${next.source} (${turnQueue.length} remaining).`
|
|
630444
631480
|
)
|
|
630445
631481
|
);
|
|
631482
|
+
if (next.telegramChatId !== void 0) activeTelegramChatId = next.telegramChatId;
|
|
630446
631483
|
rl.emit("line", next.prompt);
|
|
630447
631484
|
}, 0);
|
|
630448
631485
|
};
|
|
631486
|
+
const reminderTelegramTarget = (scope) => {
|
|
631487
|
+
if (!scope || scope.surface !== "telegram") return null;
|
|
631488
|
+
const raw = scope.chatId ?? scope.targetId;
|
|
631489
|
+
if (!raw) return null;
|
|
631490
|
+
return /^-?\d+$/.test(raw) ? Number(raw) : raw;
|
|
631491
|
+
};
|
|
631492
|
+
const reminderText = (reminder) => {
|
|
631493
|
+
const content = reminder.delivery?.content || reminder.message;
|
|
631494
|
+
const prefix = reminder.priority === "critical" ? "URGENT reminder" : "Reminder";
|
|
631495
|
+
return `${prefix}: ${content}`;
|
|
631496
|
+
};
|
|
631497
|
+
const reminderActionPrompt = (reminder) => {
|
|
631498
|
+
const task = reminder.delivery?.taskDescription || reminder.delivery?.prompt || reminder.message;
|
|
631499
|
+
const scope = reminder.scope ? `${reminder.scope.surface}/${reminder.scope.visibility}/${reminder.scope.targetId}` : "unscoped";
|
|
631500
|
+
return [
|
|
631501
|
+
`[Scheduled reminder action | ${reminder.id}]`,
|
|
631502
|
+
``,
|
|
631503
|
+
`Trigger: ${reminder.message}`,
|
|
631504
|
+
`Scope: ${scope}`,
|
|
631505
|
+
reminder.context ? `Context: ${reminder.context}` : "",
|
|
631506
|
+
reminder.tags?.length ? `Tags: ${reminder.tags.join(", ")}` : "",
|
|
631507
|
+
``,
|
|
631508
|
+
`Task description:`,
|
|
631509
|
+
task
|
|
631510
|
+
].filter(Boolean).join("\n");
|
|
631511
|
+
};
|
|
631512
|
+
const dispatchDueReminder = async (reminder) => {
|
|
631513
|
+
const mode = reminder.delivery?.mode ?? "minimal";
|
|
631514
|
+
const scope = reminder.scope;
|
|
631515
|
+
if (scope?.surface === "telegram") {
|
|
631516
|
+
const target = reminderTelegramTarget(scope);
|
|
631517
|
+
if (!target || !telegramBridge?.isActive) return false;
|
|
631518
|
+
if (mode === "minimal") {
|
|
631519
|
+
await telegramBridge.sendMessage(target, reminderText(reminder));
|
|
631520
|
+
return true;
|
|
631521
|
+
}
|
|
631522
|
+
if (activeTask) return false;
|
|
631523
|
+
activeTelegramChatId = target;
|
|
631524
|
+
rl.emit("line", `${TELEGRAM_SAFETY_PROMPT}
|
|
631525
|
+
|
|
631526
|
+
---
|
|
631527
|
+
|
|
631528
|
+
${reminderActionPrompt(reminder)}
|
|
631529
|
+
|
|
631530
|
+
Respond to the scoped Telegram target when complete.`);
|
|
631531
|
+
return true;
|
|
631532
|
+
}
|
|
631533
|
+
if (scope?.surface === "gui") {
|
|
631534
|
+
if (mode === "minimal") {
|
|
631535
|
+
writeContent(() => renderInfo(reminderText(reminder)));
|
|
631536
|
+
showPrompt();
|
|
631537
|
+
return true;
|
|
631538
|
+
}
|
|
631539
|
+
if (activeTask) return false;
|
|
631540
|
+
queuePrompt(reminderActionPrompt(reminder), "reminder");
|
|
631541
|
+
drainQueuedPrompts();
|
|
631542
|
+
return true;
|
|
631543
|
+
}
|
|
631544
|
+
if (mode === "minimal") {
|
|
631545
|
+
writeContent(() => renderInfo(reminderText(reminder)));
|
|
631546
|
+
showPrompt();
|
|
631547
|
+
return true;
|
|
631548
|
+
}
|
|
631549
|
+
if (activeTask) {
|
|
631550
|
+
queuePrompt(reminderActionPrompt(reminder), "reminder");
|
|
631551
|
+
return true;
|
|
631552
|
+
}
|
|
631553
|
+
rl.emit("line", reminderActionPrompt(reminder));
|
|
631554
|
+
return true;
|
|
631555
|
+
};
|
|
631556
|
+
const dispatchDueReminders = async () => {
|
|
631557
|
+
try {
|
|
631558
|
+
const due = await getDueReminders(repoRoot, { deliveryMode: "any", includeUnscoped: true });
|
|
631559
|
+
const dispatched = [];
|
|
631560
|
+
for (const reminder of due) {
|
|
631561
|
+
const ok2 = await dispatchDueReminder(reminder);
|
|
631562
|
+
if (ok2) dispatched.push(reminder.id);
|
|
631563
|
+
}
|
|
631564
|
+
if (dispatched.length > 0) {
|
|
631565
|
+
await markRemindersTriggered(repoRoot, dispatched);
|
|
631566
|
+
}
|
|
631567
|
+
} catch {
|
|
631568
|
+
}
|
|
631569
|
+
};
|
|
631570
|
+
const startReminderDispatcher = () => {
|
|
631571
|
+
if (reminderDispatchTimer) return;
|
|
631572
|
+
reminderDispatchTimer = setInterval(() => {
|
|
631573
|
+
dispatchDueReminders().catch(() => {
|
|
631574
|
+
});
|
|
631575
|
+
}, 15e3);
|
|
631576
|
+
dispatchDueReminders().catch(() => {
|
|
631577
|
+
});
|
|
631578
|
+
};
|
|
630449
631579
|
const listRollbackCheckpoints = () => {
|
|
630450
631580
|
const out = [];
|
|
630451
631581
|
const pushJsonFiles = (dir, prefix) => {
|
|
@@ -631538,6 +632668,10 @@ Log: ${nexusLogPath}`)
|
|
|
631538
632668
|
statusBar.refreshHeaderContent();
|
|
631539
632669
|
},
|
|
631540
632670
|
exit() {
|
|
632671
|
+
if (reminderDispatchTimer) {
|
|
632672
|
+
clearInterval(reminderDispatchTimer);
|
|
632673
|
+
reminderDispatchTimer = null;
|
|
632674
|
+
}
|
|
631541
632675
|
statusBar.deactivate();
|
|
631542
632676
|
if (carousel.isRunning) carousel.stop();
|
|
631543
632677
|
banner.stop();
|
|
@@ -633483,17 +634617,12 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
633483
634617
|
});
|
|
633484
634618
|
showPrompt();
|
|
633485
634619
|
}, 300);
|
|
633486
|
-
if (dueReminders.length > 0) {
|
|
633487
|
-
await markRemindersSeen(
|
|
633488
|
-
repoRoot,
|
|
633489
|
-
dueReminders.map((r2) => r2.id)
|
|
633490
|
-
);
|
|
633491
|
-
}
|
|
633492
634620
|
}
|
|
633493
634621
|
} catch {
|
|
633494
634622
|
}
|
|
633495
634623
|
})();
|
|
633496
634624
|
}
|
|
634625
|
+
startReminderDispatcher();
|
|
633497
634626
|
if (hasTaskToResume) {
|
|
633498
634627
|
const pendingTask = loadPendingTask(repoRoot);
|
|
633499
634628
|
if (pendingTask) {
|