forge-openclaw-plugin 0.2.28 → 0.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assets/{board-DPFvZf-D.js → board-q8cfwaAW.js} +2 -2
- package/dist/assets/{board-DPFvZf-D.js.map → board-q8cfwaAW.js.map} +1 -1
- package/dist/assets/index-CPC6E84V.js +85 -0
- package/dist/assets/index-CPC6E84V.js.map +1 -0
- package/dist/assets/index-DiyKCDxL.css +1 -0
- package/dist/assets/{motion-Bvwc85ch.js → motion-DHfqFntt.js} +2 -2
- package/dist/assets/{motion-Bvwc85ch.js.map → motion-DHfqFntt.js.map} +1 -1
- package/dist/assets/{table-FJQTJvUR.js → table-DLweENXt.js} +2 -2
- package/dist/assets/{table-FJQTJvUR.js.map → table-DLweENXt.js.map} +1 -1
- package/dist/assets/{ui-GXFcgvSw.js → ui-BV0OYxkH.js} +2 -2
- package/dist/assets/{ui-GXFcgvSw.js.map → ui-BV0OYxkH.js.map} +1 -1
- package/dist/assets/{vendor-Cwf49UMz.js → vendor-OwcH20PM.js} +2 -2
- package/dist/assets/{vendor-Cwf49UMz.js.map → vendor-OwcH20PM.js.map} +1 -1
- package/dist/index.html +7 -7
- package/dist/server/server/migrations/044_macos_local_calendar_provider.sql +21 -0
- package/dist/server/server/src/app.js +113 -17
- package/dist/server/server/src/movement.js +151 -0
- package/dist/server/server/src/openapi.js +29 -1
- package/dist/server/server/src/repositories/calendar.js +144 -12
- package/dist/server/server/src/repositories/tasks.js +36 -17
- package/dist/server/server/src/services/calendar-runtime.js +613 -32
- package/dist/server/server/src/services/life-force.js +84 -52
- package/dist/server/server/src/services/macos-calendar-helper.js +748 -0
- package/dist/server/server/src/types.js +46 -2
- package/dist/server/src/lib/api-error.js +2 -0
- package/dist/server/src/lib/api.js +51 -2
- package/dist/server/src/lib/calendar-name-deduper.js +2 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/migrations/044_macos_local_calendar_provider.sql +21 -0
- package/skills/forge-openclaw/SKILL.md +40 -7
- package/skills/forge-openclaw/entity_conversation_playbooks.md +88 -5
- package/dist/assets/index-Auw3JrdE.css +0 -1
- package/dist/assets/index-D1H7myQH.js +0 -85
- package/dist/assets/index-D1H7myQH.js.map +0 -1
|
@@ -234,6 +234,15 @@ function computeUncoveredSeconds(window, blockingWindows) {
|
|
|
234
234
|
coveredMs += activeEndMs - activeStartMs;
|
|
235
235
|
return Math.max(0, totalSeconds - Math.floor(coveredMs / 1000));
|
|
236
236
|
}
|
|
237
|
+
function containsInstant(window, instantIso) {
|
|
238
|
+
const instantMs = Date.parse(instantIso);
|
|
239
|
+
return (Number.isFinite(instantMs) &&
|
|
240
|
+
Date.parse(window.startAt) <= instantMs &&
|
|
241
|
+
Date.parse(window.endAt) > instantMs);
|
|
242
|
+
}
|
|
243
|
+
function isInstantCovered(instantIso, blockingWindows) {
|
|
244
|
+
return blockingWindows.some((window) => containsInstant(window, instantIso));
|
|
245
|
+
}
|
|
237
246
|
function nowIso() {
|
|
238
247
|
return new Date().toISOString();
|
|
239
248
|
}
|
|
@@ -1635,6 +1644,36 @@ function readTaskTimeboxLifeForceRows(userId, range) {
|
|
|
1635
1644
|
return [];
|
|
1636
1645
|
}
|
|
1637
1646
|
}
|
|
1647
|
+
function readCalendarEventLifeForceRows(range) {
|
|
1648
|
+
try {
|
|
1649
|
+
return getDatabase()
|
|
1650
|
+
.prepare(`SELECT
|
|
1651
|
+
forge_events.id,
|
|
1652
|
+
forge_events.title,
|
|
1653
|
+
forge_events.start_at,
|
|
1654
|
+
forge_events.end_at,
|
|
1655
|
+
forge_events.availability,
|
|
1656
|
+
forge_events.event_type,
|
|
1657
|
+
COUNT(forge_event_links.id) AS link_count
|
|
1658
|
+
FROM forge_events
|
|
1659
|
+
LEFT JOIN forge_event_links
|
|
1660
|
+
ON forge_event_links.forge_event_id = forge_events.id
|
|
1661
|
+
WHERE forge_events.deleted_at IS NULL
|
|
1662
|
+
AND forge_events.end_at > ?
|
|
1663
|
+
AND forge_events.start_at < ?
|
|
1664
|
+
GROUP BY
|
|
1665
|
+
forge_events.id,
|
|
1666
|
+
forge_events.title,
|
|
1667
|
+
forge_events.start_at,
|
|
1668
|
+
forge_events.end_at,
|
|
1669
|
+
forge_events.availability,
|
|
1670
|
+
forge_events.event_type`)
|
|
1671
|
+
.all(range.from, range.to);
|
|
1672
|
+
}
|
|
1673
|
+
catch {
|
|
1674
|
+
return [];
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1638
1677
|
function readWorkBlockTemplateLifeForceRows(userId) {
|
|
1639
1678
|
try {
|
|
1640
1679
|
return getDatabase()
|
|
@@ -1717,7 +1756,7 @@ function buildWorkBlockProfile(input) {
|
|
|
1717
1756
|
endMinute
|
|
1718
1757
|
});
|
|
1719
1758
|
}
|
|
1720
|
-
function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, activeTaskRunTaskIds, actualSourceWindows) {
|
|
1759
|
+
function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, activeTaskRunTaskIds, actualSourceWindows, calendarEventWindows) {
|
|
1721
1760
|
const actualContributions = [];
|
|
1722
1761
|
const plannedDrains = [];
|
|
1723
1762
|
const activeDrains = [];
|
|
@@ -1756,11 +1795,12 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1756
1795
|
startsAt: row.starts_at,
|
|
1757
1796
|
endsAt: row.ends_at
|
|
1758
1797
|
});
|
|
1798
|
+
const higherPriorityWindows = [...actualSourceWindows, ...calendarEventWindows];
|
|
1759
1799
|
const elapsedWindow = {
|
|
1760
1800
|
startAt: row.starts_at,
|
|
1761
1801
|
endAt: new Date(Math.min(now.getTime(), Date.parse(row.ends_at))).toISOString()
|
|
1762
1802
|
};
|
|
1763
|
-
const elapsedSeconds = computeUncoveredSeconds(elapsedWindow,
|
|
1803
|
+
const elapsedSeconds = computeUncoveredSeconds(elapsedWindow, higherPriorityWindows);
|
|
1764
1804
|
if (elapsedSeconds > 0) {
|
|
1765
1805
|
actualContributions.push({
|
|
1766
1806
|
entityType: "task_timebox",
|
|
@@ -1778,7 +1818,15 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1778
1818
|
}
|
|
1779
1819
|
const remainingStartMs = Math.max(now.getTime(), Date.parse(row.starts_at));
|
|
1780
1820
|
const remainingEndMs = Math.min(range.endMs, Date.parse(row.ends_at));
|
|
1781
|
-
const
|
|
1821
|
+
const remainingWindow = remainingEndMs > remainingStartMs
|
|
1822
|
+
? {
|
|
1823
|
+
startAt: new Date(remainingStartMs).toISOString(),
|
|
1824
|
+
endAt: new Date(remainingEndMs).toISOString()
|
|
1825
|
+
}
|
|
1826
|
+
: null;
|
|
1827
|
+
const remainingSeconds = remainingWindow
|
|
1828
|
+
? computeUncoveredSeconds(remainingWindow, higherPriorityWindows)
|
|
1829
|
+
: 0;
|
|
1782
1830
|
if (remainingSeconds > 0) {
|
|
1783
1831
|
plannedDrains.push({
|
|
1784
1832
|
entityType: "task_timebox",
|
|
@@ -1789,15 +1837,15 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1789
1837
|
rateApPerHour: profile.sustainRateApPerHour,
|
|
1790
1838
|
title: row.title,
|
|
1791
1839
|
why: "Planned task timeboxes forecast how much Action Point throughput is still booked today.",
|
|
1792
|
-
startsAt: row.starts_at,
|
|
1793
|
-
endsAt: row.ends_at,
|
|
1840
|
+
startsAt: remainingWindow?.startAt ?? row.starts_at,
|
|
1841
|
+
endsAt: remainingWindow?.endAt ?? row.ends_at,
|
|
1794
1842
|
role: "secondary"
|
|
1795
1843
|
});
|
|
1796
1844
|
}
|
|
1797
1845
|
if (Date.parse(row.starts_at) <= now.getTime() &&
|
|
1798
1846
|
Date.parse(row.ends_at) > now.getTime() &&
|
|
1799
1847
|
!activeTaskRunTaskIds.has(row.task_id) &&
|
|
1800
|
-
!
|
|
1848
|
+
!isInstantCovered(now.toISOString(), higherPriorityWindows)) {
|
|
1801
1849
|
activeDrains.push({
|
|
1802
1850
|
entityType: "task_timebox",
|
|
1803
1851
|
entityId: row.id,
|
|
@@ -1819,8 +1867,11 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1819
1867
|
startAt: block.start_at,
|
|
1820
1868
|
endAt: block.end_at
|
|
1821
1869
|
});
|
|
1822
|
-
const
|
|
1823
|
-
|
|
1870
|
+
const higherPriorityWindows = [
|
|
1871
|
+
...actualSourceWindows,
|
|
1872
|
+
...calendarEventWindows,
|
|
1873
|
+
...timeboxWindows
|
|
1874
|
+
];
|
|
1824
1875
|
const profile = buildEffectiveProfile(buildWorkBlockProfile({
|
|
1825
1876
|
templateId: block.id,
|
|
1826
1877
|
title: block.title,
|
|
@@ -1832,11 +1883,8 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1832
1883
|
startAt: block.start_at,
|
|
1833
1884
|
endAt: new Date(Math.min(now.getTime(), Date.parse(block.end_at))).toISOString()
|
|
1834
1885
|
};
|
|
1835
|
-
const elapsedSeconds = computeUncoveredSeconds(elapsedWindow,
|
|
1836
|
-
|
|
1837
|
-
...timeboxWindows
|
|
1838
|
-
]);
|
|
1839
|
-
if (elapsedSeconds > 0 && !overlapsTimebox) {
|
|
1886
|
+
const elapsedSeconds = computeUncoveredSeconds(elapsedWindow, higherPriorityWindows);
|
|
1887
|
+
if (elapsedSeconds > 0) {
|
|
1840
1888
|
actualContributions.push({
|
|
1841
1889
|
entityType: "work_block",
|
|
1842
1890
|
entityId: block.instance_id,
|
|
@@ -1857,8 +1905,16 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1857
1905
|
}
|
|
1858
1906
|
const remainingStartMs = Math.max(now.getTime(), Date.parse(block.start_at));
|
|
1859
1907
|
const remainingEndMs = Math.min(range.endMs, Date.parse(block.end_at));
|
|
1860
|
-
const
|
|
1861
|
-
|
|
1908
|
+
const remainingWindow = remainingEndMs > remainingStartMs
|
|
1909
|
+
? {
|
|
1910
|
+
startAt: new Date(remainingStartMs).toISOString(),
|
|
1911
|
+
endAt: new Date(remainingEndMs).toISOString()
|
|
1912
|
+
}
|
|
1913
|
+
: null;
|
|
1914
|
+
const remainingSeconds = remainingWindow
|
|
1915
|
+
? computeUncoveredSeconds(remainingWindow, higherPriorityWindows)
|
|
1916
|
+
: 0;
|
|
1917
|
+
if (remainingSeconds > 0) {
|
|
1862
1918
|
plannedDrains.push({
|
|
1863
1919
|
entityType: "work_block",
|
|
1864
1920
|
entityId: block.instance_id,
|
|
@@ -1868,8 +1924,8 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1868
1924
|
rateApPerHour: profile.sustainRateApPerHour,
|
|
1869
1925
|
title: block.title,
|
|
1870
1926
|
why: "Work blocks act as planning containers and forecast background load when no richer task plan exists.",
|
|
1871
|
-
startsAt: block.start_at,
|
|
1872
|
-
endsAt: block.end_at,
|
|
1927
|
+
startsAt: remainingWindow?.startAt ?? block.start_at,
|
|
1928
|
+
endsAt: remainingWindow?.endAt ?? block.end_at,
|
|
1873
1929
|
role: "background",
|
|
1874
1930
|
metadata: {
|
|
1875
1931
|
templateId: block.id,
|
|
@@ -1879,9 +1935,8 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1879
1935
|
}
|
|
1880
1936
|
if (Date.parse(block.start_at) <= now.getTime() &&
|
|
1881
1937
|
Date.parse(block.end_at) > now.getTime() &&
|
|
1882
|
-
!overlapsTimebox &&
|
|
1883
1938
|
activeTaskRunTaskIds.size === 0 &&
|
|
1884
|
-
!
|
|
1939
|
+
!isInstantCovered(now.toISOString(), higherPriorityWindows)) {
|
|
1885
1940
|
activeDrains.push({
|
|
1886
1941
|
entityType: "work_block",
|
|
1887
1942
|
entityId: block.instance_id,
|
|
@@ -1909,35 +1964,12 @@ function buildTimeboxAndWorkBlockDrains(userId, range, now, lifeForceProfile, ac
|
|
|
1909
1964
|
workBlockWindows
|
|
1910
1965
|
};
|
|
1911
1966
|
}
|
|
1912
|
-
function buildCalendarDrains(
|
|
1967
|
+
function buildCalendarDrains(rows, now, range, lifeForceProfile, blockingWindows) {
|
|
1913
1968
|
const actualContributions = [];
|
|
1914
1969
|
const nowIsoValue = now.toISOString();
|
|
1915
1970
|
const activeDrains = [];
|
|
1916
1971
|
const plannedDrains = [];
|
|
1917
1972
|
try {
|
|
1918
|
-
const rows = getDatabase()
|
|
1919
|
-
.prepare(`SELECT
|
|
1920
|
-
forge_events.id,
|
|
1921
|
-
forge_events.title,
|
|
1922
|
-
forge_events.start_at,
|
|
1923
|
-
forge_events.end_at,
|
|
1924
|
-
forge_events.availability,
|
|
1925
|
-
forge_events.event_type,
|
|
1926
|
-
COUNT(forge_event_links.id) AS link_count
|
|
1927
|
-
FROM forge_events
|
|
1928
|
-
LEFT JOIN forge_event_links
|
|
1929
|
-
ON forge_event_links.forge_event_id = forge_events.id
|
|
1930
|
-
WHERE forge_events.deleted_at IS NULL
|
|
1931
|
-
AND forge_events.end_at > ?
|
|
1932
|
-
AND forge_events.start_at < ?
|
|
1933
|
-
GROUP BY
|
|
1934
|
-
forge_events.id,
|
|
1935
|
-
forge_events.title,
|
|
1936
|
-
forge_events.start_at,
|
|
1937
|
-
forge_events.end_at,
|
|
1938
|
-
forge_events.availability,
|
|
1939
|
-
forge_events.event_type`)
|
|
1940
|
-
.all(range.from, range.to);
|
|
1941
1973
|
for (const row of rows) {
|
|
1942
1974
|
const calendarProfile = buildEffectiveProfile(readEntityActionProfile("calendar_event", row.id, {
|
|
1943
1975
|
profileKey: `calendar_event_${row.id}`,
|
|
@@ -1952,7 +1984,6 @@ function buildCalendarDrains(userId, now, range, lifeForceProfile, blockingWindo
|
|
|
1952
1984
|
startAt: row.start_at,
|
|
1953
1985
|
endAt: row.end_at
|
|
1954
1986
|
}), lifeForceProfile);
|
|
1955
|
-
const overlapsBlockingWindow = blockingWindows.some((window) => overlapsWindow(row.start_at, row.end_at, window.startAt, window.endAt));
|
|
1956
1987
|
const elapsedWindow = {
|
|
1957
1988
|
startAt: row.start_at,
|
|
1958
1989
|
endAt: new Date(Math.min(now.getTime(), Date.parse(row.end_at))).toISOString()
|
|
@@ -1993,7 +2024,7 @@ function buildCalendarDrains(userId, now, range, lifeForceProfile, blockingWindo
|
|
|
1993
2024
|
}
|
|
1994
2025
|
if (row.start_at <= nowIsoValue &&
|
|
1995
2026
|
row.end_at > nowIsoValue &&
|
|
1996
|
-
!
|
|
2027
|
+
!isInstantCovered(nowIsoValue, blockingWindows)) {
|
|
1997
2028
|
activeDrains.push({
|
|
1998
2029
|
entityType: "calendar_event",
|
|
1999
2030
|
entityId: row.id,
|
|
@@ -2172,14 +2203,15 @@ export function buildLifeForcePayload(now = new Date(), userIds) {
|
|
|
2172
2203
|
startAt: entry.startsAt,
|
|
2173
2204
|
endAt: entry.endsAt
|
|
2174
2205
|
}));
|
|
2206
|
+
const calendarRows = readCalendarEventLifeForceRows(range);
|
|
2207
|
+
const calendarEventWindows = calendarRows.map((row) => ({
|
|
2208
|
+
startAt: row.start_at,
|
|
2209
|
+
endAt: row.end_at
|
|
2210
|
+
}));
|
|
2175
2211
|
const activeTaskRunTaskIds = new Set(taskRuns.activeDrains.map((entry) => entry.entityId));
|
|
2176
|
-
const plannedContainers = buildTimeboxAndWorkBlockDrains(user.id, range, now, profile, activeTaskRunTaskIds, actualSourceWindows);
|
|
2177
|
-
const calendarBlockingWindows = [
|
|
2178
|
-
|
|
2179
|
-
...plannedContainers.timeboxWindows,
|
|
2180
|
-
...plannedContainers.workBlockWindows
|
|
2181
|
-
];
|
|
2182
|
-
const calendarDrains = buildCalendarDrains(user.id, now, range, profile, calendarBlockingWindows);
|
|
2212
|
+
const plannedContainers = buildTimeboxAndWorkBlockDrains(user.id, range, now, profile, activeTaskRunTaskIds, actualSourceWindows, calendarEventWindows);
|
|
2213
|
+
const calendarBlockingWindows = [...actualSourceWindows];
|
|
2214
|
+
const calendarDrains = buildCalendarDrains(calendarRows, now, range, profile, calendarBlockingWindows);
|
|
2183
2215
|
const contributions = [
|
|
2184
2216
|
...taskRuns.contributions,
|
|
2185
2217
|
...adjustments,
|