openmausbot 0.1.76 → 0.1.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{index-C6blGSq5.js → index-BqDJqf2C.js} +1 -1
- package/dist/assets/index-DjwAroIZ.js +305 -0
- package/dist/assets/index-Pbb6Ao0s.css +1 -0
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +5 -1
- package/dist-server/drivers/agents-proxy.js +838 -30
- package/dist-server/enterprise/server/index.js +387 -29
- package/dist-server/index.js +4097 -2063
- package/dist-server/openmausbot.js +730 -523
- package/dist-server/pair-cli.js +730 -523
- package/dist-server/server/agent-tool-policy.js +1 -0
- package/dist-server/server/auto-approve.js +16 -0
- package/dist-server/server/bot-overview.js +6 -2
- package/dist-server/server/bot-package.js +17 -3
- package/dist-server/server/browser-live.js +3 -0
- package/dist-server/server/chief-of-staff.js +2 -2
- package/dist-server/server/config.js +16 -0
- package/dist-server/server/drivers/acp/core.js +3 -1
- package/dist-server/server/drivers/agents-proxy.js +132 -27
- package/dist-server/server/drivers/boxagent.js +1 -1
- package/dist-server/server/drivers/claude.js +3 -2
- package/dist-server/server/drivers/codex.js +3 -1
- package/dist-server/server/drivers/pi.js +4 -0
- package/dist-server/server/enterprise.js +38 -0
- package/dist-server/server/environment.js +3 -0
- package/dist-server/server/fleet-agent.js +57 -13
- package/dist-server/server/fleet-cli.js +248 -31
- package/dist-server/server/fleet.js +88 -14
- package/dist-server/server/hosted-contract.js +16 -0
- package/dist-server/server/index.js +877 -197
- package/dist-server/server/message-file.js +4 -0
- package/dist-server/server/package-export.js +16 -14
- package/dist-server/server/peer-approval.js +1 -1
- package/dist-server/server/profile-requests.js +26 -4
- package/dist-server/server/provider-key-check.js +18 -1
- package/dist-server/server/request-auth.js +14 -5
- package/dist-server/server/room-handoffs.js +38 -1
- package/dist-server/server/routine-requests.js +86 -3
- package/dist-server/server/routines.js +31 -13
- package/dist-server/server/sessions.js +115 -8
- package/dist-server/server/setup-mode.js +11 -13
- package/dist-server/server/shared-computer-control.js +24 -0
- package/dist-server/server/shared-computers.js +131 -0
- package/dist-server/server/skill-learn.js +4 -4
- package/dist-server/server/skills.js +21 -0
- package/dist-server/server/steer-queue.js +2 -0
- package/dist-server/server/store.js +110 -8
- package/dist-server/server/system-prompt.js +7 -5
- package/dist-server/server/team-backup.js +6 -2
- package/dist-server/server/team-computers.js +108 -0
- package/dist-server/server/team-setup-requests.js +83 -31
- package/dist-server/server/tool-summary.js +53 -1
- package/dist-server/server/workspace-backup.js +1 -0
- package/dist-server/shared/approval-mode.js +4 -1
- package/dist-server/shared/cron-label.js +39 -0
- package/dist-server/shared/routine-schedule.js +89 -0
- package/dist-server/shared/team-backup.js +1 -1
- package/dist-server/shared/team-computer.js +1 -0
- package/dist-server/vps-container-mcp.js +5 -1
- package/enterprise/README.md +21 -3
- package/enterprise/server/index.js +387 -29
- package/package.json +1 -1
- package/dist/assets/index-BtT047dk.css +0 -1
- package/dist/assets/index-fKXFpB_J.js +0 -305
|
@@ -38,10 +38,719 @@ function isCredentialTargetId(value) {
|
|
|
38
38
|
return typeof value === "string" && Object.prototype.hasOwnProperty.call(CREDENTIAL_TARGETS, value);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// node_modules/.pnpm/croner@10.0.1/node_modules/croner/dist/croner.js
|
|
42
|
+
function T(s2) {
|
|
43
|
+
return Date.UTC(s2.y, s2.m - 1, s2.d, s2.h, s2.i, s2.s);
|
|
44
|
+
}
|
|
45
|
+
function D(s2, e) {
|
|
46
|
+
return s2.y === e.y && s2.m === e.m && s2.d === e.d && s2.h === e.h && s2.i === e.i && s2.s === e.s;
|
|
47
|
+
}
|
|
48
|
+
function A(s2, e) {
|
|
49
|
+
let t = new Date(Date.parse(s2));
|
|
50
|
+
if (isNaN(t)) throw new Error("Invalid ISO8601 passed to timezone parser.");
|
|
51
|
+
let r = s2.substring(9);
|
|
52
|
+
return r.includes("Z") || r.includes("+") || r.includes("-") ? b(t.getUTCFullYear(), t.getUTCMonth() + 1, t.getUTCDate(), t.getUTCHours(), t.getUTCMinutes(), t.getUTCSeconds(), "Etc/UTC") : b(t.getFullYear(), t.getMonth() + 1, t.getDate(), t.getHours(), t.getMinutes(), t.getSeconds(), e);
|
|
53
|
+
}
|
|
54
|
+
function v(s2, e, t) {
|
|
55
|
+
return k(A(s2, e), t);
|
|
56
|
+
}
|
|
57
|
+
function k(s2, e) {
|
|
58
|
+
let t = new Date(T(s2)), r = g(t, s2.tz), n = T(s2), i = T(r), a = n - i, o = new Date(t.getTime() + a), h = g(o, s2.tz);
|
|
59
|
+
if (D(h, s2)) {
|
|
60
|
+
let u = new Date(o.getTime() - 36e5), d = g(u, s2.tz);
|
|
61
|
+
return D(d, s2) ? u : o;
|
|
62
|
+
}
|
|
63
|
+
let l = new Date(o.getTime() + T(s2) - T(h)), y = g(l, s2.tz);
|
|
64
|
+
if (D(y, s2)) return l;
|
|
65
|
+
if (e) throw new Error("Invalid date passed to fromTZ()");
|
|
66
|
+
return o.getTime() > l.getTime() ? o : l;
|
|
67
|
+
}
|
|
68
|
+
function g(s2, e) {
|
|
69
|
+
let t, r;
|
|
70
|
+
try {
|
|
71
|
+
t = new Intl.DateTimeFormat("en-US", { timeZone: e, year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false }), r = t.formatToParts(s2);
|
|
72
|
+
} catch (i) {
|
|
73
|
+
let a = i instanceof Error ? i.message : String(i);
|
|
74
|
+
throw new RangeError(`toTZ: Invalid timezone '${e}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${a}`);
|
|
75
|
+
}
|
|
76
|
+
let n = { year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0 };
|
|
77
|
+
for (let i of r) (i.type === "year" || i.type === "month" || i.type === "day" || i.type === "hour" || i.type === "minute" || i.type === "second") && (n[i.type] = parseInt(i.value, 10));
|
|
78
|
+
if (isNaN(n.year) || isNaN(n.month) || isNaN(n.day) || isNaN(n.hour) || isNaN(n.minute) || isNaN(n.second)) throw new Error(`toTZ: Failed to parse all date components from timezone '${e}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify(n)}`);
|
|
79
|
+
return n.hour === 24 && (n.hour = 0), { y: n.year, m: n.month, d: n.day, h: n.hour, i: n.minute, s: n.second, tz: e };
|
|
80
|
+
}
|
|
81
|
+
function b(s2, e, t, r, n, i, a) {
|
|
82
|
+
return { y: s2, m: e, d: t, h: r, i: n, s: i, tz: a };
|
|
83
|
+
}
|
|
84
|
+
var O = [1, 2, 4, 8, 16];
|
|
85
|
+
var C = class {
|
|
86
|
+
pattern;
|
|
87
|
+
timezone;
|
|
88
|
+
mode;
|
|
89
|
+
alternativeWeekdays;
|
|
90
|
+
sloppyRanges;
|
|
91
|
+
second;
|
|
92
|
+
minute;
|
|
93
|
+
hour;
|
|
94
|
+
day;
|
|
95
|
+
month;
|
|
96
|
+
dayOfWeek;
|
|
97
|
+
year;
|
|
98
|
+
lastDayOfMonth;
|
|
99
|
+
lastWeekday;
|
|
100
|
+
nearestWeekdays;
|
|
101
|
+
starDOM;
|
|
102
|
+
starDOW;
|
|
103
|
+
starYear;
|
|
104
|
+
useAndLogic;
|
|
105
|
+
constructor(e, t, r) {
|
|
106
|
+
this.pattern = e, this.timezone = t, this.mode = r?.mode ?? "auto", this.alternativeWeekdays = r?.alternativeWeekdays ?? false, this.sloppyRanges = r?.sloppyRanges ?? false, this.second = Array(60).fill(0), this.minute = Array(60).fill(0), this.hour = Array(24).fill(0), this.day = Array(31).fill(0), this.month = Array(12).fill(0), this.dayOfWeek = Array(7).fill(0), this.year = Array(1e4).fill(0), this.lastDayOfMonth = false, this.lastWeekday = false, this.nearestWeekdays = Array(31).fill(0), this.starDOM = false, this.starDOW = false, this.starYear = false, this.useAndLogic = false, this.parse();
|
|
107
|
+
}
|
|
108
|
+
parse() {
|
|
109
|
+
if (!(typeof this.pattern == "string" || this.pattern instanceof String)) throw new TypeError("CronPattern: Pattern has to be of type string.");
|
|
110
|
+
this.pattern.indexOf("@") >= 0 && (this.pattern = this.handleNicknames(this.pattern).trim());
|
|
111
|
+
let e = this.pattern.match(/\S+/g) || [""], t = e.length;
|
|
112
|
+
if (e.length < 5 || e.length > 7) throw new TypeError("CronPattern: invalid configuration format ('" + this.pattern + "'), exactly five, six, or seven space separated parts are required.");
|
|
113
|
+
if (this.mode !== "auto") {
|
|
114
|
+
let n;
|
|
115
|
+
switch (this.mode) {
|
|
116
|
+
case "5-part":
|
|
117
|
+
n = 5;
|
|
118
|
+
break;
|
|
119
|
+
case "6-part":
|
|
120
|
+
n = 6;
|
|
121
|
+
break;
|
|
122
|
+
case "7-part":
|
|
123
|
+
n = 7;
|
|
124
|
+
break;
|
|
125
|
+
case "5-or-6-parts":
|
|
126
|
+
n = [5, 6];
|
|
127
|
+
break;
|
|
128
|
+
case "6-or-7-parts":
|
|
129
|
+
n = [6, 7];
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
n = 0;
|
|
133
|
+
}
|
|
134
|
+
if (!(Array.isArray(n) ? n.includes(t) : t === n)) {
|
|
135
|
+
let a = Array.isArray(n) ? n.join(" or ") : n.toString();
|
|
136
|
+
throw new TypeError(`CronPattern: mode '${this.mode}' requires exactly ${a} parts, but pattern '${this.pattern}' has ${t} parts.`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (e.length === 5 && e.unshift("0"), e.length === 6 && e.push("*"), e[3].toUpperCase() === "LW" ? (this.lastWeekday = true, e[3] = "") : e[3].toUpperCase().indexOf("L") >= 0 && (e[3] = e[3].replace(/L/gi, ""), this.lastDayOfMonth = true), e[3] == "*" && (this.starDOM = true), e[6] == "*" && (this.starYear = true), e[4].length >= 3 && (e[4] = this.replaceAlphaMonths(e[4])), e[5].length >= 3 && (e[5] = this.alternativeWeekdays ? this.replaceAlphaDaysQuartz(e[5]) : this.replaceAlphaDays(e[5])), e[5].startsWith("+") && (this.useAndLogic = true, e[5] = e[5].substring(1), e[5] === "")) throw new TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");
|
|
140
|
+
switch (e[5] == "*" && (this.starDOW = true), this.pattern.indexOf("?") >= 0 && (e[0] = e[0].replace(/\?/g, "*"), e[1] = e[1].replace(/\?/g, "*"), e[2] = e[2].replace(/\?/g, "*"), e[3] = e[3].replace(/\?/g, "*"), e[4] = e[4].replace(/\?/g, "*"), e[5] = e[5].replace(/\?/g, "*"), e[6] && (e[6] = e[6].replace(/\?/g, "*"))), this.mode) {
|
|
141
|
+
case "5-part":
|
|
142
|
+
e[0] = "0", e[6] = "*";
|
|
143
|
+
break;
|
|
144
|
+
case "6-part":
|
|
145
|
+
e[6] = "*";
|
|
146
|
+
break;
|
|
147
|
+
case "5-or-6-parts":
|
|
148
|
+
e[6] = "*";
|
|
149
|
+
break;
|
|
150
|
+
case "6-or-7-parts":
|
|
151
|
+
break;
|
|
152
|
+
case "7-part":
|
|
153
|
+
case "auto":
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
this.throwAtIllegalCharacters(e), this.partToArray("second", e[0], 0, 1), this.partToArray("minute", e[1], 0, 1), this.partToArray("hour", e[2], 0, 1), this.partToArray("day", e[3], -1, 1), this.partToArray("month", e[4], -1, 1);
|
|
157
|
+
let r = this.alternativeWeekdays ? -1 : 0;
|
|
158
|
+
this.partToArray("dayOfWeek", e[5], r, 63), this.partToArray("year", e[6], 0, 1), !this.alternativeWeekdays && this.dayOfWeek[7] && (this.dayOfWeek[0] = this.dayOfWeek[7]);
|
|
159
|
+
}
|
|
160
|
+
partToArray(e, t, r, n) {
|
|
161
|
+
let i = this[e], a = e === "day" && this.lastDayOfMonth, o = e === "day" && this.lastWeekday;
|
|
162
|
+
if (t === "" && !a && !o) throw new TypeError("CronPattern: configuration entry " + e + " (" + t + ") is empty, check for trailing spaces.");
|
|
163
|
+
if (t === "*") return i.fill(n);
|
|
164
|
+
let h = t.split(",");
|
|
165
|
+
if (h.length > 1) for (let l = 0; l < h.length; l++) this.partToArray(e, h[l], r, n);
|
|
166
|
+
else t.indexOf("-") !== -1 && t.indexOf("/") !== -1 ? this.handleRangeWithStepping(t, e, r, n) : t.indexOf("-") !== -1 ? this.handleRange(t, e, r, n) : t.indexOf("/") !== -1 ? this.handleStepping(t, e, r, n) : t !== "" && this.handleNumber(t, e, r, n);
|
|
167
|
+
}
|
|
168
|
+
throwAtIllegalCharacters(e) {
|
|
169
|
+
for (let t = 0; t < e.length; t++) if ((t === 3 ? /[^/*0-9,\-WwLl]+/ : t === 5 ? /[^/*0-9,\-#Ll]+/ : /[^/*0-9,\-]+/).test(e[t])) throw new TypeError("CronPattern: configuration entry " + t + " (" + e[t] + ") contains illegal characters.");
|
|
170
|
+
}
|
|
171
|
+
handleNumber(e, t, r, n) {
|
|
172
|
+
let i = this.extractNth(e, t), a = e.toUpperCase().includes("W");
|
|
173
|
+
if (t !== "day" && a) throw new TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");
|
|
174
|
+
a && (t = "nearestWeekdays");
|
|
175
|
+
let o = parseInt(i[0], 10) + r;
|
|
176
|
+
if (isNaN(o)) throw new TypeError("CronPattern: " + t + " is not a number: '" + e + "'");
|
|
177
|
+
this.setPart(t, o, i[1] || n);
|
|
178
|
+
}
|
|
179
|
+
setPart(e, t, r) {
|
|
180
|
+
if (!Object.prototype.hasOwnProperty.call(this, e)) throw new TypeError("CronPattern: Invalid part specified: " + e);
|
|
181
|
+
if (e === "dayOfWeek") {
|
|
182
|
+
if (t === 7 && (t = 0), t < 0 || t > 6) throw new RangeError("CronPattern: Invalid value for dayOfWeek: " + t);
|
|
183
|
+
this.setNthWeekdayOfMonth(t, r);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (e === "second" || e === "minute") {
|
|
187
|
+
if (t < 0 || t >= 60) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
|
|
188
|
+
} else if (e === "hour") {
|
|
189
|
+
if (t < 0 || t >= 24) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
|
|
190
|
+
} else if (e === "day" || e === "nearestWeekdays") {
|
|
191
|
+
if (t < 0 || t >= 31) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
|
|
192
|
+
} else if (e === "month") {
|
|
193
|
+
if (t < 0 || t >= 12) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t);
|
|
194
|
+
} else if (e === "year" && (t < 1 || t >= 1e4)) throw new RangeError("CronPattern: Invalid value for " + e + ": " + t + " (supported range: 1-9999)");
|
|
195
|
+
this[e][t] = r;
|
|
196
|
+
}
|
|
197
|
+
validateNotNaN(e, t) {
|
|
198
|
+
if (isNaN(e)) throw new TypeError(t);
|
|
199
|
+
}
|
|
200
|
+
validateRange(e, t, r, n, i) {
|
|
201
|
+
if (e > t) throw new TypeError("CronPattern: From value is larger than to value: '" + i + "'");
|
|
202
|
+
if (r !== void 0) {
|
|
203
|
+
if (r === 0) throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");
|
|
204
|
+
if (r > this[n].length) throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part (" + this[n].length + ")");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
handleRangeWithStepping(e, t, r, n) {
|
|
208
|
+
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");
|
|
209
|
+
let i = this.extractNth(e, t), a = i[0].match(/^(\d+)-(\d+)\/(\d+)$/);
|
|
210
|
+
if (a === null) throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '" + e + "'");
|
|
211
|
+
let [, o, h, l] = a, y = parseInt(o, 10) + r, u = parseInt(h, 10) + r, d = parseInt(l, 10);
|
|
212
|
+
this.validateNotNaN(y, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(u, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateNotNaN(d, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(y, u, d, t, e);
|
|
213
|
+
for (let c = y; c <= u; c += d) this.setPart(t, c, i[1] || n);
|
|
214
|
+
}
|
|
215
|
+
extractNth(e, t) {
|
|
216
|
+
let r = e, n;
|
|
217
|
+
if (r.includes("#")) {
|
|
218
|
+
if (t !== "dayOfWeek") throw new Error("CronPattern: nth (#) only allowed in day-of-week field");
|
|
219
|
+
n = r.split("#")[1], r = r.split("#")[0];
|
|
220
|
+
} else if (r.toUpperCase().endsWith("L")) {
|
|
221
|
+
if (t !== "dayOfWeek") throw new Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");
|
|
222
|
+
n = "L", r = r.slice(0, -1);
|
|
223
|
+
}
|
|
224
|
+
return [r, n];
|
|
225
|
+
}
|
|
226
|
+
handleRange(e, t, r, n) {
|
|
227
|
+
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in a range.");
|
|
228
|
+
let i = this.extractNth(e, t), a = i[0].split("-");
|
|
229
|
+
if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal range: '" + e + "'");
|
|
230
|
+
let o = parseInt(a[0], 10) + r, h = parseInt(a[1], 10) + r;
|
|
231
|
+
this.validateNotNaN(o, "CronPattern: Syntax error, illegal lower range (NaN)"), this.validateNotNaN(h, "CronPattern: Syntax error, illegal upper range (NaN)"), this.validateRange(o, h, void 0, t, e);
|
|
232
|
+
for (let l = o; l <= h; l++) this.setPart(t, l, i[1] || n);
|
|
233
|
+
}
|
|
234
|
+
handleStepping(e, t, r, n) {
|
|
235
|
+
if (e.toUpperCase().includes("W")) throw new TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");
|
|
236
|
+
let i = this.extractNth(e, t), a = i[0].split("/");
|
|
237
|
+
if (a.length !== 2) throw new TypeError("CronPattern: Syntax error, illegal stepping: '" + e + "'");
|
|
238
|
+
if (this.sloppyRanges) a[0] === "" && (a[0] = "*");
|
|
239
|
+
else {
|
|
240
|
+
if (a[0] === "") throw new TypeError("CronPattern: Syntax error, stepping with missing prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
|
|
241
|
+
if (a[0] !== "*") throw new TypeError("CronPattern: Syntax error, stepping with numeric prefix ('" + e + "') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");
|
|
242
|
+
}
|
|
243
|
+
let o = 0;
|
|
244
|
+
a[0] !== "*" && (o = parseInt(a[0], 10) + r);
|
|
245
|
+
let h = parseInt(a[1], 10);
|
|
246
|
+
this.validateNotNaN(h, "CronPattern: Syntax error, illegal stepping: (NaN)"), this.validateRange(0, this[t].length - 1, h, t, e);
|
|
247
|
+
for (let l = o; l < this[t].length; l += h) this.setPart(t, l, i[1] || n);
|
|
248
|
+
}
|
|
249
|
+
replaceAlphaDays(e) {
|
|
250
|
+
return e.replace(/-sun/gi, "-7").replace(/sun/gi, "0").replace(/mon/gi, "1").replace(/tue/gi, "2").replace(/wed/gi, "3").replace(/thu/gi, "4").replace(/fri/gi, "5").replace(/sat/gi, "6");
|
|
251
|
+
}
|
|
252
|
+
replaceAlphaDaysQuartz(e) {
|
|
253
|
+
return e.replace(/sun/gi, "1").replace(/mon/gi, "2").replace(/tue/gi, "3").replace(/wed/gi, "4").replace(/thu/gi, "5").replace(/fri/gi, "6").replace(/sat/gi, "7");
|
|
254
|
+
}
|
|
255
|
+
replaceAlphaMonths(e) {
|
|
256
|
+
return e.replace(/jan/gi, "1").replace(/feb/gi, "2").replace(/mar/gi, "3").replace(/apr/gi, "4").replace(/may/gi, "5").replace(/jun/gi, "6").replace(/jul/gi, "7").replace(/aug/gi, "8").replace(/sep/gi, "9").replace(/oct/gi, "10").replace(/nov/gi, "11").replace(/dec/gi, "12");
|
|
257
|
+
}
|
|
258
|
+
handleNicknames(e) {
|
|
259
|
+
let t = e.trim().toLowerCase();
|
|
260
|
+
if (t === "@yearly" || t === "@annually") return "0 0 1 1 *";
|
|
261
|
+
if (t === "@monthly") return "0 0 1 * *";
|
|
262
|
+
if (t === "@weekly") return "0 0 * * 0";
|
|
263
|
+
if (t === "@daily" || t === "@midnight") return "0 0 * * *";
|
|
264
|
+
if (t === "@hourly") return "0 * * * *";
|
|
265
|
+
if (t === "@reboot") throw new TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");
|
|
266
|
+
return e;
|
|
267
|
+
}
|
|
268
|
+
setNthWeekdayOfMonth(e, t) {
|
|
269
|
+
if (typeof t != "number" && t.toUpperCase() === "L") this.dayOfWeek[e] = this.dayOfWeek[e] | 32;
|
|
270
|
+
else if (t === 63) this.dayOfWeek[e] = 63;
|
|
271
|
+
else if (t < 6 && t > 0) this.dayOfWeek[e] = this.dayOfWeek[e] | O[t - 1];
|
|
272
|
+
else throw new TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${t}, Type: ${typeof t}`);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
var P = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
276
|
+
var f = [["month", "year", 0], ["day", "month", -1], ["hour", "day", 0], ["minute", "hour", 0], ["second", "minute", 0]];
|
|
277
|
+
var m = class s {
|
|
278
|
+
tz;
|
|
279
|
+
ms;
|
|
280
|
+
second;
|
|
281
|
+
minute;
|
|
282
|
+
hour;
|
|
283
|
+
day;
|
|
284
|
+
month;
|
|
285
|
+
year;
|
|
286
|
+
constructor(e, t) {
|
|
287
|
+
if (this.tz = t, e && e instanceof Date) if (!isNaN(e)) this.fromDate(e);
|
|
288
|
+
else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");
|
|
289
|
+
else if (e == null) this.fromDate(/* @__PURE__ */ new Date());
|
|
290
|
+
else if (e && typeof e == "string") this.fromString(e);
|
|
291
|
+
else if (e instanceof s) this.fromCronDate(e);
|
|
292
|
+
else throw new TypeError("CronDate: Invalid type (" + typeof e + ") passed to CronDate constructor");
|
|
293
|
+
}
|
|
294
|
+
getLastDayOfMonth(e, t) {
|
|
295
|
+
return t !== 1 ? P[t] : new Date(Date.UTC(e, t + 1, 0)).getUTCDate();
|
|
296
|
+
}
|
|
297
|
+
getLastWeekday(e, t) {
|
|
298
|
+
let r = this.getLastDayOfMonth(e, t), i = new Date(Date.UTC(e, t, r)).getUTCDay();
|
|
299
|
+
return i === 0 ? r - 2 : i === 6 ? r - 1 : r;
|
|
300
|
+
}
|
|
301
|
+
getNearestWeekday(e, t, r) {
|
|
302
|
+
let n = this.getLastDayOfMonth(e, t);
|
|
303
|
+
if (r > n) return -1;
|
|
304
|
+
let a = new Date(Date.UTC(e, t, r)).getUTCDay();
|
|
305
|
+
return a === 0 ? r === n ? r - 2 : r + 1 : a === 6 ? r === 1 ? r + 2 : r - 1 : r;
|
|
306
|
+
}
|
|
307
|
+
isNthWeekdayOfMonth(e, t, r, n) {
|
|
308
|
+
let a = new Date(Date.UTC(e, t, r)).getUTCDay(), o = 0;
|
|
309
|
+
for (let h = 1; h <= r; h++) new Date(Date.UTC(e, t, h)).getUTCDay() === a && o++;
|
|
310
|
+
if (n & 63 && O[o - 1] & n) return true;
|
|
311
|
+
if (n & 32) {
|
|
312
|
+
let h = this.getLastDayOfMonth(e, t);
|
|
313
|
+
for (let l = r + 1; l <= h; l++) if (new Date(Date.UTC(e, t, l)).getUTCDay() === a) return false;
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
fromDate(e) {
|
|
319
|
+
if (this.tz !== void 0) if (typeof this.tz == "number") this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes() + this.tz, this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), this.apply();
|
|
320
|
+
else try {
|
|
321
|
+
let t = g(e, this.tz);
|
|
322
|
+
this.ms = e.getMilliseconds(), this.second = t.s, this.minute = t.i, this.hour = t.h, this.day = t.d, this.month = t.m - 1, this.year = t.y;
|
|
323
|
+
} catch (t) {
|
|
324
|
+
let r = t instanceof Error ? t.message : String(t);
|
|
325
|
+
throw new TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${r}`);
|
|
326
|
+
}
|
|
327
|
+
else this.ms = e.getMilliseconds(), this.second = e.getSeconds(), this.minute = e.getMinutes(), this.hour = e.getHours(), this.day = e.getDate(), this.month = e.getMonth(), this.year = e.getFullYear();
|
|
328
|
+
}
|
|
329
|
+
fromCronDate(e) {
|
|
330
|
+
this.tz = e.tz, this.year = e.year, this.month = e.month, this.day = e.day, this.hour = e.hour, this.minute = e.minute, this.second = e.second, this.ms = e.ms;
|
|
331
|
+
}
|
|
332
|
+
apply() {
|
|
333
|
+
if (this.month > 11 || this.month < 0 || this.day > P[this.month] || this.day < 1 || this.hour > 59 || this.minute > 59 || this.second > 59 || this.hour < 0 || this.minute < 0 || this.second < 0) {
|
|
334
|
+
let e = new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms));
|
|
335
|
+
return this.ms = e.getUTCMilliseconds(), this.second = e.getUTCSeconds(), this.minute = e.getUTCMinutes(), this.hour = e.getUTCHours(), this.day = e.getUTCDate(), this.month = e.getUTCMonth(), this.year = e.getUTCFullYear(), true;
|
|
336
|
+
} else return false;
|
|
337
|
+
}
|
|
338
|
+
fromString(e) {
|
|
339
|
+
if (typeof this.tz == "number") {
|
|
340
|
+
let t = v(e);
|
|
341
|
+
this.ms = t.getUTCMilliseconds(), this.second = t.getUTCSeconds(), this.minute = t.getUTCMinutes(), this.hour = t.getUTCHours(), this.day = t.getUTCDate(), this.month = t.getUTCMonth(), this.year = t.getUTCFullYear(), this.apply();
|
|
342
|
+
} else return this.fromDate(v(e, this.tz));
|
|
343
|
+
}
|
|
344
|
+
findNext(e, t, r, n) {
|
|
345
|
+
return this._findMatch(e, t, r, n, 1);
|
|
346
|
+
}
|
|
347
|
+
_findMatch(e, t, r, n, i) {
|
|
348
|
+
let a = this[t], o;
|
|
349
|
+
r.lastDayOfMonth && (o = this.getLastDayOfMonth(this.year, this.month));
|
|
350
|
+
let h = !r.starDOW && t == "day" ? new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay() : void 0, l = this[t] + n, y = i === 1 ? (u) => u < r[t].length : (u) => u >= 0;
|
|
351
|
+
for (let u = l; y(u); u += i) {
|
|
352
|
+
let d = r[t][u];
|
|
353
|
+
if (t === "day" && !d) {
|
|
354
|
+
for (let c = 0; c < r.nearestWeekdays.length; c++) if (r.nearestWeekdays[c]) {
|
|
355
|
+
let M = this.getNearestWeekday(this.year, this.month, c - n);
|
|
356
|
+
if (M === -1) continue;
|
|
357
|
+
if (M === u - n) {
|
|
358
|
+
d = 1;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (t === "day" && r.lastWeekday) {
|
|
364
|
+
let c = this.getLastWeekday(this.year, this.month);
|
|
365
|
+
u - n === c && (d = 1);
|
|
366
|
+
}
|
|
367
|
+
if (t === "day" && r.lastDayOfMonth && u - n == o && (d = 1), t === "day" && !r.starDOW) {
|
|
368
|
+
let c = r.dayOfWeek[(h + (u - n - 1)) % 7];
|
|
369
|
+
if (c && c & 63) c = this.isNthWeekdayOfMonth(this.year, this.month, u - n, c) ? 1 : 0;
|
|
370
|
+
else if (c) throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${c}`);
|
|
371
|
+
r.useAndLogic ? d = d && c : !e.domAndDow && !r.starDOM ? d = d || c : d = d && c;
|
|
372
|
+
}
|
|
373
|
+
if (d) return this[t] = u - n, a !== this[t] ? 2 : 1;
|
|
374
|
+
}
|
|
375
|
+
return 3;
|
|
376
|
+
}
|
|
377
|
+
recurse(e, t, r) {
|
|
378
|
+
if (r === 0 && !e.starYear) {
|
|
379
|
+
if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
|
|
380
|
+
let i = -1;
|
|
381
|
+
for (let a = this.year + 1; a < e.year.length && a < 1e4; a++) if (e.year[a] === 1) {
|
|
382
|
+
i = a;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
if (i === -1) return null;
|
|
386
|
+
this.year = i, this.month = 0, this.day = 1, this.hour = 0, this.minute = 0, this.second = 0, this.ms = 0;
|
|
387
|
+
}
|
|
388
|
+
if (this.year >= 1e4) return null;
|
|
389
|
+
}
|
|
390
|
+
let n = this.findNext(t, f[r][0], e, f[r][2]);
|
|
391
|
+
if (n > 1) {
|
|
392
|
+
let i = r + 1;
|
|
393
|
+
for (; i < f.length; ) this[f[i][0]] = -f[i][2], i++;
|
|
394
|
+
if (n === 3) {
|
|
395
|
+
if (this[f[r][1]]++, this[f[r][0]] = -f[r][2], this.apply(), r === 0 && !e.starYear) {
|
|
396
|
+
for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0 && this.year < 1e4; ) this.year++;
|
|
397
|
+
if (this.year >= 1e4 || this.year >= e.year.length) return null;
|
|
398
|
+
}
|
|
399
|
+
return this.recurse(e, t, 0);
|
|
400
|
+
} else if (this.apply()) return this.recurse(e, t, r - 1);
|
|
401
|
+
}
|
|
402
|
+
return r += 1, r >= f.length ? this : (e.starYear ? this.year >= 3e3 : this.year >= 1e4) ? null : this.recurse(e, t, r);
|
|
403
|
+
}
|
|
404
|
+
increment(e, t, r) {
|
|
405
|
+
return this.second += t.interval !== void 0 && t.interval > 1 && r ? t.interval : 1, this.ms = 0, this.apply(), this.recurse(e, t, 0);
|
|
406
|
+
}
|
|
407
|
+
decrement(e, t) {
|
|
408
|
+
return this.second -= t.interval !== void 0 && t.interval > 1 ? t.interval : 1, this.ms = 0, this.apply(), this.recurseBackward(e, t, 0, 0);
|
|
409
|
+
}
|
|
410
|
+
recurseBackward(e, t, r, n = 0) {
|
|
411
|
+
if (n > 1e4) return null;
|
|
412
|
+
if (r === 0 && !e.starYear) {
|
|
413
|
+
if (this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0) {
|
|
414
|
+
let a = -1;
|
|
415
|
+
for (let o = this.year - 1; o >= 0; o--) if (e.year[o] === 1) {
|
|
416
|
+
a = o;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
if (a === -1) return null;
|
|
420
|
+
this.year = a, this.month = 11, this.day = 31, this.hour = 23, this.minute = 59, this.second = 59, this.ms = 0;
|
|
421
|
+
}
|
|
422
|
+
if (this.year < 0) return null;
|
|
423
|
+
}
|
|
424
|
+
let i = this.findPrevious(t, f[r][0], e, f[r][2]);
|
|
425
|
+
if (i > 1) {
|
|
426
|
+
let a = r + 1;
|
|
427
|
+
for (; a < f.length; ) {
|
|
428
|
+
let o = f[a][0], h = f[a][2], l = this.getMaxPatternValue(o, e, h);
|
|
429
|
+
this[o] = l, a++;
|
|
430
|
+
}
|
|
431
|
+
if (i === 3) {
|
|
432
|
+
if (this[f[r][1]]--, r === 0) {
|
|
433
|
+
let y = this.getLastDayOfMonth(this.year, this.month);
|
|
434
|
+
this.day > y && (this.day = y);
|
|
435
|
+
}
|
|
436
|
+
if (r === 1) if (this.day <= 0) this.day = 1;
|
|
437
|
+
else {
|
|
438
|
+
let y = this.year, u = this.month;
|
|
439
|
+
for (; u < 0; ) u += 12, y--;
|
|
440
|
+
for (; u > 11; ) u -= 12, y++;
|
|
441
|
+
let d = u !== 1 ? P[u] : new Date(Date.UTC(y, u + 1, 0)).getUTCDate();
|
|
442
|
+
this.day > d && (this.day = d);
|
|
443
|
+
}
|
|
444
|
+
this.apply();
|
|
445
|
+
let o = f[r][0], h = f[r][2], l = this.getMaxPatternValue(o, e, h);
|
|
446
|
+
if (o === "day") {
|
|
447
|
+
let y = this.getLastDayOfMonth(this.year, this.month);
|
|
448
|
+
this[o] = Math.min(l, y);
|
|
449
|
+
} else this[o] = l;
|
|
450
|
+
if (this.apply(), r === 0) {
|
|
451
|
+
let y = f[1][2], u = this.getMaxPatternValue("day", e, y), d = this.getLastDayOfMonth(this.year, this.month), c = Math.min(u, d);
|
|
452
|
+
c !== this.day && (this.day = c, this.hour = this.getMaxPatternValue("hour", e, f[2][2]), this.minute = this.getMaxPatternValue("minute", e, f[3][2]), this.second = this.getMaxPatternValue("second", e, f[4][2]));
|
|
453
|
+
}
|
|
454
|
+
if (r === 0 && !e.starYear) {
|
|
455
|
+
for (; this.year >= 0 && this.year < e.year.length && e.year[this.year] === 0; ) this.year--;
|
|
456
|
+
if (this.year < 0) return null;
|
|
457
|
+
}
|
|
458
|
+
return this.recurseBackward(e, t, 0, n + 1);
|
|
459
|
+
} else if (this.apply()) return this.recurseBackward(e, t, r - 1, n + 1);
|
|
460
|
+
}
|
|
461
|
+
return r += 1, r >= f.length ? this : this.year < 0 ? null : this.recurseBackward(e, t, r, n + 1);
|
|
462
|
+
}
|
|
463
|
+
getMaxPatternValue(e, t, r) {
|
|
464
|
+
if (e === "day" && t.lastDayOfMonth) return this.getLastDayOfMonth(this.year, this.month);
|
|
465
|
+
if (e === "day" && !t.starDOW) return this.getLastDayOfMonth(this.year, this.month);
|
|
466
|
+
for (let n = t[e].length - 1; n >= 0; n--) if (t[e][n]) return n - r;
|
|
467
|
+
return t[e].length - 1 - r;
|
|
468
|
+
}
|
|
469
|
+
findPrevious(e, t, r, n) {
|
|
470
|
+
return this._findMatch(e, t, r, n, -1);
|
|
471
|
+
}
|
|
472
|
+
getDate(e) {
|
|
473
|
+
return e || this.tz === void 0 ? new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms) : typeof this.tz == "number" ? new Date(Date.UTC(this.year, this.month, this.day, this.hour, this.minute - this.tz, this.second, this.ms)) : k(b(this.year, this.month + 1, this.day, this.hour, this.minute, this.second, this.tz), false);
|
|
474
|
+
}
|
|
475
|
+
getTime() {
|
|
476
|
+
return this.getDate(false).getTime();
|
|
477
|
+
}
|
|
478
|
+
match(e, t) {
|
|
479
|
+
if (!e.starYear && (this.year < 0 || this.year >= e.year.length || e.year[this.year] === 0)) return false;
|
|
480
|
+
for (let r = 0; r < f.length; r++) {
|
|
481
|
+
let n = f[r][0], i = f[r][2], a = this[n];
|
|
482
|
+
if (a + i < 0 || a + i >= e[n].length) return false;
|
|
483
|
+
let o = e[n][a + i];
|
|
484
|
+
if (n === "day") {
|
|
485
|
+
if (!o) {
|
|
486
|
+
for (let h = 0; h < e.nearestWeekdays.length; h++) if (e.nearestWeekdays[h]) {
|
|
487
|
+
let l = this.getNearestWeekday(this.year, this.month, h - i);
|
|
488
|
+
if (l !== -1 && l === a) {
|
|
489
|
+
o = 1;
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (e.lastWeekday) {
|
|
495
|
+
let h = this.getLastWeekday(this.year, this.month);
|
|
496
|
+
a === h && (o = 1);
|
|
497
|
+
}
|
|
498
|
+
if (e.lastDayOfMonth) {
|
|
499
|
+
let h = this.getLastDayOfMonth(this.year, this.month);
|
|
500
|
+
a === h && (o = 1);
|
|
501
|
+
}
|
|
502
|
+
if (!e.starDOW) {
|
|
503
|
+
let h = new Date(Date.UTC(this.year, this.month, 1, 0, 0, 0, 0)).getUTCDay(), l = e.dayOfWeek[(h + (a - 1)) % 7];
|
|
504
|
+
l && l & 63 && (l = this.isNthWeekdayOfMonth(this.year, this.month, a, l) ? 1 : 0), e.useAndLogic ? o = o && l : !t.domAndDow && !e.starDOM ? o = o || l : o = o && l;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (!o) return false;
|
|
508
|
+
}
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
function R(s2) {
|
|
513
|
+
if (s2 === void 0 && (s2 = {}), delete s2.name, s2.legacyMode !== void 0 && s2.domAndDow === void 0 ? s2.domAndDow = !s2.legacyMode : s2.domAndDow === void 0 && (s2.domAndDow = false), s2.legacyMode = !s2.domAndDow, s2.paused = s2.paused === void 0 ? false : s2.paused, s2.maxRuns = s2.maxRuns === void 0 ? 1 / 0 : s2.maxRuns, s2.catch = s2.catch === void 0 ? false : s2.catch, s2.interval = s2.interval === void 0 ? 0 : parseInt(s2.interval.toString(), 10), s2.utcOffset = s2.utcOffset === void 0 ? void 0 : parseInt(s2.utcOffset.toString(), 10), s2.dayOffset = s2.dayOffset === void 0 ? 0 : parseInt(s2.dayOffset.toString(), 10), s2.unref = s2.unref === void 0 ? false : s2.unref, s2.mode = s2.mode === void 0 ? "auto" : s2.mode, s2.alternativeWeekdays = s2.alternativeWeekdays === void 0 ? false : s2.alternativeWeekdays, s2.sloppyRanges = s2.sloppyRanges === void 0 ? false : s2.sloppyRanges, !["auto", "5-part", "6-part", "7-part", "5-or-6-parts", "6-or-7-parts"].includes(s2.mode)) throw new Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");
|
|
514
|
+
if (s2.startAt && (s2.startAt = new m(s2.startAt, s2.timezone)), s2.stopAt && (s2.stopAt = new m(s2.stopAt, s2.timezone)), s2.interval !== null) {
|
|
515
|
+
if (isNaN(s2.interval)) throw new Error("CronOptions: Supplied value for interval is not a number");
|
|
516
|
+
if (s2.interval < 0) throw new Error("CronOptions: Supplied value for interval can not be negative");
|
|
517
|
+
}
|
|
518
|
+
if (s2.utcOffset !== void 0) {
|
|
519
|
+
if (isNaN(s2.utcOffset)) throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");
|
|
520
|
+
if (s2.utcOffset < -870 || s2.utcOffset > 870) throw new Error("CronOptions: utcOffset out of bounds.");
|
|
521
|
+
if (s2.utcOffset !== void 0 && s2.timezone) throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.");
|
|
522
|
+
}
|
|
523
|
+
if (s2.unref !== true && s2.unref !== false) throw new Error("CronOptions: Unref should be either true, false or undefined(false).");
|
|
524
|
+
if (s2.dayOffset !== void 0 && s2.dayOffset !== 0 && isNaN(s2.dayOffset)) throw new Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");
|
|
525
|
+
return s2;
|
|
526
|
+
}
|
|
527
|
+
function p(s2) {
|
|
528
|
+
return Object.prototype.toString.call(s2) === "[object Function]" || typeof s2 == "function" || s2 instanceof Function;
|
|
529
|
+
}
|
|
530
|
+
function _(s2) {
|
|
531
|
+
return p(s2);
|
|
532
|
+
}
|
|
533
|
+
function x(s2) {
|
|
534
|
+
typeof Deno < "u" && typeof Deno.unrefTimer < "u" ? Deno.unrefTimer(s2) : s2 && typeof s2.unref < "u" && s2.unref();
|
|
535
|
+
}
|
|
536
|
+
var W = 30 * 1e3;
|
|
537
|
+
var w = [];
|
|
538
|
+
var E = class {
|
|
539
|
+
name;
|
|
540
|
+
options;
|
|
541
|
+
_states;
|
|
542
|
+
fn;
|
|
543
|
+
getTz() {
|
|
544
|
+
return this.options.timezone || this.options.utcOffset;
|
|
545
|
+
}
|
|
546
|
+
applyDayOffset(e) {
|
|
547
|
+
if (this.options.dayOffset !== void 0 && this.options.dayOffset !== 0) {
|
|
548
|
+
let t = this.options.dayOffset * 24 * 60 * 60 * 1e3;
|
|
549
|
+
return new Date(e.getTime() + t);
|
|
550
|
+
}
|
|
551
|
+
return e;
|
|
552
|
+
}
|
|
553
|
+
constructor(e, t, r) {
|
|
554
|
+
let n, i;
|
|
555
|
+
if (p(t)) i = t;
|
|
556
|
+
else if (typeof t == "object") n = t;
|
|
557
|
+
else if (t !== void 0) throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");
|
|
558
|
+
if (p(r)) i = r;
|
|
559
|
+
else if (typeof r == "object") n = r;
|
|
560
|
+
else if (r !== void 0) throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");
|
|
561
|
+
if (this.name = n?.name, this.options = R(n), this._states = { kill: false, blocking: false, previousRun: void 0, currentRun: void 0, once: void 0, currentTimeout: void 0, maxRuns: n ? n.maxRuns : void 0, paused: n ? n.paused : false, pattern: new C("* * * * *", void 0, { mode: "auto" }) }, e && (e instanceof Date || typeof e == "string" && e.indexOf(":") > 0) ? this._states.once = new m(e, this.getTz()) : this._states.pattern = new C(e, this.options.timezone, { mode: this.options.mode, alternativeWeekdays: this.options.alternativeWeekdays, sloppyRanges: this.options.sloppyRanges }), this.name) {
|
|
562
|
+
if (w.find((o) => o.name === this.name)) throw new Error("Cron: Tried to initialize new named job '" + this.name + "', but name already taken.");
|
|
563
|
+
w.push(this);
|
|
564
|
+
}
|
|
565
|
+
return i !== void 0 && _(i) && (this.fn = i, this.schedule()), this;
|
|
566
|
+
}
|
|
567
|
+
nextRun(e) {
|
|
568
|
+
let t = this._next(e);
|
|
569
|
+
return t ? this.applyDayOffset(t.getDate(false)) : null;
|
|
570
|
+
}
|
|
571
|
+
nextRuns(e, t) {
|
|
572
|
+
this._states.maxRuns !== void 0 && e > this._states.maxRuns && (e = this._states.maxRuns);
|
|
573
|
+
let r = t || this._states.currentRun || void 0;
|
|
574
|
+
return this._enumerateRuns(e, r, "next");
|
|
575
|
+
}
|
|
576
|
+
previousRuns(e, t) {
|
|
577
|
+
return this._enumerateRuns(e, t || void 0, "previous");
|
|
578
|
+
}
|
|
579
|
+
_enumerateRuns(e, t, r) {
|
|
580
|
+
let n = [], i = t ? new m(t, this.getTz()) : null, a = r === "next" ? this._next : this._previous;
|
|
581
|
+
for (; e--; ) {
|
|
582
|
+
let o = a.call(this, i);
|
|
583
|
+
if (!o) break;
|
|
584
|
+
let h = o.getDate(false);
|
|
585
|
+
n.push(this.applyDayOffset(h)), i = o;
|
|
586
|
+
}
|
|
587
|
+
return n;
|
|
588
|
+
}
|
|
589
|
+
match(e) {
|
|
590
|
+
if (this._states.once) {
|
|
591
|
+
let r = new m(e, this.getTz());
|
|
592
|
+
r.ms = 0;
|
|
593
|
+
let n = new m(this._states.once, this.getTz());
|
|
594
|
+
return n.ms = 0, r.getTime() === n.getTime();
|
|
595
|
+
}
|
|
596
|
+
let t = new m(e, this.getTz());
|
|
597
|
+
return t.ms = 0, t.match(this._states.pattern, this.options);
|
|
598
|
+
}
|
|
599
|
+
getPattern() {
|
|
600
|
+
if (!this._states.once) return this._states.pattern ? this._states.pattern.pattern : void 0;
|
|
601
|
+
}
|
|
602
|
+
getOnce() {
|
|
603
|
+
return this._states.once ? this._states.once.getDate() : null;
|
|
604
|
+
}
|
|
605
|
+
isRunning() {
|
|
606
|
+
let e = this.nextRun(this._states.currentRun), t = !this._states.paused, r = this.fn !== void 0, n = !this._states.kill;
|
|
607
|
+
return t && r && n && e !== null;
|
|
608
|
+
}
|
|
609
|
+
isStopped() {
|
|
610
|
+
return this._states.kill;
|
|
611
|
+
}
|
|
612
|
+
isBusy() {
|
|
613
|
+
return this._states.blocking;
|
|
614
|
+
}
|
|
615
|
+
currentRun() {
|
|
616
|
+
return this._states.currentRun ? this._states.currentRun.getDate() : null;
|
|
617
|
+
}
|
|
618
|
+
previousRun() {
|
|
619
|
+
return this._states.previousRun ? this._states.previousRun.getDate() : null;
|
|
620
|
+
}
|
|
621
|
+
msToNext(e) {
|
|
622
|
+
let t = this._next(e);
|
|
623
|
+
return t ? e instanceof m || e instanceof Date ? t.getTime() - e.getTime() : t.getTime() - new m(e).getTime() : null;
|
|
624
|
+
}
|
|
625
|
+
stop() {
|
|
626
|
+
this._states.kill = true, this._states.currentTimeout && clearTimeout(this._states.currentTimeout);
|
|
627
|
+
let e = w.indexOf(this);
|
|
628
|
+
e >= 0 && w.splice(e, 1);
|
|
629
|
+
}
|
|
630
|
+
pause() {
|
|
631
|
+
return this._states.paused = true, !this._states.kill;
|
|
632
|
+
}
|
|
633
|
+
resume() {
|
|
634
|
+
return this._states.paused = false, !this._states.kill;
|
|
635
|
+
}
|
|
636
|
+
schedule(e) {
|
|
637
|
+
if (e && this.fn) throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");
|
|
638
|
+
e && (this.fn = e);
|
|
639
|
+
let t = this.msToNext(), r = this.nextRun(this._states.currentRun);
|
|
640
|
+
return t == null || isNaN(t) || r === null ? this : (t > W && (t = W), this._states.currentTimeout = setTimeout(() => this._checkTrigger(r), t), this._states.currentTimeout && this.options.unref && x(this._states.currentTimeout), this);
|
|
641
|
+
}
|
|
642
|
+
async _trigger(e) {
|
|
643
|
+
this._states.blocking = true, this._states.currentRun = new m(void 0, this.getTz());
|
|
644
|
+
try {
|
|
645
|
+
if (this.options.catch) try {
|
|
646
|
+
this.fn !== void 0 && await this.fn(this, this.options.context);
|
|
647
|
+
} catch (t) {
|
|
648
|
+
if (p(this.options.catch)) try {
|
|
649
|
+
this.options.catch(t, this);
|
|
650
|
+
} catch {
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
else this.fn !== void 0 && await this.fn(this, this.options.context);
|
|
654
|
+
} finally {
|
|
655
|
+
this._states.previousRun = new m(e, this.getTz()), this._states.blocking = false;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
async trigger() {
|
|
659
|
+
await this._trigger();
|
|
660
|
+
}
|
|
661
|
+
runsLeft() {
|
|
662
|
+
return this._states.maxRuns;
|
|
663
|
+
}
|
|
664
|
+
_checkTrigger(e) {
|
|
665
|
+
let t = /* @__PURE__ */ new Date(), r = !this._states.paused && t.getTime() >= e.getTime(), n = this._states.blocking && this.options.protect;
|
|
666
|
+
r && !n ? (this._states.maxRuns !== void 0 && this._states.maxRuns--, this._trigger()) : r && n && p(this.options.protect) && setTimeout(() => this.options.protect(this), 0), this.schedule();
|
|
667
|
+
}
|
|
668
|
+
_next(e) {
|
|
669
|
+
let t = !!(e || this._states.currentRun), r = false;
|
|
670
|
+
!e && this.options.startAt && this.options.interval && ([e, t] = this._calculatePreviousRun(e, t), r = !e), e = new m(e, this.getTz()), this.options.startAt && e && e.getTime() < this.options.startAt.getTime() && (e = this.options.startAt);
|
|
671
|
+
let n = this._states.once || new m(e, this.getTz());
|
|
672
|
+
return !r && n !== this._states.once && (n = n.increment(this._states.pattern, this.options, t)), this._states.once && this._states.once.getTime() <= e.getTime() || n === null || this._states.maxRuns !== void 0 && this._states.maxRuns <= 0 || this._states.kill || this.options.stopAt && n.getTime() >= this.options.stopAt.getTime() ? null : n;
|
|
673
|
+
}
|
|
674
|
+
_previous(e) {
|
|
675
|
+
let t = new m(e, this.getTz());
|
|
676
|
+
this.options.stopAt && t.getTime() > this.options.stopAt.getTime() && (t = this.options.stopAt);
|
|
677
|
+
let r = new m(t, this.getTz());
|
|
678
|
+
return this._states.once ? this._states.once.getTime() < t.getTime() ? this._states.once : null : (r = r.decrement(this._states.pattern, this.options), r === null || this.options.startAt && r.getTime() < this.options.startAt.getTime() ? null : r);
|
|
679
|
+
}
|
|
680
|
+
_calculatePreviousRun(e, t) {
|
|
681
|
+
let r = new m(void 0, this.getTz()), n = e;
|
|
682
|
+
if (this.options.startAt.getTime() <= r.getTime()) {
|
|
683
|
+
n = this.options.startAt;
|
|
684
|
+
let i = n.getTime() + this.options.interval * 1e3;
|
|
685
|
+
for (; i <= r.getTime(); ) n = new m(n, this.getTz()).increment(this._states.pattern, this.options, true), i = n.getTime() + this.options.interval * 1e3;
|
|
686
|
+
t = true;
|
|
687
|
+
}
|
|
688
|
+
return n === null && (n = void 0), [n, t];
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// shared/routine-schedule.ts
|
|
693
|
+
var MAX_EXPRESSION_LENGTH = 256;
|
|
694
|
+
function cronCalculator(value) {
|
|
695
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Choose a valid cron schedule");
|
|
696
|
+
const input = value;
|
|
697
|
+
if (input.type !== "cron" || typeof input.expression !== "string") throw new Error("Choose a valid cron schedule");
|
|
698
|
+
if (Object.keys(input).some((key) => !["type", "expression", "timeZone"].includes(key))) {
|
|
699
|
+
throw new Error("Cron schedules accept only type, expression and timeZone; start/end dates and other restrictions are not supported");
|
|
700
|
+
}
|
|
701
|
+
const expression = input.expression.trim().replace(/\s+/g, " ");
|
|
702
|
+
if (expression.length > MAX_EXPRESSION_LENGTH || expression.split(" ").length !== 5 || expression.includes("@")) {
|
|
703
|
+
throw new Error("Cron must have five fields: minute hour day-of-month month weekday (no seconds, year, or macros)");
|
|
704
|
+
}
|
|
705
|
+
const timeZone = typeof input.timeZone === "string" ? input.timeZone.trim() : "";
|
|
706
|
+
if (timeZone.length > 128 || !(timeZone === "UTC" || /^[A-Za-z][A-Za-z0-9_+-]*(?:\/[A-Za-z0-9_+-]+)+$/.test(timeZone))) {
|
|
707
|
+
throw new Error("Choose an IANA timezone such as America/New_York, Asia/Kolkata, or UTC");
|
|
708
|
+
}
|
|
709
|
+
try {
|
|
710
|
+
new Intl.DateTimeFormat("en-US", { timeZone }).format(0);
|
|
711
|
+
} catch {
|
|
712
|
+
throw new Error("Choose a valid IANA timezone such as America/New_York, Asia/Kolkata, or UTC");
|
|
713
|
+
}
|
|
714
|
+
try {
|
|
715
|
+
const cron = new E(expression, { timezone: timeZone, mode: "5-part", paused: true });
|
|
716
|
+
return { schedule: { type: "cron", expression, timeZone }, cron };
|
|
717
|
+
} catch (error) {
|
|
718
|
+
throw new Error(`Invalid cron expression: ${error.message}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
function calculationDate(after) {
|
|
722
|
+
const date = new Date(after);
|
|
723
|
+
if (!Number.isFinite(after) || !Number.isFinite(date.getTime())) throw new Error("Choose a valid cron preview date");
|
|
724
|
+
return date;
|
|
725
|
+
}
|
|
726
|
+
function futureRuns(cron, after, count) {
|
|
727
|
+
const from = calculationDate(after);
|
|
728
|
+
const maximum = count + 1440;
|
|
729
|
+
let requested = count;
|
|
730
|
+
while (true) {
|
|
731
|
+
const candidates = cron.nextRuns(requested, from);
|
|
732
|
+
const runs = [];
|
|
733
|
+
for (const date of candidates) {
|
|
734
|
+
const at = date.getTime();
|
|
735
|
+
if (!Number.isFinite(at)) throw new Error("The cron schedule produced an invalid date");
|
|
736
|
+
if (at > (runs.at(-1) ?? after)) runs.push(at);
|
|
737
|
+
if (runs.length === count) return runs;
|
|
738
|
+
}
|
|
739
|
+
if (candidates.length < requested || requested === maximum) return runs;
|
|
740
|
+
requested = Math.min(maximum, requested * 2);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
function normalizeCronSchedule(value, after = Date.now()) {
|
|
744
|
+
const { schedule, cron } = cronCalculator(value);
|
|
745
|
+
if (!futureRuns(cron, after, 1).length) throw new Error("This cron expression has no future runs. Choose dates that exist.");
|
|
746
|
+
return schedule;
|
|
747
|
+
}
|
|
748
|
+
|
|
41
749
|
// server/agent-tool-policy.ts
|
|
42
750
|
var READ_ONLY_AGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
43
751
|
"list_bots",
|
|
44
752
|
"list_team_setup",
|
|
753
|
+
"list_shared_computers",
|
|
45
754
|
"list_rooms",
|
|
46
755
|
"list_threads",
|
|
47
756
|
"check_delegation",
|
|
@@ -90,6 +799,7 @@ var THREAD_ID = process.env.OMB_THREAD_ID ?? "";
|
|
|
90
799
|
var TOKEN = process.env.OMB_COMMS_TOKEN ?? "";
|
|
91
800
|
var DEPTH = Number(process.env.OMB_TURN_DEPTH ?? "0") || 0;
|
|
92
801
|
var SKILL_AUTHORING_ENABLED = process.env.OMB_SKILL_AUTHORING_ENABLED === "1";
|
|
802
|
+
var SHARED_COMPUTERS_ENABLED = process.env.OMB_SHARED_COMPUTERS_ENABLED === "1";
|
|
93
803
|
var MAX_CREATED_PER_TURN = 4;
|
|
94
804
|
var createdThisTurn = 0;
|
|
95
805
|
var MAX_ROOM_POSTS_PER_TURN = 3;
|
|
@@ -111,12 +821,22 @@ var WEEKDAYS = [
|
|
|
111
821
|
var ROUTINE_SCHEDULE_SCHEMA = {
|
|
112
822
|
type: "object",
|
|
113
823
|
additionalProperties: false,
|
|
114
|
-
description: '
|
|
824
|
+
description: 'Use {"type":"cron","expression":"0 9 1 * *","timeZone":"Asia/Kolkata"} for 09:00 on the first of each month, once with at for one future run, weekly with time + weekdays, daily with time, or interval with every_minutes for elapsed-time repetition. Intervals can optionally be limited with weekdays, window_start + window_end, and ends_at.',
|
|
115
825
|
properties: {
|
|
116
826
|
type: {
|
|
117
827
|
type: "string",
|
|
118
|
-
enum: ["once", "weekly", "daily", "interval"],
|
|
119
|
-
description: "once = a single future run; weekly = chosen weekdays; daily = every day; interval = every N minutes."
|
|
828
|
+
enum: ["once", "weekly", "daily", "interval", "cron"],
|
|
829
|
+
description: "once = a single future run; weekly = chosen weekdays; daily = every day; interval = every N elapsed minutes; cron = a calendar rule in an explicit timezone."
|
|
830
|
+
},
|
|
831
|
+
expression: {
|
|
832
|
+
type: "string",
|
|
833
|
+
maxLength: 256,
|
|
834
|
+
description: "Only for cron: five fields, minute hour day-of-month month weekday. Examples: 0 9 1 * * = monthly on day 1 at 09:00; 0 9 L * * = last day of each month; 0 9 * * MON#2 = second Monday of each month. Lists, ranges and steps are supported. No seconds, year, or @ macros. Never substitute daily AI date checks for a calendar rule."
|
|
835
|
+
},
|
|
836
|
+
timeZone: {
|
|
837
|
+
type: "string",
|
|
838
|
+
maxLength: 128,
|
|
839
|
+
description: "Required for cron: explicit IANA timezone, for example Asia/Kolkata, America/New_York, or UTC. Use the user's requested zone; resolve ambiguity before proposing. Do not send a numeric offset or local-time abbreviation."
|
|
120
840
|
},
|
|
121
841
|
at: {
|
|
122
842
|
type: "string",
|
|
@@ -139,7 +859,7 @@ var ROUTINE_SCHEDULE_SCHEMA = {
|
|
|
139
859
|
},
|
|
140
860
|
starts_at: {
|
|
141
861
|
type: "string",
|
|
142
|
-
description: "Optional for type interval: RFC3339 date-time with an explicit timezone offset that anchors the cadence. Omit to start one interval after confirmation."
|
|
862
|
+
description: "Optional for type interval: RFC3339 date-time with an explicit timezone offset that anchors the cadence. Omit to start one interval after the routine is applied (immediately with granted Full Access, otherwise after confirmation)."
|
|
143
863
|
},
|
|
144
864
|
window_start: {
|
|
145
865
|
type: "string",
|
|
@@ -180,7 +900,7 @@ var SHORT_WEEKDAYS = {
|
|
|
180
900
|
sat: "saturday",
|
|
181
901
|
sun: "sunday"
|
|
182
902
|
};
|
|
183
|
-
var SUPPORTED_SCHEDULES = 'Supported schedules: {"type":"once","at":"2026-09-01T09:00:00+05:30"} (future RFC3339 with explicit offset), {"type":"weekly","time":"09:00","weekdays":["monday","friday"]}, {"type":"daily","time":"09:00"},
|
|
903
|
+
var SUPPORTED_SCHEDULES = 'Supported schedules: {"type":"once","at":"2026-09-01T09:00:00+05:30"} (future RFC3339 with explicit offset), {"type":"weekly","time":"09:00","weekdays":["monday","friday"]}, {"type":"daily","time":"09:00"}, {"type":"interval","every_minutes":15,"weekdays":["monday","friday"],"window_start":"09:00","window_end":"17:00"}, or {"type":"cron","expression":"0 9 1 * *","timeZone":"Asia/Kolkata"} (monthly at 09:00 on day 1; five fields and an explicit IANA timezone).';
|
|
184
904
|
function normalizeScheduleInput(args) {
|
|
185
905
|
let raw = args.schedule;
|
|
186
906
|
if (typeof raw === "string") {
|
|
@@ -192,11 +912,18 @@ function normalizeScheduleInput(args) {
|
|
|
192
912
|
}
|
|
193
913
|
if (!jsonRecord(raw)) return { error: `The schedule must be a JSON object. ${SUPPORTED_SCHEDULES}` };
|
|
194
914
|
const type = typeof raw.type === "string" ? raw.type.trim().toLowerCase() : "";
|
|
195
|
-
const fields = type === "once" ? ["type", "at"] : type === "weekly" || type === "daily" ? ["type", "time", "weekdays"] : type === "interval" ? ["type", "every_minutes", "everyMinutes", "starts_at", "anchorAt", "weekdays", "every_day", "window_start", "window_end", "window", "all_day", "ends_at", "endsAt", "never_ends"] : null;
|
|
915
|
+
const fields = type === "once" ? ["type", "at"] : type === "weekly" || type === "daily" ? ["type", "time", "weekdays"] : type === "interval" ? ["type", "every_minutes", "everyMinutes", "starts_at", "anchorAt", "weekdays", "every_day", "window_start", "window_end", "window", "all_day", "ends_at", "endsAt", "never_ends"] : type === "cron" ? ["type", "expression", "timeZone"] : null;
|
|
196
916
|
const unsupported = fields && Object.keys(raw).find((key) => raw[key] != null && !fields.includes(key));
|
|
197
917
|
if (unsupported) {
|
|
198
918
|
return { error: `Unsupported ${type} schedule field "${unsupported}". Weekly and daily times use the computer's timezone from list_routines. ${SUPPORTED_SCHEDULES}` };
|
|
199
919
|
}
|
|
920
|
+
if (type === "cron") {
|
|
921
|
+
try {
|
|
922
|
+
return { schedule: { ...normalizeCronSchedule({ type, expression: raw.expression, timeZone: raw.timeZone }) } };
|
|
923
|
+
} catch (error) {
|
|
924
|
+
return { error: `${error instanceof Error ? error.message : "Invalid cron schedule"}. ${SUPPORTED_SCHEDULES}` };
|
|
925
|
+
}
|
|
926
|
+
}
|
|
200
927
|
if (type === "once") {
|
|
201
928
|
if (typeof raw.at !== "string" || !raw.at.trim()) {
|
|
202
929
|
return { error: `A once schedule needs "at": a future RFC3339 date-time with an explicit offset, for example 2026-09-01T09:00:00+05:30.` };
|
|
@@ -298,7 +1025,7 @@ function normalizeScheduleInput(args) {
|
|
|
298
1025
|
}
|
|
299
1026
|
};
|
|
300
1027
|
}
|
|
301
|
-
if (type === "
|
|
1028
|
+
if (type === "hourly" || type === "minutes") {
|
|
302
1029
|
return { error: `Use an interval schedule for every-N-minutes work. ${SUPPORTED_SCHEDULES}` };
|
|
303
1030
|
}
|
|
304
1031
|
return { error: `Unknown schedule type "${type || "(missing)"}". ${SUPPORTED_SCHEDULES}` };
|
|
@@ -329,10 +1056,32 @@ var ROUTINE_FIELDS_SCHEMA = {
|
|
|
329
1056
|
},
|
|
330
1057
|
continuity: {
|
|
331
1058
|
type: "boolean",
|
|
332
|
-
description: "Opt in to using the latest completed run's bounded report as historical context. Defaults to false; set false in an update to start fresh again.
|
|
1059
|
+
description: "Opt in to using the latest completed run's bounded report as historical context. Defaults to false; set false in an update to start fresh again. Included in the applied result or pending confirmation."
|
|
333
1060
|
}
|
|
334
1061
|
};
|
|
1062
|
+
var PROPOSAL_OUTCOME = " Read the result: granted Full Access may apply the change immediately. If applied, continue the requested work without another confirmation. Only a pending result requires ending the turn and waiting for the in-app decision. Never claim success from the permission mode alone; report failed or cancelled results honestly. This does not elevate another bot's execution permissions.";
|
|
335
1063
|
var TOOLS = [
|
|
1064
|
+
{
|
|
1065
|
+
name: "list_shared_computers",
|
|
1066
|
+
description: "List online desktop computers explicitly shared with this workspace, and their allowed folders/capabilities. These are the user's computers, not this server. An offline or unshared computer cannot be accessed. Folder paths use opaque folder IDs and relative paths.",
|
|
1067
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
name: "shared_computer",
|
|
1071
|
+
description: "Use a desktop explicitly shared by the user. Discover computer_id and folder_id with list_shared_computers. list_files/read_file/write_file are confined to chosen folders; paths are relative. read_file returns sha256; overwriting requires expected_sha256. Binary files support base64 encoding. run_command requires a SEPARATE unrestricted terminal grant. computer_tools lists the native computer-control tools; computer_call invokes one with arguments and needs a SEPARATE computer-control grant. Never substitute the server's filesystem when this desktop is offline. Actions are not retried automatically; inspect an uncertain outcome before retrying.",
|
|
1072
|
+
inputSchema: { type: "object", additionalProperties: false, properties: {
|
|
1073
|
+
computer_id: { type: "string" },
|
|
1074
|
+
action: { type: "string", enum: ["list_files", "read_file", "write_file", "run_command", "computer_tools", "computer_call"] },
|
|
1075
|
+
folder_id: { type: "string" },
|
|
1076
|
+
path: { type: "string" },
|
|
1077
|
+
content: { type: "string" },
|
|
1078
|
+
encoding: { type: "string", enum: ["utf8", "base64"] },
|
|
1079
|
+
expected_sha256: { type: "string" },
|
|
1080
|
+
command: { type: "string" },
|
|
1081
|
+
tool_name: { type: "string" },
|
|
1082
|
+
arguments: { type: "object", additionalProperties: true }
|
|
1083
|
+
}, required: ["computer_id", "action"] }
|
|
1084
|
+
},
|
|
336
1085
|
{
|
|
337
1086
|
name: "list_room_targets",
|
|
338
1087
|
description: "Discover actual OpenMausBot teammates and rooms in your allowed teams. Works in a normal bot conversation too; no room is required. Returns bot and room IDs, roles and working folders, never other conversations' history. Use these bots, not native coding helpers with similar names, when the user asks their team to work together.",
|
|
@@ -340,13 +1089,14 @@ var TOOLS = [
|
|
|
340
1089
|
},
|
|
341
1090
|
{
|
|
342
1091
|
name: "coordinate_bots",
|
|
343
|
-
description: "Ask existing OpenMausBot teammates for advice or assign concrete work. From normal chat
|
|
1092
|
+
description: "Ask existing OpenMausBot teammates for advice or assign concrete work. From normal chat every assignment you send a teammate continues your one standing conversation with that teammate, so they keep the context of what you asked before; from a room it defaults to this room. Use group_id from list_room_targets for a specific room. Name 1-4 bot_ids: they receive only your brief and use their own model, tools and permissions. Busy bots queue. They can consult their specialists; all results return here and resume you automatically. Include exact file paths, constraints and what must be verified. After sending all assignments, END your turn; do not poll or wait. On return, resolve tradeoffs, verify the requested outcome and request concrete corrections if necessary before giving one final answer. Do not send acknowledgements as new work.",
|
|
344
1093
|
inputSchema: { type: "object", additionalProperties: false, properties: {
|
|
345
|
-
group_id: { type: "string", description: "Optional destination room. Omit for this room, or
|
|
1094
|
+
group_id: { type: "string", description: "Optional destination room. Omit for this room, or your standing conversation with each teammate when chatting directly." },
|
|
346
1095
|
bot_ids: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 4, uniqueItems: true },
|
|
347
1096
|
message: { type: "string", minLength: 1, maxLength: 4e3, description: "Self-contained question or task for these teammates. Send separate requests when responsibilities differ." },
|
|
348
1097
|
request_key: { type: "string", description: "A short unique assignment key. Reuse for an identical retry." },
|
|
349
|
-
rework: { type: "boolean", description: "True only for concrete additional work from someone who already completed a request." }
|
|
1098
|
+
rework: { type: "boolean", description: "True only for concrete additional work from someone who already completed a request." },
|
|
1099
|
+
label: { type: "string", description: "Optional short name (one line, at most 60 characters) for this job. Used only when the teammate is still working on your previous assignment and this one therefore runs in its own thread beside your standing conversation." }
|
|
350
1100
|
}, required: ["bot_ids", "message", "request_key"] }
|
|
351
1101
|
},
|
|
352
1102
|
{
|
|
@@ -470,7 +1220,7 @@ var TOOLS = [
|
|
|
470
1220
|
},
|
|
471
1221
|
{
|
|
472
1222
|
name: "propose_team_setup",
|
|
473
|
-
description: "Chief of Staff only:
|
|
1223
|
+
description: "Chief of Staff only: submit all requested specialist creation, profile/model configuration, and authorized team moves in ONE combined plan. Use exact catalog engine/model IDs from list_team_setup. Combine all fields for each bot; use the same create key or botId to coalesce repeated entries. New teams must be named explicitly in newTeams and have a specialist in this plan; access is granted only to those new teams. Existing unauthorized teams cannot be included. Models change bot defaults for groups/new threads; existing threads and execution permissions stay unchanged. If review is pending, the decision and structured result automatically resume you once; do not ask again, poll, or repeat the proposal." + PROPOSAL_OUTCOME,
|
|
474
1224
|
inputSchema: {
|
|
475
1225
|
type: "object",
|
|
476
1226
|
additionalProperties: false,
|
|
@@ -505,7 +1255,7 @@ var TOOLS = [
|
|
|
505
1255
|
},
|
|
506
1256
|
{
|
|
507
1257
|
name: "propose_bot_deletion",
|
|
508
|
-
description: "Chief of Staff only: when the user explicitly asks to delete a named teammate,
|
|
1258
|
+
description: "Chief of Staff only: when the user explicitly asks to delete a named teammate, submit a separate deletion request for that exact bot. Deletion removes its conversations, memory, instructions and skills; generated project files remain. Running work and owned computers can block deletion. Never delete yourself, substitute an archive, or put deletion into a setup batch. If review is pending, the decision and result resume you once." + PROPOSAL_OUTCOME,
|
|
509
1259
|
inputSchema: { type: "object", additionalProperties: false, properties: {
|
|
510
1260
|
bot_id: { type: "string", minLength: 1 },
|
|
511
1261
|
reason: { type: "string", minLength: 1, maxLength: 500 }
|
|
@@ -513,7 +1263,7 @@ var TOOLS = [
|
|
|
513
1263
|
},
|
|
514
1264
|
{
|
|
515
1265
|
name: "create_room",
|
|
516
|
-
description: "Create a room in your own section when the user asks for one (maximum four per turn). Chiefs only. Choose active peers from list_bots; you are included automatically as the default responder. This creates no turns or messages. Section moves stay with the user.
|
|
1266
|
+
description: "Create a room in your own section when the user asks for one (maximum four per turn). Chiefs only. Choose active peers from list_bots; you are included automatically as the default responder. This creates no turns or messages. Section moves stay with the user. Follow the tool result under the effective access level; if permission is refused, ask the user to make the room change instead, without trying another route.",
|
|
517
1267
|
inputSchema: {
|
|
518
1268
|
type: "object",
|
|
519
1269
|
additionalProperties: false,
|
|
@@ -537,7 +1287,7 @@ var TOOLS = [
|
|
|
537
1287
|
},
|
|
538
1288
|
{
|
|
539
1289
|
name: "manage_room",
|
|
540
|
-
description: "Manage a room from list_rooms: rename it, change its bulletin, or add/remove/set members. Chiefs only, within your own section and allowed peers; keep yourself as a member. Busy rooms, pending approvals and team-goal leads are protected. You cannot move rooms or bots between sections.
|
|
1290
|
+
description: "Manage a room from list_rooms: rename it, change its bulletin, or add/remove/set members. Chiefs only, within your own section and allowed peers; keep yourself as a member. Busy rooms, pending approvals and team-goal leads are protected. You cannot move rooms or bots between sections. Follow the tool result under the effective access level; if the change is refused, report the blocker and ask the user to make the change instead, without trying another route.",
|
|
541
1291
|
inputSchema: {
|
|
542
1292
|
type: "object",
|
|
543
1293
|
additionalProperties: false,
|
|
@@ -645,7 +1395,7 @@ var TOOLS = [
|
|
|
645
1395
|
},
|
|
646
1396
|
{
|
|
647
1397
|
name: "propose_routine",
|
|
648
|
-
description: "Prepare a new routine after the user explicitly asks to schedule recurring or future work. Call list_routines first for relative dates or times so you use its authoritative current time and timezone.
|
|
1398
|
+
description: "Prepare a new routine after the user explicitly asks to schedule recurring or future work. Call list_routines first for relative dates or times so you use its authoritative current time and timezone. Convert calendar requests (monthly dates, last days, nth weekdays) into a validated five-field cron schedule with an explicit IANA timeZone; keep elapsed every-N-minutes work as interval. Never approximate unsupported requests with a different weekly schedule or an AI date-check routine; explain the limitation instead. Resolve ambiguous dates, times, timezone, destination, or instructions with the user first, and always give one-time schedules an explicit RFC3339 offset. If the user asks for the routine to run as ANOTHER bot in your section, call list_bots and pass that bot's id as for_bot_id; each run retains that bot's own permissions." + PROPOSAL_OUTCOME,
|
|
649
1399
|
inputSchema: {
|
|
650
1400
|
type: "object",
|
|
651
1401
|
additionalProperties: false,
|
|
@@ -661,7 +1411,7 @@ var TOOLS = [
|
|
|
661
1411
|
},
|
|
662
1412
|
{
|
|
663
1413
|
name: "propose_routine_action",
|
|
664
|
-
description: "Prepare a user-requested change to one of this bot's existing routines.
|
|
1414
|
+
description: "Prepare a user-requested change to one of this bot's existing routines. Use list_routines first to get the routine id." + PROPOSAL_OUTCOME,
|
|
665
1415
|
inputSchema: {
|
|
666
1416
|
type: "object",
|
|
667
1417
|
additionalProperties: false,
|
|
@@ -684,7 +1434,7 @@ var TOOLS = [
|
|
|
684
1434
|
},
|
|
685
1435
|
{
|
|
686
1436
|
name: "propose_profile",
|
|
687
|
-
description: "
|
|
1437
|
+
description: "Submit user-requested changes to your own name, title, description, standing instructions (SOUL.md), or working folder (cwd). Keep SOUL.md short \u2014 who you are and the rules you never break; put step-by-step procedure into a skill instead. A Chief of Staff may pass for_bot_id (from list_bots) for a requested change to another bot in its section." + PROPOSAL_OUTCOME,
|
|
688
1438
|
inputSchema: {
|
|
689
1439
|
type: "object",
|
|
690
1440
|
additionalProperties: false,
|
|
@@ -714,7 +1464,7 @@ var TOOLS = [
|
|
|
714
1464
|
},
|
|
715
1465
|
{
|
|
716
1466
|
name: "skill_manage",
|
|
717
|
-
description: "
|
|
1467
|
+
description: "Submit a new or updated reusable SKILL.md. Never update unless the user explicitly asked to revise that named skill. While review is pending, a create stays inactive and an update leaves the current version unchanged." + PROPOSAL_OUTCOME,
|
|
718
1468
|
inputSchema: {
|
|
719
1469
|
type: "object",
|
|
720
1470
|
additionalProperties: false,
|
|
@@ -734,7 +1484,7 @@ var TOOLS = [
|
|
|
734
1484
|
},
|
|
735
1485
|
gist: {
|
|
736
1486
|
type: "string",
|
|
737
|
-
description: "Optional one-line summary
|
|
1487
|
+
description: "Optional one-line summary of the skill change, included in its applied result or pending review."
|
|
738
1488
|
},
|
|
739
1489
|
source: {
|
|
740
1490
|
type: "string",
|
|
@@ -750,10 +1500,20 @@ var TOOLS = [
|
|
|
750
1500
|
});
|
|
751
1501
|
var SKILL_TOOL_NAMES = /* @__PURE__ */ new Set(["skills_list", "skill_manage"]);
|
|
752
1502
|
var AUTHORING_TOOLS = SKILL_AUTHORING_ENABLED ? TOOLS : TOOLS.filter((tool) => !SKILL_TOOL_NAMES.has(tool.name));
|
|
1503
|
+
var SHARED_COMPUTER_TOOL_NAMES = /* @__PURE__ */ new Set(["list_shared_computers", "shared_computer"]);
|
|
1504
|
+
var SHAREABLE_TOOLS = SHARED_COMPUTERS_ENABLED ? AUTHORING_TOOLS : AUTHORING_TOOLS.filter((tool) => !SHARED_COMPUTER_TOOL_NAMES.has(tool.name));
|
|
753
1505
|
var ROOM_ONLY_TOOLS = /* @__PURE__ */ new Set(["list_room_targets", "coordinate_bots"]);
|
|
754
1506
|
var ROOM_REPLACED_TOOLS = /* @__PURE__ */ new Set(["ask_bot", "delegate_bot", "check_delegation", "wait_delegation", "start_thread", "send_to_thread", "wait_thread"]);
|
|
755
1507
|
var COORDINATING = process.env.OMB_ROOM_TURN === "1";
|
|
756
|
-
var
|
|
1508
|
+
var OWN_THREAD_CREATION = process.env.OMB_OWN_THREAD_CREATION === "1";
|
|
1509
|
+
var AVAILABLE_TOOLS = COORDINATING ? SHAREABLE_TOOLS.filter((tool) => !ROOM_REPLACED_TOOLS.has(tool.name) || tool.name === "start_thread" && OWN_THREAD_CREATION).map((tool) => tool.name === "start_thread" ? {
|
|
1510
|
+
...tool,
|
|
1511
|
+
description: "Open a separate job on yourself with its own history and run, without switching the person's selected conversation. Use only when the user requests independent jobs (for example one review per pull request). Give a short specific title and complete instructions; you can open at most five per turn. This is not a teammate handoff: use coordinate_bots for teammates and their automatic replies. Self-opened jobs cannot recursively open more jobs. If refused, do not retry; explain what remains.",
|
|
1512
|
+
inputSchema: { ...tool.inputSchema, properties: {
|
|
1513
|
+
...tool.inputSchema.properties,
|
|
1514
|
+
bot_id: { type: "string", enum: [BOT_ID], description: "Leave out, or use your own bot ID. For teammates use coordinate_bots." }
|
|
1515
|
+
} }
|
|
1516
|
+
} : tool) : SHAREABLE_TOOLS.filter((tool) => !ROOM_ONLY_TOOLS.has(tool.name));
|
|
757
1517
|
var send = (msg) => process.stdout.write(JSON.stringify(msg) + "\n");
|
|
758
1518
|
var ok = (id, result) => send({ jsonrpc: "2.0", id, result });
|
|
759
1519
|
var rpcErr = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
@@ -821,7 +1581,32 @@ function routineFields(args) {
|
|
|
821
1581
|
if (typeof args.continuity === "boolean") fields.continuity = args.continuity;
|
|
822
1582
|
return { fields };
|
|
823
1583
|
}
|
|
1584
|
+
function completedProposalResult(r, subject) {
|
|
1585
|
+
const state = r.state;
|
|
1586
|
+
const result = jsonRecord(r.result) ? r.result : void 0;
|
|
1587
|
+
const error = typeof r.error === "string" ? r.error : typeof result?.error === "string" ? result.error : void 0;
|
|
1588
|
+
const attention = error ?? (r.settlementPending && typeof r.message === "string" ? r.message : void 0);
|
|
1589
|
+
if ((!state || state === "pending") && !error) return void 0;
|
|
1590
|
+
const summary = typeof r.summary === "string" && r.summary.trim() ? `
|
|
1591
|
+
|
|
1592
|
+
${r.summary.trim()}` : "";
|
|
1593
|
+
const details = result ? `
|
|
1594
|
+
|
|
1595
|
+
Result: ${JSON.stringify(result)}` : "";
|
|
1596
|
+
if (state !== "applied" || result?.state !== void 0 && result.state !== "applied") {
|
|
1597
|
+
return { text: `The request for ${subject} did not complete successfully.${error ? ` ${error}` : ""}${summary}${details}
|
|
1598
|
+
|
|
1599
|
+
Do not claim it was applied. Address the reported blocker rather than repeating the request or asking for a duplicate confirmation.`, isError: true };
|
|
1600
|
+
}
|
|
1601
|
+
return { text: `Applied ${subject}.${summary}${details}${attention ? `
|
|
1602
|
+
|
|
1603
|
+
Needs attention: ${attention}` : ""}
|
|
1604
|
+
|
|
1605
|
+
No additional confirmation is needed. Continue the requested work; do not wait for a review card or ask the user to approve this change again.` };
|
|
1606
|
+
}
|
|
824
1607
|
function confirmationResult(r, fallback, noun = "routine") {
|
|
1608
|
+
const completed = completedProposalResult(r, fallback);
|
|
1609
|
+
if (completed) return completed;
|
|
825
1610
|
const summary = typeof r.summary === "string" && r.summary.trim() ? `
|
|
826
1611
|
|
|
827
1612
|
${r.summary.trim()}` : "";
|
|
@@ -847,7 +1632,8 @@ async function callTool(name, args) {
|
|
|
847
1632
|
botIds: args.bot_ids,
|
|
848
1633
|
message: args.message,
|
|
849
1634
|
requestKey: args.request_key,
|
|
850
|
-
rework: args.rework
|
|
1635
|
+
rework: args.rework,
|
|
1636
|
+
label: args.label
|
|
851
1637
|
}) });
|
|
852
1638
|
return { text: JSON.stringify(r), ...r.error ? { isError: true } : {} };
|
|
853
1639
|
}
|
|
@@ -855,12 +1641,12 @@ async function callTool(name, args) {
|
|
|
855
1641
|
const r = await api(`/api/internal/agents?self=${encodeURIComponent(BOT_ID)}`);
|
|
856
1642
|
const bots = r.bots ?? [];
|
|
857
1643
|
if (!bots.length) return { text: "No other reachable bots yet." };
|
|
858
|
-
const lines = bots.map((
|
|
859
|
-
const role =
|
|
860
|
-
const about =
|
|
861
|
-
const state = typeof
|
|
862
|
-
const team = typeof
|
|
863
|
-
return `- ${
|
|
1644
|
+
const lines = bots.map((b2) => {
|
|
1645
|
+
const role = b2.title ? ` \u2014 ${b2.title}` : "";
|
|
1646
|
+
const about = b2.description ? ` (${String(b2.description).slice(0, 120)})` : "";
|
|
1647
|
+
const state = typeof b2.statusText === "string" ? b2.status === "available" ? "" : b2.statusText : b2.busy ? "busy" : "";
|
|
1648
|
+
const team = typeof b2.section === "string" ? `, team: ${peerName(b2.section) || "General"}` : "";
|
|
1649
|
+
return `- ${b2.name}${role}${about} [id: ${b2.id}, model: ${b2.model}${team}${state ? `, ${state}` : ""}]`;
|
|
864
1650
|
});
|
|
865
1651
|
return {
|
|
866
1652
|
text: `Reachable teammates:
|
|
@@ -1039,6 +1825,9 @@ ${lines.join("\n")}` };
|
|
|
1039
1825
|
};
|
|
1040
1826
|
}
|
|
1041
1827
|
const toBotId = typeof args.bot_id === "string" ? args.bot_id.trim() : "";
|
|
1828
|
+
if (COORDINATING && toBotId && toBotId !== BOT_ID) {
|
|
1829
|
+
return { text: "Use coordinate_bots for teammates; start_thread only opens a separate job on yourself.", isError: true };
|
|
1830
|
+
}
|
|
1042
1831
|
const folder = typeof args.folder === "string" ? args.folder.trim() : "";
|
|
1043
1832
|
const body = { fromBotId: BOT_ID, fromThreadId: THREAD_ID, title, message, depth: DEPTH };
|
|
1044
1833
|
if (toBotId) body.toBotId = toBotId;
|
|
@@ -1082,6 +1871,8 @@ ${lines.join("\n")}` };
|
|
|
1082
1871
|
...deleting ? { targetBotId: args.bot_id, reason: args.reason } : { plan: args }
|
|
1083
1872
|
})
|
|
1084
1873
|
});
|
|
1874
|
+
const completed = completedProposalResult(result, deleting ? "the requested bot deletion" : "the requested team setup");
|
|
1875
|
+
if (completed) return completed;
|
|
1085
1876
|
return { text: `One review card is visible: ${String(result.title)}. Nothing has been applied. End this turn; the decision and structured result resume you automatically once. Do not ask again, poll, or repeat this proposal.` };
|
|
1086
1877
|
}
|
|
1087
1878
|
if (name === "create_bot") {
|
|
@@ -1377,7 +2168,7 @@ ${note}` };
|
|
|
1377
2168
|
const skills = Array.isArray(r.skills) ? r.skills : [];
|
|
1378
2169
|
const staged = Array.isArray(r.staged) ? r.staged : [];
|
|
1379
2170
|
if (!skills.length && !staged.length) {
|
|
1380
|
-
return { text: 'This bot has no imported skills and nothing staged. Use skill_manage action="create"
|
|
2171
|
+
return { text: 'This bot has no imported skills and nothing staged. Use skill_manage action="create" for a user-requested skill, then follow its applied or pending result.' };
|
|
1381
2172
|
}
|
|
1382
2173
|
const live = skills.length ? skills.map((skill) => {
|
|
1383
2174
|
const row = skill;
|
|
@@ -1426,8 +2217,10 @@ ${pending}` };
|
|
|
1426
2217
|
const nameLabel = typeof r.name === "string" ? r.name : "the skill";
|
|
1427
2218
|
const warningText = Array.isArray(r.warnings) && r.warnings.length ? `
|
|
1428
2219
|
|
|
1429
|
-
Scan warnings
|
|
2220
|
+
Scan warnings:
|
|
1430
2221
|
- ${r.warnings.join("\n- ")}` : "";
|
|
2222
|
+
const completed = completedProposalResult(r, args.action === "update" ? `the update to skill \u201C${nameLabel}\u201D` : `the new skill \u201C${nameLabel}\u201D`);
|
|
2223
|
+
if (completed) return { ...completed, text: completed.text + warningText };
|
|
1431
2224
|
const status = args.action === "update" ? "The current version remains unchanged until the user reviews and applies the update." : "The skill is staged and inactive until the user reviews and enables it.";
|
|
1432
2225
|
const proposal = args.action === "update" ? `updating skill \u201C${nameLabel}\u201D` : `new skill \u201C${nameLabel}\u201D`;
|
|
1433
2226
|
return {
|
|
@@ -1464,6 +2257,21 @@ async function handle(msg) {
|
|
|
1464
2257
|
const name = params.name;
|
|
1465
2258
|
if (!AVAILABLE_TOOLS.some((t) => t.name === name)) return rpcErr(id, -32602, `Unknown tool: ${name}`);
|
|
1466
2259
|
try {
|
|
2260
|
+
if (SHARED_COMPUTER_TOOL_NAMES.has(name) && !SHARED_COMPUTERS_ENABLED) {
|
|
2261
|
+
textResult(id, "Computer sharing is turned off in this workspace. There are no shared computers to use.", true);
|
|
2262
|
+
return;
|
|
2263
|
+
}
|
|
2264
|
+
if (name === "list_shared_computers") {
|
|
2265
|
+
textResult(id, JSON.stringify(await api("/api/internal/shared-computers")));
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
if (name === "shared_computer") {
|
|
2269
|
+
const response = await api("/api/internal/shared-computers", { method: "POST", body: JSON.stringify(params.arguments ?? {}) });
|
|
2270
|
+
const result = response.result;
|
|
2271
|
+
if (Array.isArray(result?.content)) ok(id, result);
|
|
2272
|
+
else textResult(id, JSON.stringify(result));
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
1467
2275
|
const { text, isError } = await callTool(name, params.arguments ?? {});
|
|
1468
2276
|
textResult(id, text, isError);
|
|
1469
2277
|
} catch (e) {
|