openfox 2.0.140 → 2.0.142
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/CHANGELOG.md +30 -0
- package/dist/CHANGELOG.md +30 -0
- package/dist/{chat-handler-JWRCPG72.js → chat-handler-OFB4426F.js} +26 -26
- package/dist/{chunk-CRJ5J7U5.js → chunk-2CEZQAGQ.js} +3 -3
- package/dist/{chunk-GZJRXVVJ.js → chunk-5CZAKVGZ.js} +12 -12
- package/dist/{chunk-SSHXYKW3.js → chunk-5HDPFHHJ.js} +2 -2
- package/dist/{chunk-K227HOLU.js → chunk-ACILWRPU.js} +7 -7
- package/dist/{chunk-TJOKDC34.js → chunk-CSUMZAYY.js} +399 -86
- package/dist/{chunk-EE6VFEE6.js → chunk-DNL2NUDB.js} +2 -2
- package/dist/{chunk-UA2ATO3B.js → chunk-DQEANXXF.js} +3 -3
- package/dist/{chunk-4F4ARGAM.js → chunk-DRIR2IZR.js} +3 -3
- package/dist/{chunk-AE2IBEUH.js → chunk-EFEHIJXF.js} +2 -2
- package/dist/chunk-EPZO3MGM.js +7 -0
- package/dist/{chunk-7OHSAZLF.js → chunk-F3R4YS3F.js} +16 -18
- package/dist/{chunk-WD354R3H.js → chunk-FFVIO6GL.js} +4 -4
- package/dist/{chunk-5EKBZXCU.js → chunk-HQDKHNWS.js} +7 -7
- package/dist/{chunk-H7YL7PH3.js → chunk-J556QIRD.js} +2 -2
- package/dist/{chunk-DPFET73G.js → chunk-JYYBSODN.js} +2 -2
- package/dist/{chunk-46Q2SHGJ.js → chunk-MEPTCUYN.js} +2 -2
- package/dist/{chunk-RG326HS4.js → chunk-N5AJHJG5.js} +45 -13
- package/dist/{chunk-JTR3PC5I.js → chunk-NJFXYSXP.js} +5 -5
- package/dist/{chunk-XE6UC5Z3.js → chunk-PHR64A6U.js} +2 -2
- package/dist/{chunk-5F7LNEEP.js → chunk-Q5JCBAQF.js} +3 -3
- package/dist/{chunk-5MGCTRKM.js → chunk-RM4ZBI2B.js} +20 -20
- package/dist/{chunk-EMXMTCSY.js → chunk-SKNPOZYP.js} +4 -2
- package/dist/{chunk-IFARTQOK.js → chunk-TEUVZCPS.js} +17 -17
- package/dist/{chunk-JLHYB445.js → chunk-TIIWXMGE.js} +2 -2
- package/dist/{chunk-66XJC5TA.js → chunk-TRZZCMJ3.js} +9 -9
- package/dist/{chunk-LW6MMSTD.js → chunk-VGE6UYND.js} +2 -2
- package/dist/{chunk-QIGVYXMH.js → chunk-VK2BSIJP.js} +141 -131
- package/dist/{chunk-JU757HVI.js → chunk-WOVWVB5J.js} +11 -1
- package/dist/{chunk-FIEFBRTQ.js → chunk-WSDR27YV.js} +4 -4
- package/dist/{chunk-MAUQ6AW4.js → chunk-XADIBENX.js} +6 -6
- package/dist/{chunk-GKRYQ56N.js → chunk-Z7IT3V22.js} +3 -3
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{client-KJS7QIIV.js → client-2A766XZK.js} +5 -5
- package/dist/{compactor-UREBHSZQ.js → compactor-3BVVHO4M.js} +11 -11
- package/dist/{describe-image-TQOD52IC.js → describe-image-F22VNBWY.js} +12 -12
- package/dist/{dynamic-context-KGSZ7TRQ.js → dynamic-context-5SFXTEAP.js} +12 -12
- package/dist/{events-ZLP5V2YU.js → events-UAUOGRSV.js} +8 -8
- package/dist/{export-import-CJT33IO6.js → export-import-PBEX3KWU.js} +9 -9
- package/dist/{folding-BXMVJIFF.js → folding-IHD244OU.js} +6 -6
- package/dist/http-client-RA7XFYPO.js +11 -0
- package/dist/{inspect-proxy-A3OROWPG.js → inspect-proxy-24Q2CNCZ.js} +4 -4
- package/dist/{launch-7NKOCT5A.js → launch-L5NL75KK.js} +26 -26
- package/dist/{manager-JZNNVDYR.js → manager-4SMHCFXY.js} +5 -5
- package/dist/{orchestrator-VSVDUGBT.js → orchestrator-53SS74LD.js} +25 -25
- package/dist/package.json +1 -1
- package/dist/{path-security-V3XALT5E.js → path-security-WOA6MTWQ.js} +10 -10
- package/dist/{platform-DBPLSLE4.js → platform-EAZNZDAE.js} +4 -4
- package/dist/{processor-ACZM62WO.js → processor-T4VWZMXT.js} +25 -25
- package/dist/{project-creator-T3A4H3YV.js → project-creator-K5EGKY2P.js} +3 -3
- package/dist/{projects-5U37RUTL.js → projects-VDWCFPVE.js} +3 -3
- package/dist/{protocol-D6DZzkSH.d.ts → protocol-Dpf4FBF2.d.ts} +1 -1
- package/dist/provider/index.d.ts +4 -4
- package/dist/{provider-7LNTLWRB.js → provider-5XNJEDKW.js} +6 -6
- package/dist/{provider-manager-TV5I5YJH.js → provider-manager-RHJYUU5W.js} +6 -6
- package/dist/{registry-PVJAAL2Y.js → registry-C7RKKHZB.js} +5 -5
- package/dist/scheduler-VLTPMGGJ.js +25 -0
- package/dist/{serve-36D5HXWE.js → serve-LP3ZX6CW.js} +31 -31
- package/dist/server/index.d.ts +6 -6
- package/dist/server/index.js +30 -30
- package/dist/server-IGZLCNZG.js +61 -0
- package/dist/{service-7QKWUNU4.js → service-AZU4YTS2.js} +9 -9
- package/dist/{session-overrides-7OPGV7CQ.js → session-overrides-CKS2AVE5.js} +7 -7
- package/dist/{sessions-VHS47DHO.js → sessions-DAHLRQE2.js} +6 -6
- package/dist/{settings-HCSHADP5.js → settings-TR4BF2C4.js} +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/{tasks-E7EG7344.js → tasks-T5KZXKMD.js} +18 -12
- package/dist/{tools-AY6XEVJK.js → tools-BL6XCTUV.js} +23 -23
- package/dist/{types-ofYNpiqi.d.ts → types-CZJf6Fnb.d.ts} +1 -1
- package/dist/{types-CLcL33hJ.d.ts → types-LO8296aY.d.ts} +34 -1
- package/dist/{update-JHFZMW3T.js → update-M5DMX3FC.js} +2 -2
- package/dist/web/assets/{index-BtkaULxJ.css → index-2WvLd7SC.css} +1 -1
- package/dist/web/assets/index-BPhet33M.js +313 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/{workspace-LM646OHC.js → workspace-ENN27P56.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-6RYTDRUR.js +0 -7
- package/dist/http-client-JVJ43TBY.js +0 -11
- package/dist/server-R3J26IP2.js +0 -61
- package/dist/web/assets/index-Bm0_ekvt.js +0 -313
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
serverT
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TIIWXMGE.js";
|
|
4
4
|
import {
|
|
5
5
|
deleteItemFromDir,
|
|
6
6
|
getDefaultIds,
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
} from "./chunk-OSXPQSLW.js";
|
|
12
12
|
import {
|
|
13
13
|
parseDefaultModelSelection
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-J556QIRD.js";
|
|
15
15
|
import {
|
|
16
16
|
getProject
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JYYBSODN.js";
|
|
18
18
|
import {
|
|
19
19
|
getDatabase
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-WOVWVB5J.js";
|
|
21
21
|
import {
|
|
22
22
|
logger
|
|
23
23
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -365,14 +365,17 @@ async function resolveSlashLaunch(configDir, projectDir, prompt) {
|
|
|
365
365
|
|
|
366
366
|
// src/server/db/tasks.ts
|
|
367
367
|
import { randomBytes } from "crypto";
|
|
368
|
+
function scheduleNextRun(schedule) {
|
|
369
|
+
return schedule.type === "once" ? schedule.runAt : schedule.nextRunAt;
|
|
370
|
+
}
|
|
368
371
|
function createTask(projectId, input) {
|
|
369
372
|
const db = getDatabase();
|
|
370
373
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
374
|
const id = randomBytes(8).toString("hex");
|
|
372
375
|
const position = db.prepare(`SELECT COALESCE(MAX(position), -1) + 1 AS pos FROM tasks WHERE project_id = ? AND status = 'todo'`).get(projectId);
|
|
373
376
|
db.prepare(
|
|
374
|
-
`INSERT INTO tasks (id, project_id, prompt, attachments, status, run_state, position, version, agent_id, provider_id, model, created_at, updated_at)
|
|
375
|
-
VALUES (?, ?, ?, ?, 'todo', NULL, ?, 1, ?, ?, ?, ?, ?)`
|
|
377
|
+
`INSERT INTO tasks (id, project_id, prompt, attachments, status, run_state, position, version, agent_id, provider_id, model, schedule, next_run_at, created_at, updated_at)
|
|
378
|
+
VALUES (?, ?, ?, ?, 'todo', NULL, ?, 1, ?, ?, ?, ?, ?, ?, ?)`
|
|
376
379
|
).run(
|
|
377
380
|
id,
|
|
378
381
|
projectId,
|
|
@@ -382,6 +385,8 @@ function createTask(projectId, input) {
|
|
|
382
385
|
input.agentId ?? null,
|
|
383
386
|
input.providerId ?? null,
|
|
384
387
|
input.model ?? null,
|
|
388
|
+
input.schedule ? JSON.stringify(input.schedule) : null,
|
|
389
|
+
input.schedule ? scheduleNextRun(input.schedule) : null,
|
|
385
390
|
now,
|
|
386
391
|
now
|
|
387
392
|
);
|
|
@@ -423,6 +428,12 @@ function updateTask(id, patch) {
|
|
|
423
428
|
sets.push("model = ?");
|
|
424
429
|
values.push(patch.model);
|
|
425
430
|
}
|
|
431
|
+
if (patch.schedule !== void 0) {
|
|
432
|
+
sets.push("schedule = ?");
|
|
433
|
+
values.push(patch.schedule ? JSON.stringify(patch.schedule) : null);
|
|
434
|
+
sets.push("next_run_at = ?");
|
|
435
|
+
values.push(patch.schedule ? scheduleNextRun(patch.schedule) : null);
|
|
436
|
+
}
|
|
426
437
|
values.push(id);
|
|
427
438
|
db.prepare(`UPDATE tasks SET ${sets.join(", ")} WHERE id = ?`).run(...values);
|
|
428
439
|
return getTask(id);
|
|
@@ -449,6 +460,28 @@ function deleteTask(id) {
|
|
|
449
460
|
const db = getDatabase();
|
|
450
461
|
db.prepare(`DELETE FROM tasks WHERE id = ?`).run(id);
|
|
451
462
|
}
|
|
463
|
+
function listDueScheduledTasks(nowIso) {
|
|
464
|
+
const db = getDatabase();
|
|
465
|
+
const rows = db.prepare(
|
|
466
|
+
`SELECT * FROM tasks WHERE status = 'todo' AND next_run_at IS NOT NULL AND next_run_at <= ? ORDER BY next_run_at ASC`
|
|
467
|
+
).all(nowIso);
|
|
468
|
+
return rows.map(hydrateTask);
|
|
469
|
+
}
|
|
470
|
+
function setTaskSchedule(id, schedule, nextRunAt) {
|
|
471
|
+
const db = getDatabase();
|
|
472
|
+
db.prepare(`UPDATE tasks SET schedule = ?, next_run_at = ?, version = version + 1, updated_at = ? WHERE id = ?`).run(
|
|
473
|
+
JSON.stringify(schedule),
|
|
474
|
+
nextRunAt,
|
|
475
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
476
|
+
id
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
function clearTaskSchedule(id) {
|
|
480
|
+
const db = getDatabase();
|
|
481
|
+
db.prepare(
|
|
482
|
+
`UPDATE tasks SET schedule = NULL, next_run_at = NULL, version = version + 1, updated_at = ? WHERE id = ?`
|
|
483
|
+
).run((/* @__PURE__ */ new Date()).toISOString(), id);
|
|
484
|
+
}
|
|
452
485
|
function appendToBottom(id, status) {
|
|
453
486
|
const db = getDatabase();
|
|
454
487
|
const task = getTask(id);
|
|
@@ -460,7 +493,7 @@ function appendToBottom(id, status) {
|
|
|
460
493
|
id
|
|
461
494
|
);
|
|
462
495
|
}
|
|
463
|
-
function cloneTask(sourceId) {
|
|
496
|
+
function cloneTask(sourceId, copySchedule = true) {
|
|
464
497
|
const source = getTask(sourceId);
|
|
465
498
|
if (!source) return null;
|
|
466
499
|
return createTask(source.projectId, {
|
|
@@ -468,7 +501,8 @@ function cloneTask(sourceId) {
|
|
|
468
501
|
attachments: source.attachments,
|
|
469
502
|
...source.agentId ? { agentId: source.agentId } : {},
|
|
470
503
|
...source.providerId ? { providerId: source.providerId } : {},
|
|
471
|
-
...source.model ? { model: source.model } : {}
|
|
504
|
+
...source.model ? { model: source.model } : {},
|
|
505
|
+
...copySchedule && source.schedule ? { schedule: source.schedule } : {}
|
|
472
506
|
});
|
|
473
507
|
}
|
|
474
508
|
function reorderTask(id, status, toIndex) {
|
|
@@ -612,6 +646,7 @@ function hydrateTask(row) {
|
|
|
612
646
|
const sessionIds = links.map((l) => l.session_id);
|
|
613
647
|
const activeLink = links.find((l) => Boolean(l.active));
|
|
614
648
|
const runState = row.status === "in_progress" ? row.run_state : void 0;
|
|
649
|
+
const schedule = row.schedule ? safeParseSchedule(row.schedule) : void 0;
|
|
615
650
|
const task = {
|
|
616
651
|
id: row.id,
|
|
617
652
|
projectId: row.project_id,
|
|
@@ -624,6 +659,7 @@ function hydrateTask(row) {
|
|
|
624
659
|
...row.agent_id ? { agentId: row.agent_id } : {},
|
|
625
660
|
...row.provider_id ? { providerId: row.provider_id } : {},
|
|
626
661
|
...row.model ? { model: row.model } : {},
|
|
662
|
+
...schedule ? { schedule } : {},
|
|
627
663
|
sessionIds,
|
|
628
664
|
...activeLink ? { activeSessionId: activeLink.session_id } : {},
|
|
629
665
|
gateValues: getGateValues(row.id),
|
|
@@ -656,6 +692,104 @@ function safeParseAttachments(raw) {
|
|
|
656
692
|
return [];
|
|
657
693
|
}
|
|
658
694
|
}
|
|
695
|
+
function safeParseSchedule(raw) {
|
|
696
|
+
try {
|
|
697
|
+
const parsed = JSON.parse(raw);
|
|
698
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
699
|
+
if (parsed.type === "once" && typeof parsed.runAt === "string") return parsed;
|
|
700
|
+
if (parsed.type === "recurring" && typeof parsed.interval === "number" && typeof parsed.startAt === "string" && typeof parsed.nextRunAt === "string" && parsed.end && typeof parsed.end.kind === "string" && typeof parsed.occurrencesDone === "number") {
|
|
701
|
+
return parsed;
|
|
702
|
+
}
|
|
703
|
+
return void 0;
|
|
704
|
+
} catch {
|
|
705
|
+
return void 0;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/server/tasks/recurrence.ts
|
|
710
|
+
var MS_DAY = 864e5;
|
|
711
|
+
function dayDiff(a, b) {
|
|
712
|
+
const ua = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
|
|
713
|
+
const ub = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
|
|
714
|
+
return Math.round((ub - ua) / MS_DAY);
|
|
715
|
+
}
|
|
716
|
+
function addDays(date, days) {
|
|
717
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
|
|
718
|
+
}
|
|
719
|
+
function mondayOf(date) {
|
|
720
|
+
return addDays(date, -((date.getDay() + 6) % 7));
|
|
721
|
+
}
|
|
722
|
+
function lastDayOfMonth(y, m0) {
|
|
723
|
+
return new Date(y, m0 + 1, 0).getDate();
|
|
724
|
+
}
|
|
725
|
+
function nextOccurrence(after, rule) {
|
|
726
|
+
const start = new Date(rule.startAt);
|
|
727
|
+
if (Number.isNaN(start.getTime()) || !Number.isFinite(after.getTime())) return null;
|
|
728
|
+
if (rule.end.kind === "count" && rule.occurrencesDone >= rule.end.count) return null;
|
|
729
|
+
const hour = start.getHours();
|
|
730
|
+
const minute = start.getMinutes();
|
|
731
|
+
const second = start.getSeconds();
|
|
732
|
+
const ms = start.getMilliseconds();
|
|
733
|
+
const atTime = (y, m0, d) => new Date(y, m0, d, hour, minute, second, ms);
|
|
734
|
+
let candidate = null;
|
|
735
|
+
if (after.getTime() < start.getTime()) {
|
|
736
|
+
candidate = new Date(start);
|
|
737
|
+
} else if (rule.freq === "day") {
|
|
738
|
+
const k = Math.floor(dayDiff(start, after) / rule.interval);
|
|
739
|
+
let c = addDays(start, k * rule.interval);
|
|
740
|
+
if (c.getTime() <= after.getTime()) c = addDays(c, rule.interval);
|
|
741
|
+
candidate = atTime(c.getFullYear(), c.getMonth(), c.getDate());
|
|
742
|
+
} else if (rule.freq === "week") {
|
|
743
|
+
const weekdays = rule.weekdays && rule.weekdays.length > 0 ? rule.weekdays : [start.getDay()];
|
|
744
|
+
const baseMonday = mondayOf(start);
|
|
745
|
+
const maxDays = (rule.interval + 1) * 7 + 7;
|
|
746
|
+
for (let i = 1; i <= maxDays; i++) {
|
|
747
|
+
const c = addDays(after, i);
|
|
748
|
+
if (!weekdays.includes(c.getDay())) continue;
|
|
749
|
+
const weekIndex = Math.floor(dayDiff(baseMonday, mondayOf(c)) / 7);
|
|
750
|
+
if (weekIndex >= 0 && weekIndex % rule.interval === 0) {
|
|
751
|
+
candidate = atTime(c.getFullYear(), c.getMonth(), c.getDate());
|
|
752
|
+
break;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
} else if (rule.freq === "month") {
|
|
756
|
+
const baseAbs = start.getFullYear() * 12 + start.getMonth();
|
|
757
|
+
const day = rule.monthDay ?? start.getDate();
|
|
758
|
+
const startAbs = after.getFullYear() * 12 + after.getMonth();
|
|
759
|
+
const rem = ((startAbs - baseAbs) % rule.interval + rule.interval) % rule.interval;
|
|
760
|
+
let mAbs = startAbs + (rem === 0 ? 0 : rule.interval - rem);
|
|
761
|
+
for (let i = 0; i <= rule.interval + 1; i++) {
|
|
762
|
+
const y = Math.floor(mAbs / 12);
|
|
763
|
+
const m0 = mAbs % 12;
|
|
764
|
+
const c = atTime(y, m0, Math.min(day, lastDayOfMonth(y, m0)));
|
|
765
|
+
if (c.getTime() > after.getTime()) {
|
|
766
|
+
candidate = c;
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
mAbs += rule.interval;
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
const baseY = start.getFullYear();
|
|
773
|
+
const m = (rule.yearMonth ?? start.getMonth() + 1) - 1;
|
|
774
|
+
const day = rule.monthDay ?? start.getDate();
|
|
775
|
+
const rem = ((after.getFullYear() - baseY) % rule.interval + rule.interval) % rule.interval;
|
|
776
|
+
let y = after.getFullYear() + (rem === 0 ? 0 : rule.interval - rem);
|
|
777
|
+
for (let i = 0; i <= rule.interval + 1; i++) {
|
|
778
|
+
const c = atTime(y, m, Math.min(day, lastDayOfMonth(y, m)));
|
|
779
|
+
if (c.getTime() > after.getTime()) {
|
|
780
|
+
candidate = c;
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
y += rule.interval;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
if (!candidate) return null;
|
|
787
|
+
if (rule.end.kind === "until") {
|
|
788
|
+
const until = new Date(rule.end.until);
|
|
789
|
+
if (Number.isNaN(until.getTime()) || candidate.getTime() > until.getTime()) return null;
|
|
790
|
+
}
|
|
791
|
+
return candidate;
|
|
792
|
+
}
|
|
659
793
|
|
|
660
794
|
// src/server/tasks/service.ts
|
|
661
795
|
function isTaskConflictError(err) {
|
|
@@ -745,7 +879,8 @@ function createTasksService(deps) {
|
|
|
745
879
|
attachments: input.attachments ?? [],
|
|
746
880
|
...input.agentId ? { agentId: input.agentId } : {},
|
|
747
881
|
...input.providerId ? { providerId: input.providerId } : {},
|
|
748
|
-
...input.model ? { model: input.model } : {}
|
|
882
|
+
...input.model ? { model: input.model } : {},
|
|
883
|
+
...input.schedule ? { schedule: normalizeSchedule(input.schedule) } : {}
|
|
749
884
|
});
|
|
750
885
|
addAuditEntry(task.id, actor.actor, "create", `Task created in To Do`, actor.actorName);
|
|
751
886
|
const fresh = getTask(task.id);
|
|
@@ -756,7 +891,10 @@ function createTasksService(deps) {
|
|
|
756
891
|
return withLock(projectId, () => {
|
|
757
892
|
const task = assertOwned(projectId, taskId);
|
|
758
893
|
assertNotStale(task, expectedVersion);
|
|
759
|
-
const next = updateTask(taskId,
|
|
894
|
+
const next = updateTask(taskId, {
|
|
895
|
+
...patch,
|
|
896
|
+
...patch.schedule !== void 0 ? { schedule: patch.schedule === null ? null : normalizeSchedule(patch.schedule) } : {}
|
|
897
|
+
}) ?? getTask(taskId);
|
|
760
898
|
const changed = summarizeChanges(task, next);
|
|
761
899
|
addAuditEntry(taskId, actor.actor, "edit", changed || "Task updated", actor.actorName);
|
|
762
900
|
const fresh = getTask(taskId);
|
|
@@ -792,87 +930,164 @@ function createTasksService(deps) {
|
|
|
792
930
|
});
|
|
793
931
|
}
|
|
794
932
|
function move(projectId, taskId, to, opts) {
|
|
795
|
-
return withLock(projectId,
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
933
|
+
return withLock(projectId, () => moveLocked(projectId, taskId, to, opts));
|
|
934
|
+
}
|
|
935
|
+
async function moveLocked(projectId, taskId, to, opts) {
|
|
936
|
+
const task = assertOwned(projectId, taskId);
|
|
937
|
+
assertNotStale(task, opts.expectedVersion);
|
|
938
|
+
const from = task.status;
|
|
939
|
+
if (from === to) {
|
|
940
|
+
return { task };
|
|
941
|
+
}
|
|
942
|
+
let sessionId;
|
|
943
|
+
const wasRunning = task.status === "in_progress" && task.runState === "running";
|
|
944
|
+
if (to === "in_progress") {
|
|
945
|
+
const readyGates = requiredGates(projectId, "ready");
|
|
946
|
+
const missing = missingGateFields(task, readyGates);
|
|
947
|
+
if (missing.length > 0) {
|
|
948
|
+
throw gateBlockedError(task, "In Progress", missing);
|
|
801
949
|
}
|
|
802
|
-
|
|
803
|
-
const
|
|
804
|
-
if (
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
950
|
+
setTaskStatus(taskId, "in_progress");
|
|
951
|
+
const settings = getTaskSettings(projectId);
|
|
952
|
+
if (opts.actor === "agent") {
|
|
953
|
+
if (!opts.sessionId) {
|
|
954
|
+
throw new Error(
|
|
955
|
+
serverT({
|
|
956
|
+
en: "Agent moves must bind to the current session (sessionId is required)",
|
|
957
|
+
fr: "Les d\xE9placements d\u2019agent doivent \xEAtre li\xE9s \xE0 la session courante (sessionId requis)"
|
|
958
|
+
})
|
|
959
|
+
);
|
|
809
960
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
961
|
+
setTaskRunState(taskId, "running");
|
|
962
|
+
addTaskLink(taskId, opts.sessionId, true);
|
|
963
|
+
addAuditEntry(taskId, "agent", "move", `Moved to In Progress (running)`, opts.actorName);
|
|
964
|
+
emitReminder(opts.sessionId, reminderForInProgress(task, opts.sessionId, from));
|
|
965
|
+
sessionId = opts.sessionId;
|
|
966
|
+
} else {
|
|
967
|
+
const runningCount = activeCount(projectId);
|
|
968
|
+
const launched = runningCount < settings.slotLimit && !settings.queuePaused;
|
|
969
|
+
setTaskRunState(taskId, launched ? "running" : "queued");
|
|
970
|
+
if (task.schedule) {
|
|
971
|
+
clearTaskSchedule(taskId);
|
|
972
|
+
}
|
|
973
|
+
if (launched) {
|
|
974
|
+
const seeded = await seedSession(projectId, task, from, reusableTarget(projectId, opts.sessionId));
|
|
975
|
+
addTaskLink(taskId, seeded.session.id, true);
|
|
976
|
+
addAuditEntry(taskId, opts.actor, "move", `Moved to In Progress (running)`, opts.actorName);
|
|
977
|
+
sessionId = seeded.session.id;
|
|
978
|
+
} else {
|
|
979
|
+
appendToBottom(taskId, "in_progress");
|
|
980
|
+
const earmarked = reusableTarget(projectId, opts.sessionId);
|
|
981
|
+
if (earmarked) addTaskLink(taskId, earmarked, false);
|
|
982
|
+
addAuditEntry(taskId, opts.actor, "move", `Moved to In Progress (queued)`, opts.actorName);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
} else if (to === "done") {
|
|
986
|
+
const doneGates = requiredGates(projectId, "done");
|
|
987
|
+
const missing = missingGateFields(task, doneGates);
|
|
988
|
+
if (missing.length > 0) {
|
|
989
|
+
throw gateBlockedError(task, "Done", missing);
|
|
990
|
+
}
|
|
991
|
+
setTaskStatus(taskId, "done");
|
|
992
|
+
clearActiveTaskLink(taskId);
|
|
993
|
+
if (task.schedule) clearTaskSchedule(taskId);
|
|
994
|
+
addAuditEntry(taskId, opts.actor, "move", `Moved to Done`, opts.actorName);
|
|
995
|
+
if (task.activeSessionId) {
|
|
996
|
+
emitReminder(task.activeSessionId, reminderForDone(task));
|
|
997
|
+
}
|
|
998
|
+
} else {
|
|
999
|
+
setTaskStatus(taskId, "todo");
|
|
1000
|
+
removeTaskLinks(taskId);
|
|
1001
|
+
const detailParts = [`Moved back to To Do`];
|
|
1002
|
+
if (opts.reason) detailParts.push(`Reason: ${opts.reason}`);
|
|
1003
|
+
addAuditEntry(taskId, opts.actor, "move", detailParts.join(". "), opts.actorName);
|
|
1004
|
+
if (task.activeSessionId) {
|
|
1005
|
+
emitReminder(task.activeSessionId, reminderForTodo(task));
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
const fresh = getTask(taskId);
|
|
1009
|
+
let autoLaunched;
|
|
1010
|
+
if (wasRunning || to === "todo" && from === "in_progress") {
|
|
1011
|
+
autoLaunched = await maybeAutoLaunch(projectId);
|
|
1012
|
+
}
|
|
1013
|
+
publish(projectId, fresh.id, autoLaunched);
|
|
1014
|
+
return {
|
|
1015
|
+
task: fresh,
|
|
1016
|
+
...sessionId ? { sessionId } : {},
|
|
1017
|
+
...autoLaunched ? { autoLaunched } : {}
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
async function runScheduled(now = /* @__PURE__ */ new Date()) {
|
|
1021
|
+
const due = listDueScheduledTasks(now.toISOString());
|
|
1022
|
+
for (const task of due) {
|
|
1023
|
+
try {
|
|
1024
|
+
await withLock(task.projectId, async () => {
|
|
1025
|
+
const fresh = getTask(task.id);
|
|
1026
|
+
if (!fresh || fresh.status !== "todo" || !fresh.schedule) return;
|
|
1027
|
+
const schedule = fresh.schedule;
|
|
1028
|
+
if (schedule.type === "once") {
|
|
1029
|
+
await moveLocked(fresh.projectId, fresh.id, "in_progress", { actor: "system" });
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
const readyGates = requiredGates(fresh.projectId, "ready");
|
|
1033
|
+
if (missingGateFields(fresh, readyGates).length > 0) {
|
|
1034
|
+
logger.warn("Scheduled recurring spawn skipped: missing ready gates", {
|
|
1035
|
+
taskId: fresh.id,
|
|
1036
|
+
gates: readyGates.map((g) => g.name).join(", ")
|
|
1037
|
+
});
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
const run = cloneTask(fresh.id, false);
|
|
1041
|
+
if (run) {
|
|
1042
|
+
try {
|
|
1043
|
+
await moveLocked(run.projectId, run.id, "in_progress", { actor: "system" });
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
deleteTask(run.id);
|
|
1046
|
+
throw error;
|
|
1047
|
+
}
|
|
1048
|
+
addAuditEntry(
|
|
1049
|
+
run.id,
|
|
1050
|
+
"system",
|
|
1051
|
+
"scheduled_run",
|
|
1052
|
+
`Spawned from recurring task "${promptLabel(fresh.prompt)}"`,
|
|
1053
|
+
"system"
|
|
819
1054
|
);
|
|
820
1055
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1056
|
+
const rule = {
|
|
1057
|
+
freq: schedule.freq,
|
|
1058
|
+
interval: schedule.interval,
|
|
1059
|
+
...schedule.weekdays ? { weekdays: schedule.weekdays } : {},
|
|
1060
|
+
...schedule.monthDay ? { monthDay: schedule.monthDay } : {},
|
|
1061
|
+
...schedule.yearMonth ? { yearMonth: schedule.yearMonth } : {},
|
|
1062
|
+
startAt: schedule.startAt,
|
|
1063
|
+
end: schedule.end,
|
|
1064
|
+
occurrencesDone: schedule.occurrencesDone + 1
|
|
1065
|
+
};
|
|
1066
|
+
const next = nextOccurrence(now, rule);
|
|
1067
|
+
if (next) {
|
|
1068
|
+
const advanced = {
|
|
1069
|
+
...schedule,
|
|
1070
|
+
occurrencesDone: schedule.occurrencesDone + 1,
|
|
1071
|
+
nextRunAt: next.toISOString()
|
|
1072
|
+
};
|
|
1073
|
+
setTaskSchedule(fresh.id, advanced, next.toISOString());
|
|
1074
|
+
addAuditEntry(
|
|
1075
|
+
fresh.id,
|
|
1076
|
+
"system",
|
|
1077
|
+
"scheduled_run",
|
|
1078
|
+
`Triggered occurrence ${schedule.occurrencesDone + 1}, next run ${next.toISOString()}`,
|
|
1079
|
+
"system"
|
|
1080
|
+
);
|
|
835
1081
|
} else {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (earmarked) addTaskLink(taskId, earmarked, false);
|
|
839
|
-
addAuditEntry(taskId, "human", "move", `Moved to In Progress (queued)`, opts.actorName);
|
|
1082
|
+
clearTaskSchedule(fresh.id);
|
|
1083
|
+
addAuditEntry(fresh.id, "system", "schedule_ended", "Recurrence ended \u2014 schedule cleared", "system");
|
|
840
1084
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (missing.length > 0) {
|
|
846
|
-
throw gateBlockedError(task, "Done", missing);
|
|
847
|
-
}
|
|
848
|
-
setTaskStatus(taskId, "done");
|
|
849
|
-
clearActiveTaskLink(taskId);
|
|
850
|
-
addAuditEntry(taskId, opts.actor, "move", `Moved to Done`, opts.actorName);
|
|
851
|
-
if (task.activeSessionId) {
|
|
852
|
-
emitReminder(task.activeSessionId, reminderForDone(task));
|
|
853
|
-
}
|
|
854
|
-
} else {
|
|
855
|
-
setTaskStatus(taskId, "todo");
|
|
856
|
-
removeTaskLinks(taskId);
|
|
857
|
-
const detailParts = [`Moved back to To Do`];
|
|
858
|
-
if (opts.reason) detailParts.push(`Reason: ${opts.reason}`);
|
|
859
|
-
addAuditEntry(taskId, opts.actor, "move", detailParts.join(". "), opts.actorName);
|
|
860
|
-
if (task.activeSessionId) {
|
|
861
|
-
emitReminder(task.activeSessionId, reminderForTodo(task));
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
const fresh = getTask(taskId);
|
|
865
|
-
let autoLaunched;
|
|
866
|
-
if (wasRunning || to === "todo" && from === "in_progress") {
|
|
867
|
-
autoLaunched = await maybeAutoLaunch(projectId);
|
|
1085
|
+
publish(fresh.projectId, fresh.id);
|
|
1086
|
+
});
|
|
1087
|
+
} catch (error) {
|
|
1088
|
+
logger.warn("Scheduled task trigger failed", { taskId: task.id, error: String(error) });
|
|
868
1089
|
}
|
|
869
|
-
|
|
870
|
-
return {
|
|
871
|
-
task: fresh,
|
|
872
|
-
...sessionId ? { sessionId } : {},
|
|
873
|
-
...autoLaunched ? { autoLaunched } : {}
|
|
874
|
-
};
|
|
875
|
-
});
|
|
1090
|
+
}
|
|
876
1091
|
}
|
|
877
1092
|
function setGateValue2(projectId, taskId, gateId, value, actor, sessionId, expectedVersion) {
|
|
878
1093
|
return withLock(projectId, () => {
|
|
@@ -1106,7 +1321,105 @@ ${evidenceLine}`,
|
|
|
1106
1321
|
setGateConfig,
|
|
1107
1322
|
setSettings,
|
|
1108
1323
|
reorder,
|
|
1109
|
-
counts
|
|
1324
|
+
counts,
|
|
1325
|
+
runScheduled
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function normalizeSchedule(input) {
|
|
1329
|
+
if (input.type === "once") {
|
|
1330
|
+
if (!Number.isFinite(new Date(input.runAt).getTime())) {
|
|
1331
|
+
throw new Error(
|
|
1332
|
+
serverT(
|
|
1333
|
+
{ en: "Invalid schedule time: {{time}}", fr: "Heure de planification invalide : {{time}}" },
|
|
1334
|
+
{
|
|
1335
|
+
time: input.runAt
|
|
1336
|
+
}
|
|
1337
|
+
)
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
return { type: "once", runAt: input.runAt };
|
|
1341
|
+
}
|
|
1342
|
+
const { freq, interval, startAt, end } = input;
|
|
1343
|
+
if (!Number.isInteger(interval) || interval < 1) {
|
|
1344
|
+
throw new Error(
|
|
1345
|
+
serverT({
|
|
1346
|
+
en: "Recurring interval must be a positive integer",
|
|
1347
|
+
fr: "L\u2019intervalle de r\xE9currence doit \xEAtre un entier positif"
|
|
1348
|
+
})
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
if (freq === "week") {
|
|
1352
|
+
const days = input.weekdays ?? [];
|
|
1353
|
+
if (days.length === 0 || !days.every((d) => Number.isInteger(d) && d >= 0 && d <= 6)) {
|
|
1354
|
+
throw new Error(
|
|
1355
|
+
serverT({
|
|
1356
|
+
en: "Weekly recurrence requires at least one selected weekday",
|
|
1357
|
+
fr: "La r\xE9currence hebdomadaire requiert au moins un jour de la semaine s\xE9lectionn\xE9"
|
|
1358
|
+
})
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
if ((freq === "month" || freq === "year") && input.monthDay !== void 0) {
|
|
1363
|
+
if (!Number.isInteger(input.monthDay) || input.monthDay < 1 || input.monthDay > 31) {
|
|
1364
|
+
throw new Error(
|
|
1365
|
+
serverT({
|
|
1366
|
+
en: "Day of month must be between 1 and 31",
|
|
1367
|
+
fr: "Le jour du mois doit \xEAtre compris entre 1 et 31"
|
|
1368
|
+
})
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
if (freq === "year" && input.yearMonth !== void 0) {
|
|
1373
|
+
if (!Number.isInteger(input.yearMonth) || input.yearMonth < 1 || input.yearMonth > 12) {
|
|
1374
|
+
throw new Error(
|
|
1375
|
+
serverT({
|
|
1376
|
+
en: "Month must be between 1 and 12",
|
|
1377
|
+
fr: "Le mois doit \xEAtre compris entre 1 et 12"
|
|
1378
|
+
})
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
if (!Number.isFinite(new Date(startAt).getTime())) {
|
|
1383
|
+
throw new Error(
|
|
1384
|
+
serverT(
|
|
1385
|
+
{
|
|
1386
|
+
en: "Invalid schedule start time: {{time}}",
|
|
1387
|
+
fr: "Heure de d\xE9part de planification invalide : {{time}}"
|
|
1388
|
+
},
|
|
1389
|
+
{ time: startAt }
|
|
1390
|
+
)
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
if (end.kind === "until" && !Number.isFinite(new Date(end.until).getTime())) {
|
|
1394
|
+
throw new Error(
|
|
1395
|
+
serverT(
|
|
1396
|
+
{
|
|
1397
|
+
en: "Invalid recurrence end date: {{time}}",
|
|
1398
|
+
fr: "Date de fin de r\xE9currence invalide : {{time}}"
|
|
1399
|
+
},
|
|
1400
|
+
{ time: end.until }
|
|
1401
|
+
)
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
if (end.kind === "count" && (!Number.isInteger(end.count) || end.count < 1)) {
|
|
1405
|
+
throw new Error(
|
|
1406
|
+
serverT({
|
|
1407
|
+
en: "Occurrence count must be a positive integer",
|
|
1408
|
+
fr: "Le nombre d\u2019occurrences doit \xEAtre un entier positif"
|
|
1409
|
+
})
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
return {
|
|
1413
|
+
type: "recurring",
|
|
1414
|
+
freq,
|
|
1415
|
+
interval,
|
|
1416
|
+
...input.weekdays ? { weekdays: input.weekdays } : {},
|
|
1417
|
+
...input.monthDay !== void 0 ? { monthDay: input.monthDay } : {},
|
|
1418
|
+
...input.yearMonth !== void 0 ? { yearMonth: input.yearMonth } : {},
|
|
1419
|
+
startAt,
|
|
1420
|
+
end,
|
|
1421
|
+
occurrencesDone: 0,
|
|
1422
|
+
nextRunAt: startAt
|
|
1110
1423
|
};
|
|
1111
1424
|
}
|
|
1112
1425
|
function promptLabel(prompt) {
|
|
@@ -1149,4 +1462,4 @@ export {
|
|
|
1149
1462
|
isTaskGateError,
|
|
1150
1463
|
createTasksService
|
|
1151
1464
|
};
|
|
1152
|
-
//# sourceMappingURL=chunk-
|
|
1465
|
+
//# sourceMappingURL=chunk-CSUMZAYY.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETTINGS_KEYS,
|
|
3
3
|
getSetting
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SKNPOZYP.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -194,4 +194,4 @@ export {
|
|
|
194
194
|
ChatHttpClient,
|
|
195
195
|
OpenAIHttpClient
|
|
196
196
|
};
|
|
197
|
-
//# sourceMappingURL=chunk-
|
|
197
|
+
//# sourceMappingURL=chunk-DNL2NUDB.js.map
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
} from "./chunk-I72ACQ6R.js";
|
|
12
12
|
import {
|
|
13
13
|
getPlatformShell
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MEPTCUYN.js";
|
|
15
15
|
import {
|
|
16
16
|
SETTINGS_KEYS,
|
|
17
17
|
getSetting
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-SKNPOZYP.js";
|
|
19
19
|
|
|
20
20
|
// src/server/utils/shell.ts
|
|
21
21
|
import { spawn } from "child_process";
|
|
@@ -214,4 +214,4 @@ export {
|
|
|
214
214
|
getSessionProcesses2 as getSessionProcesses,
|
|
215
215
|
getProcessLogs
|
|
216
216
|
};
|
|
217
|
-
//# sourceMappingURL=chunk-
|
|
217
|
+
//# sourceMappingURL=chunk-DQEANXXF.js.map
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
} from "./chunk-OSXPQSLW.js";
|
|
4
4
|
import {
|
|
5
5
|
getProjectDefaultAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JYYBSODN.js";
|
|
7
7
|
import {
|
|
8
8
|
SETTINGS_KEYS,
|
|
9
9
|
getSetting
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SKNPOZYP.js";
|
|
11
11
|
import {
|
|
12
12
|
logger
|
|
13
13
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -352,4 +352,4 @@ export {
|
|
|
352
352
|
getOverrideAgentIds,
|
|
353
353
|
resolveDefaultAgentId
|
|
354
354
|
};
|
|
355
|
-
//# sourceMappingURL=chunk-
|
|
355
|
+
//# sourceMappingURL=chunk-DRIR2IZR.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveDefaultAgentId
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DRIR2IZR.js";
|
|
4
4
|
import {
|
|
5
5
|
normalizeAskOptions
|
|
6
6
|
} from "./chunk-LCLH6ZUL.js";
|
|
@@ -983,4 +983,4 @@ export {
|
|
|
983
983
|
buildSnapshot,
|
|
984
984
|
buildSnapshotFromSessionState
|
|
985
985
|
};
|
|
986
|
-
//# sourceMappingURL=chunk-
|
|
986
|
+
//# sourceMappingURL=chunk-EFEHIJXF.js.map
|