@positronic/cloudflare 0.0.20 → 0.0.22
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/src/api.js +506 -1
- package/dist/src/brain-runner-do.js +9 -4
- package/dist/src/monitor-do.js +42 -2
- package/dist/src/page-adapter.js +282 -0
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/brain-runner-do.d.ts.map +1 -1
- package/dist/types/monitor-do.d.ts +19 -0
- package/dist/types/monitor-do.d.ts.map +1 -1
- package/dist/types/page-adapter.d.ts +16 -0
- package/dist/types/page-adapter.d.ts.map +1 -0
- package/package.json +4 -4
package/dist/src/api.js
CHANGED
|
@@ -1591,7 +1591,16 @@ app.post('/webhooks/:slug', function(context) {
|
|
|
1591
1591
|
];
|
|
1592
1592
|
case 2:
|
|
1593
1593
|
result = _state.sent();
|
|
1594
|
-
//
|
|
1594
|
+
// Handle verification challenge (for Slack, Stripe, GitHub, Discord)
|
|
1595
|
+
if (result.type === 'verification') {
|
|
1596
|
+
return [
|
|
1597
|
+
2,
|
|
1598
|
+
context.json({
|
|
1599
|
+
challenge: result.challenge
|
|
1600
|
+
})
|
|
1601
|
+
];
|
|
1602
|
+
}
|
|
1603
|
+
// Normal webhook processing - check if there's a brain waiting
|
|
1595
1604
|
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
1596
1605
|
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
1597
1606
|
return [
|
|
@@ -1651,4 +1660,500 @@ app.post('/webhooks/:slug', function(context) {
|
|
|
1651
1660
|
});
|
|
1652
1661
|
})();
|
|
1653
1662
|
});
|
|
1663
|
+
// Create a new page
|
|
1664
|
+
app.post('/pages', function(context) {
|
|
1665
|
+
return _async_to_generator(function() {
|
|
1666
|
+
var body, slug, html, brainRunId, _body_persist, persist, ttl, bucket, key, createdAt, metadata, monitorId, monitorStub, url, pageUrl, error;
|
|
1667
|
+
return _ts_generator(this, function(_state) {
|
|
1668
|
+
switch(_state.label){
|
|
1669
|
+
case 0:
|
|
1670
|
+
_state.trys.push([
|
|
1671
|
+
0,
|
|
1672
|
+
4,
|
|
1673
|
+
,
|
|
1674
|
+
5
|
|
1675
|
+
]);
|
|
1676
|
+
return [
|
|
1677
|
+
4,
|
|
1678
|
+
context.req.json()
|
|
1679
|
+
];
|
|
1680
|
+
case 1:
|
|
1681
|
+
body = _state.sent();
|
|
1682
|
+
slug = body.slug, html = body.html, brainRunId = body.brainRunId, _body_persist = body.persist, persist = _body_persist === void 0 ? false : _body_persist, ttl = body.ttl;
|
|
1683
|
+
if (!slug) {
|
|
1684
|
+
return [
|
|
1685
|
+
2,
|
|
1686
|
+
context.json({
|
|
1687
|
+
error: 'Missing required field "slug"'
|
|
1688
|
+
}, 400)
|
|
1689
|
+
];
|
|
1690
|
+
}
|
|
1691
|
+
if (!html) {
|
|
1692
|
+
return [
|
|
1693
|
+
2,
|
|
1694
|
+
context.json({
|
|
1695
|
+
error: 'Missing required field "html"'
|
|
1696
|
+
}, 400)
|
|
1697
|
+
];
|
|
1698
|
+
}
|
|
1699
|
+
if (!brainRunId) {
|
|
1700
|
+
return [
|
|
1701
|
+
2,
|
|
1702
|
+
context.json({
|
|
1703
|
+
error: 'Missing required field "brainRunId"'
|
|
1704
|
+
}, 400)
|
|
1705
|
+
];
|
|
1706
|
+
}
|
|
1707
|
+
// Validate slug format (alphanumeric, hyphens, underscores only)
|
|
1708
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(slug)) {
|
|
1709
|
+
return [
|
|
1710
|
+
2,
|
|
1711
|
+
context.json({
|
|
1712
|
+
error: 'Slug must contain only alphanumeric characters, hyphens, and underscores'
|
|
1713
|
+
}, 400)
|
|
1714
|
+
];
|
|
1715
|
+
}
|
|
1716
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
1717
|
+
key = "pages/".concat(slug, ".html");
|
|
1718
|
+
createdAt = new Date().toISOString();
|
|
1719
|
+
// Store HTML with metadata
|
|
1720
|
+
metadata = _object_spread({
|
|
1721
|
+
slug: slug,
|
|
1722
|
+
brainRunId: brainRunId,
|
|
1723
|
+
persist: persist === true,
|
|
1724
|
+
createdAt: createdAt
|
|
1725
|
+
}, ttl !== undefined && {
|
|
1726
|
+
ttl: Number(ttl)
|
|
1727
|
+
});
|
|
1728
|
+
return [
|
|
1729
|
+
4,
|
|
1730
|
+
bucket.put(key, html, {
|
|
1731
|
+
httpMetadata: {
|
|
1732
|
+
contentType: 'text/html; charset=utf-8'
|
|
1733
|
+
},
|
|
1734
|
+
customMetadata: _object_spread({
|
|
1735
|
+
slug: slug,
|
|
1736
|
+
brainRunId: brainRunId,
|
|
1737
|
+
persist: persist === true ? 'true' : 'false',
|
|
1738
|
+
createdAt: createdAt
|
|
1739
|
+
}, ttl !== undefined && {
|
|
1740
|
+
ttl: String(ttl)
|
|
1741
|
+
})
|
|
1742
|
+
})
|
|
1743
|
+
];
|
|
1744
|
+
case 2:
|
|
1745
|
+
_state.sent();
|
|
1746
|
+
// Register the page with MonitorDO for cleanup tracking
|
|
1747
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
1748
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
1749
|
+
return [
|
|
1750
|
+
4,
|
|
1751
|
+
monitorStub.registerPage(slug, brainRunId, persist === true)
|
|
1752
|
+
];
|
|
1753
|
+
case 3:
|
|
1754
|
+
_state.sent();
|
|
1755
|
+
// Build the public URL for this page
|
|
1756
|
+
url = new URL(context.req.url);
|
|
1757
|
+
pageUrl = "".concat(url.protocol, "//").concat(url.host, "/pages/").concat(slug);
|
|
1758
|
+
return [
|
|
1759
|
+
2,
|
|
1760
|
+
context.json(_object_spread_props(_object_spread({
|
|
1761
|
+
slug: slug,
|
|
1762
|
+
url: pageUrl,
|
|
1763
|
+
brainRunId: brainRunId,
|
|
1764
|
+
persist: persist === true
|
|
1765
|
+
}, ttl !== undefined && {
|
|
1766
|
+
ttl: Number(ttl)
|
|
1767
|
+
}), {
|
|
1768
|
+
createdAt: createdAt
|
|
1769
|
+
}), 201)
|
|
1770
|
+
];
|
|
1771
|
+
case 4:
|
|
1772
|
+
error = _state.sent();
|
|
1773
|
+
console.error('Error creating page:', error);
|
|
1774
|
+
return [
|
|
1775
|
+
2,
|
|
1776
|
+
context.json({
|
|
1777
|
+
error: "Failed to create page: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
1778
|
+
}, 500)
|
|
1779
|
+
];
|
|
1780
|
+
case 5:
|
|
1781
|
+
return [
|
|
1782
|
+
2
|
|
1783
|
+
];
|
|
1784
|
+
}
|
|
1785
|
+
});
|
|
1786
|
+
})();
|
|
1787
|
+
});
|
|
1788
|
+
// List all pages
|
|
1789
|
+
app.get('/pages', function(context) {
|
|
1790
|
+
return _async_to_generator(function() {
|
|
1791
|
+
var bucket, listed, pages, validPages, error;
|
|
1792
|
+
return _ts_generator(this, function(_state) {
|
|
1793
|
+
switch(_state.label){
|
|
1794
|
+
case 0:
|
|
1795
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
1796
|
+
_state.label = 1;
|
|
1797
|
+
case 1:
|
|
1798
|
+
_state.trys.push([
|
|
1799
|
+
1,
|
|
1800
|
+
4,
|
|
1801
|
+
,
|
|
1802
|
+
5
|
|
1803
|
+
]);
|
|
1804
|
+
return [
|
|
1805
|
+
4,
|
|
1806
|
+
bucket.list({
|
|
1807
|
+
prefix: 'pages/'
|
|
1808
|
+
})
|
|
1809
|
+
];
|
|
1810
|
+
case 2:
|
|
1811
|
+
listed = _state.sent();
|
|
1812
|
+
return [
|
|
1813
|
+
4,
|
|
1814
|
+
Promise.all(listed.objects.map(function(object) {
|
|
1815
|
+
return _async_to_generator(function() {
|
|
1816
|
+
var r2Object, metadata, slug, url, pageUrl;
|
|
1817
|
+
return _ts_generator(this, function(_state) {
|
|
1818
|
+
switch(_state.label){
|
|
1819
|
+
case 0:
|
|
1820
|
+
return [
|
|
1821
|
+
4,
|
|
1822
|
+
bucket.head(object.key)
|
|
1823
|
+
];
|
|
1824
|
+
case 1:
|
|
1825
|
+
r2Object = _state.sent();
|
|
1826
|
+
if (!r2Object) {
|
|
1827
|
+
return [
|
|
1828
|
+
2,
|
|
1829
|
+
null
|
|
1830
|
+
];
|
|
1831
|
+
}
|
|
1832
|
+
metadata = r2Object.customMetadata || {};
|
|
1833
|
+
slug = metadata.slug || object.key.replace('pages/', '').replace('.html', '');
|
|
1834
|
+
// Build the public URL
|
|
1835
|
+
url = new URL(context.req.url);
|
|
1836
|
+
pageUrl = "".concat(url.protocol, "//").concat(url.host, "/pages/").concat(slug);
|
|
1837
|
+
return [
|
|
1838
|
+
2,
|
|
1839
|
+
_object_spread_props(_object_spread({
|
|
1840
|
+
slug: slug,
|
|
1841
|
+
url: pageUrl,
|
|
1842
|
+
brainRunId: metadata.brainRunId || '',
|
|
1843
|
+
persist: metadata.persist === 'true'
|
|
1844
|
+
}, metadata.ttl && {
|
|
1845
|
+
ttl: Number(metadata.ttl)
|
|
1846
|
+
}), {
|
|
1847
|
+
createdAt: metadata.createdAt || object.uploaded.toISOString(),
|
|
1848
|
+
size: object.size
|
|
1849
|
+
})
|
|
1850
|
+
];
|
|
1851
|
+
}
|
|
1852
|
+
});
|
|
1853
|
+
})();
|
|
1854
|
+
}))
|
|
1855
|
+
];
|
|
1856
|
+
case 3:
|
|
1857
|
+
pages = _state.sent();
|
|
1858
|
+
// Filter out any null entries
|
|
1859
|
+
validPages = pages.filter(function(page) {
|
|
1860
|
+
return page !== null;
|
|
1861
|
+
});
|
|
1862
|
+
return [
|
|
1863
|
+
2,
|
|
1864
|
+
context.json({
|
|
1865
|
+
pages: validPages,
|
|
1866
|
+
count: validPages.length
|
|
1867
|
+
})
|
|
1868
|
+
];
|
|
1869
|
+
case 4:
|
|
1870
|
+
error = _state.sent();
|
|
1871
|
+
console.error('Error listing pages:', error);
|
|
1872
|
+
return [
|
|
1873
|
+
2,
|
|
1874
|
+
context.json({
|
|
1875
|
+
error: "Failed to list pages: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
1876
|
+
}, 500)
|
|
1877
|
+
];
|
|
1878
|
+
case 5:
|
|
1879
|
+
return [
|
|
1880
|
+
2
|
|
1881
|
+
];
|
|
1882
|
+
}
|
|
1883
|
+
});
|
|
1884
|
+
})();
|
|
1885
|
+
});
|
|
1886
|
+
// Get page metadata (without content)
|
|
1887
|
+
app.get('/pages/:slug/meta', function(context) {
|
|
1888
|
+
return _async_to_generator(function() {
|
|
1889
|
+
var slug, bucket, key, r2Object, metadata, error;
|
|
1890
|
+
return _ts_generator(this, function(_state) {
|
|
1891
|
+
switch(_state.label){
|
|
1892
|
+
case 0:
|
|
1893
|
+
slug = context.req.param('slug');
|
|
1894
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
1895
|
+
key = "pages/".concat(slug, ".html");
|
|
1896
|
+
_state.label = 1;
|
|
1897
|
+
case 1:
|
|
1898
|
+
_state.trys.push([
|
|
1899
|
+
1,
|
|
1900
|
+
3,
|
|
1901
|
+
,
|
|
1902
|
+
4
|
|
1903
|
+
]);
|
|
1904
|
+
return [
|
|
1905
|
+
4,
|
|
1906
|
+
bucket.head(key)
|
|
1907
|
+
];
|
|
1908
|
+
case 2:
|
|
1909
|
+
r2Object = _state.sent();
|
|
1910
|
+
if (!r2Object) {
|
|
1911
|
+
return [
|
|
1912
|
+
2,
|
|
1913
|
+
context.json({
|
|
1914
|
+
error: 'Page not found'
|
|
1915
|
+
}, 404)
|
|
1916
|
+
];
|
|
1917
|
+
}
|
|
1918
|
+
metadata = r2Object.customMetadata || {};
|
|
1919
|
+
return [
|
|
1920
|
+
2,
|
|
1921
|
+
context.json(_object_spread_props(_object_spread({
|
|
1922
|
+
slug: metadata.slug || slug,
|
|
1923
|
+
brainRunId: metadata.brainRunId || '',
|
|
1924
|
+
persist: metadata.persist === 'true'
|
|
1925
|
+
}, metadata.ttl && {
|
|
1926
|
+
ttl: Number(metadata.ttl)
|
|
1927
|
+
}), {
|
|
1928
|
+
createdAt: metadata.createdAt || r2Object.uploaded.toISOString(),
|
|
1929
|
+
size: r2Object.size
|
|
1930
|
+
}))
|
|
1931
|
+
];
|
|
1932
|
+
case 3:
|
|
1933
|
+
error = _state.sent();
|
|
1934
|
+
console.error("Error getting page metadata for ".concat(slug, ":"), error);
|
|
1935
|
+
return [
|
|
1936
|
+
2,
|
|
1937
|
+
context.json({
|
|
1938
|
+
error: "Failed to get page metadata: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
1939
|
+
}, 500)
|
|
1940
|
+
];
|
|
1941
|
+
case 4:
|
|
1942
|
+
return [
|
|
1943
|
+
2
|
|
1944
|
+
];
|
|
1945
|
+
}
|
|
1946
|
+
});
|
|
1947
|
+
})();
|
|
1948
|
+
});
|
|
1949
|
+
// Get page HTML content
|
|
1950
|
+
app.get('/pages/:slug', function(context) {
|
|
1951
|
+
return _async_to_generator(function() {
|
|
1952
|
+
var slug, bucket, key, r2Object, html, error;
|
|
1953
|
+
return _ts_generator(this, function(_state) {
|
|
1954
|
+
switch(_state.label){
|
|
1955
|
+
case 0:
|
|
1956
|
+
slug = context.req.param('slug');
|
|
1957
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
1958
|
+
key = "pages/".concat(slug, ".html");
|
|
1959
|
+
_state.label = 1;
|
|
1960
|
+
case 1:
|
|
1961
|
+
_state.trys.push([
|
|
1962
|
+
1,
|
|
1963
|
+
4,
|
|
1964
|
+
,
|
|
1965
|
+
5
|
|
1966
|
+
]);
|
|
1967
|
+
return [
|
|
1968
|
+
4,
|
|
1969
|
+
bucket.get(key)
|
|
1970
|
+
];
|
|
1971
|
+
case 2:
|
|
1972
|
+
r2Object = _state.sent();
|
|
1973
|
+
if (!r2Object) {
|
|
1974
|
+
return [
|
|
1975
|
+
2,
|
|
1976
|
+
context.json({
|
|
1977
|
+
error: 'Page not found'
|
|
1978
|
+
}, 404)
|
|
1979
|
+
];
|
|
1980
|
+
}
|
|
1981
|
+
return [
|
|
1982
|
+
4,
|
|
1983
|
+
r2Object.text()
|
|
1984
|
+
];
|
|
1985
|
+
case 3:
|
|
1986
|
+
html = _state.sent();
|
|
1987
|
+
return [
|
|
1988
|
+
2,
|
|
1989
|
+
new Response(html, {
|
|
1990
|
+
status: 200,
|
|
1991
|
+
headers: {
|
|
1992
|
+
'Content-Type': 'text/html; charset=utf-8'
|
|
1993
|
+
}
|
|
1994
|
+
})
|
|
1995
|
+
];
|
|
1996
|
+
case 4:
|
|
1997
|
+
error = _state.sent();
|
|
1998
|
+
console.error("Error getting page ".concat(slug, ":"), error);
|
|
1999
|
+
return [
|
|
2000
|
+
2,
|
|
2001
|
+
context.json({
|
|
2002
|
+
error: "Failed to get page: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
2003
|
+
}, 500)
|
|
2004
|
+
];
|
|
2005
|
+
case 5:
|
|
2006
|
+
return [
|
|
2007
|
+
2
|
|
2008
|
+
];
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
})();
|
|
2012
|
+
});
|
|
2013
|
+
// Update page HTML content
|
|
2014
|
+
app.put('/pages/:slug', function(context) {
|
|
2015
|
+
return _async_to_generator(function() {
|
|
2016
|
+
var slug, bucket, key, existingObject, body, html, existingMetadata, url, pageUrl, error;
|
|
2017
|
+
return _ts_generator(this, function(_state) {
|
|
2018
|
+
switch(_state.label){
|
|
2019
|
+
case 0:
|
|
2020
|
+
slug = context.req.param('slug');
|
|
2021
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
2022
|
+
key = "pages/".concat(slug, ".html");
|
|
2023
|
+
_state.label = 1;
|
|
2024
|
+
case 1:
|
|
2025
|
+
_state.trys.push([
|
|
2026
|
+
1,
|
|
2027
|
+
5,
|
|
2028
|
+
,
|
|
2029
|
+
6
|
|
2030
|
+
]);
|
|
2031
|
+
return [
|
|
2032
|
+
4,
|
|
2033
|
+
bucket.head(key)
|
|
2034
|
+
];
|
|
2035
|
+
case 2:
|
|
2036
|
+
existingObject = _state.sent();
|
|
2037
|
+
if (!existingObject) {
|
|
2038
|
+
return [
|
|
2039
|
+
2,
|
|
2040
|
+
context.json({
|
|
2041
|
+
error: 'Page not found'
|
|
2042
|
+
}, 404)
|
|
2043
|
+
];
|
|
2044
|
+
}
|
|
2045
|
+
return [
|
|
2046
|
+
4,
|
|
2047
|
+
context.req.json()
|
|
2048
|
+
];
|
|
2049
|
+
case 3:
|
|
2050
|
+
body = _state.sent();
|
|
2051
|
+
html = body.html;
|
|
2052
|
+
if (!html) {
|
|
2053
|
+
return [
|
|
2054
|
+
2,
|
|
2055
|
+
context.json({
|
|
2056
|
+
error: 'Missing required field "html"'
|
|
2057
|
+
}, 400)
|
|
2058
|
+
];
|
|
2059
|
+
}
|
|
2060
|
+
// Preserve existing metadata
|
|
2061
|
+
existingMetadata = existingObject.customMetadata || {};
|
|
2062
|
+
// Update with new HTML, preserving metadata
|
|
2063
|
+
return [
|
|
2064
|
+
4,
|
|
2065
|
+
bucket.put(key, html, {
|
|
2066
|
+
httpMetadata: {
|
|
2067
|
+
contentType: 'text/html; charset=utf-8'
|
|
2068
|
+
},
|
|
2069
|
+
customMetadata: existingMetadata
|
|
2070
|
+
})
|
|
2071
|
+
];
|
|
2072
|
+
case 4:
|
|
2073
|
+
_state.sent();
|
|
2074
|
+
// Build the public URL
|
|
2075
|
+
url = new URL(context.req.url);
|
|
2076
|
+
pageUrl = "".concat(url.protocol, "//").concat(url.host, "/pages/").concat(slug);
|
|
2077
|
+
return [
|
|
2078
|
+
2,
|
|
2079
|
+
context.json({
|
|
2080
|
+
slug: slug,
|
|
2081
|
+
url: pageUrl,
|
|
2082
|
+
updatedAt: new Date().toISOString()
|
|
2083
|
+
})
|
|
2084
|
+
];
|
|
2085
|
+
case 5:
|
|
2086
|
+
error = _state.sent();
|
|
2087
|
+
console.error("Error updating page ".concat(slug, ":"), error);
|
|
2088
|
+
return [
|
|
2089
|
+
2,
|
|
2090
|
+
context.json({
|
|
2091
|
+
error: "Failed to update page: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
2092
|
+
}, 500)
|
|
2093
|
+
];
|
|
2094
|
+
case 6:
|
|
2095
|
+
return [
|
|
2096
|
+
2
|
|
2097
|
+
];
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
})();
|
|
2101
|
+
});
|
|
2102
|
+
// Delete a page
|
|
2103
|
+
app.delete('/pages/:slug', function(context) {
|
|
2104
|
+
return _async_to_generator(function() {
|
|
2105
|
+
var slug, bucket, key, monitorId, monitorStub, error;
|
|
2106
|
+
return _ts_generator(this, function(_state) {
|
|
2107
|
+
switch(_state.label){
|
|
2108
|
+
case 0:
|
|
2109
|
+
slug = context.req.param('slug');
|
|
2110
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
2111
|
+
key = "pages/".concat(slug, ".html");
|
|
2112
|
+
_state.label = 1;
|
|
2113
|
+
case 1:
|
|
2114
|
+
_state.trys.push([
|
|
2115
|
+
1,
|
|
2116
|
+
4,
|
|
2117
|
+
,
|
|
2118
|
+
5
|
|
2119
|
+
]);
|
|
2120
|
+
// R2 delete is idempotent - no error if object doesn't exist
|
|
2121
|
+
return [
|
|
2122
|
+
4,
|
|
2123
|
+
bucket.delete(key)
|
|
2124
|
+
];
|
|
2125
|
+
case 2:
|
|
2126
|
+
_state.sent();
|
|
2127
|
+
// Also remove from MonitorDO tracking
|
|
2128
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
2129
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
2130
|
+
return [
|
|
2131
|
+
4,
|
|
2132
|
+
monitorStub.unregisterPage(slug)
|
|
2133
|
+
];
|
|
2134
|
+
case 3:
|
|
2135
|
+
_state.sent();
|
|
2136
|
+
return [
|
|
2137
|
+
2,
|
|
2138
|
+
new Response(null, {
|
|
2139
|
+
status: 204
|
|
2140
|
+
})
|
|
2141
|
+
];
|
|
2142
|
+
case 4:
|
|
2143
|
+
error = _state.sent();
|
|
2144
|
+
console.error("Error deleting page ".concat(slug, ":"), error);
|
|
2145
|
+
return [
|
|
2146
|
+
2,
|
|
2147
|
+
context.json({
|
|
2148
|
+
error: "Failed to delete page: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
2149
|
+
}, 500)
|
|
2150
|
+
];
|
|
2151
|
+
case 5:
|
|
2152
|
+
return [
|
|
2153
|
+
2
|
|
2154
|
+
];
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
2157
|
+
})();
|
|
2158
|
+
});
|
|
1654
2159
|
export default app;
|
|
@@ -247,6 +247,7 @@ import { STATUS, BRAIN_EVENTS } from '@positronic/core';
|
|
|
247
247
|
import { DurableObject } from 'cloudflare:workers';
|
|
248
248
|
import { BrainRunSQLiteAdapter } from './sqlite-adapter.js';
|
|
249
249
|
import { WebhookAdapter } from './webhook-adapter.js';
|
|
250
|
+
import { PageAdapter } from './page-adapter.js';
|
|
250
251
|
import { CloudflareR2Loader } from './r2-loader.js';
|
|
251
252
|
import { createResources } from '@positronic/core';
|
|
252
253
|
var manifest = null;
|
|
@@ -569,7 +570,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
569
570
|
key: "start",
|
|
570
571
|
value: function start(brainTitle, brainRunId, initialData) {
|
|
571
572
|
return _async_to_generator(function() {
|
|
572
|
-
var _this, sql, resolution, brainToRun, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, r2Resources, runnerWithResources, options, initialState;
|
|
573
|
+
var _this, sql, resolution, brainToRun, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, r2Resources, runnerWithResources, options, initialState;
|
|
573
574
|
return _ts_generator(this, function(_state) {
|
|
574
575
|
switch(_state.label){
|
|
575
576
|
case 0:
|
|
@@ -599,6 +600,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
599
600
|
monitorAdapter = new MonitorAdapter(monitorDOStub);
|
|
600
601
|
scheduleAdapter = new ScheduleAdapter(this.env.SCHEDULE_DO.get(this.env.SCHEDULE_DO.idFromName('singleton')));
|
|
601
602
|
webhookAdapter = new WebhookAdapter(monitorDOStub);
|
|
603
|
+
pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
|
|
602
604
|
if (!brainRunner) {
|
|
603
605
|
throw new Error('BrainRunner not initialized');
|
|
604
606
|
}
|
|
@@ -624,7 +626,8 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
624
626
|
eventStreamAdapter,
|
|
625
627
|
monitorAdapter,
|
|
626
628
|
scheduleAdapter,
|
|
627
|
-
webhookAdapter
|
|
629
|
+
webhookAdapter,
|
|
630
|
+
pageAdapter
|
|
628
631
|
]).run(brainToRun, _object_spread_props(_object_spread({
|
|
629
632
|
initialState: initialState,
|
|
630
633
|
brainRunId: brainRunId
|
|
@@ -651,7 +654,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
651
654
|
key: "resume",
|
|
652
655
|
value: function resume(brainRunId, webhookResponse) {
|
|
653
656
|
return _async_to_generator(function() {
|
|
654
|
-
var _this, sql, startEventResult, startEvent, brainTitle, initialState, resolution, brainToRun, eventsResult, initialCompletedSteps, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, r2Resources, runnerWithResources;
|
|
657
|
+
var _this, sql, startEventResult, startEvent, brainTitle, initialState, resolution, brainToRun, eventsResult, initialCompletedSteps, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, r2Resources, runnerWithResources;
|
|
655
658
|
return _ts_generator(this, function(_state) {
|
|
656
659
|
switch(_state.label){
|
|
657
660
|
case 0:
|
|
@@ -702,6 +705,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
702
705
|
monitorAdapter = new MonitorAdapter(monitorDOStub);
|
|
703
706
|
scheduleAdapter = new ScheduleAdapter(this.env.SCHEDULE_DO.get(this.env.SCHEDULE_DO.idFromName('singleton')));
|
|
704
707
|
webhookAdapter = new WebhookAdapter(monitorDOStub);
|
|
708
|
+
pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
|
|
705
709
|
if (!brainRunner) {
|
|
706
710
|
throw new Error('BrainRunner not initialized');
|
|
707
711
|
}
|
|
@@ -722,7 +726,8 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
722
726
|
eventStreamAdapter,
|
|
723
727
|
monitorAdapter,
|
|
724
728
|
scheduleAdapter,
|
|
725
|
-
webhookAdapter
|
|
729
|
+
webhookAdapter,
|
|
730
|
+
pageAdapter
|
|
726
731
|
]).run(brainToRun, {
|
|
727
732
|
initialState: initialState,
|
|
728
733
|
initialCompletedSteps: initialCompletedSteps,
|
package/dist/src/monitor-do.js
CHANGED
|
@@ -218,7 +218,7 @@ export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
218
218
|
]), _define_property(_this, "storage", void 0), _define_property(_this, "eventStreamHandler", new EventStreamHandler());
|
|
219
219
|
_this.storage = state.storage.sql;
|
|
220
220
|
// Update table schema and indexes
|
|
221
|
-
_this.storage.exec("\n CREATE TABLE IF NOT EXISTS brain_runs (\n run_id TEXT PRIMARY KEY,\n brain_title TEXT NOT NULL, -- Renamed column\n brain_description TEXT, -- Renamed column\n type TEXT NOT NULL,\n status TEXT NOT NULL,\n options TEXT,\n error TEXT,\n created_at INTEGER NOT NULL,\n started_at INTEGER,\n completed_at INTEGER\n );\n\n CREATE INDEX IF NOT EXISTS idx_brain_status -- Renamed index\n ON brain_runs(brain_title, status);\n\n CREATE INDEX IF NOT EXISTS idx_brain_time -- Renamed index\n ON brain_runs(created_at DESC);\n\n CREATE TABLE IF NOT EXISTS webhook_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL,\n identifier TEXT NOT NULL,\n brain_run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_webhook_lookup\n ON webhook_registrations(slug, identifier);\n\n CREATE INDEX IF NOT EXISTS idx_webhook_brain_run\n ON webhook_registrations(brain_run_id);\n ");
|
|
221
|
+
_this.storage.exec("\n CREATE TABLE IF NOT EXISTS brain_runs (\n run_id TEXT PRIMARY KEY,\n brain_title TEXT NOT NULL, -- Renamed column\n brain_description TEXT, -- Renamed column\n type TEXT NOT NULL,\n status TEXT NOT NULL,\n options TEXT,\n error TEXT,\n created_at INTEGER NOT NULL,\n started_at INTEGER,\n completed_at INTEGER\n );\n\n CREATE INDEX IF NOT EXISTS idx_brain_status -- Renamed index\n ON brain_runs(brain_title, status);\n\n CREATE INDEX IF NOT EXISTS idx_brain_time -- Renamed index\n ON brain_runs(created_at DESC);\n\n CREATE TABLE IF NOT EXISTS webhook_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL,\n identifier TEXT NOT NULL,\n brain_run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_webhook_lookup\n ON webhook_registrations(slug, identifier);\n\n CREATE INDEX IF NOT EXISTS idx_webhook_brain_run\n ON webhook_registrations(brain_run_id);\n\n CREATE TABLE IF NOT EXISTS page_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL UNIQUE,\n brain_run_id TEXT NOT NULL,\n persist INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_page_brain_run\n ON page_registrations(brain_run_id);\n\n CREATE INDEX IF NOT EXISTS idx_page_persist\n ON page_registrations(persist);\n ");
|
|
222
222
|
return _this;
|
|
223
223
|
}
|
|
224
224
|
_create_class(MonitorDO, [
|
|
@@ -232,9 +232,11 @@ export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
232
232
|
var error = event.type === BRAIN_EVENTS.ERROR ? JSON.stringify(event.error) : null;
|
|
233
233
|
// Update SQL insert/update with new column names, read from existing event fields
|
|
234
234
|
this.storage.exec("\n INSERT INTO brain_runs (\n run_id, brain_title, brain_description, type, status,\n options, error, created_at, started_at, completed_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(run_id) DO UPDATE SET\n type = excluded.type,\n status = excluded.status,\n error = excluded.error,\n completed_at = excluded.completed_at\n ", event.brainRunId, event.brainTitle, event.brainDescription || null, event.type, event.status, JSON.stringify(event.options || {}), error, currentTime, startTime, completeTime);
|
|
235
|
-
// Clean up
|
|
235
|
+
// Clean up registrations when brain terminates
|
|
236
236
|
if (event.type === BRAIN_EVENTS.COMPLETE || event.type === BRAIN_EVENTS.ERROR || event.type === BRAIN_EVENTS.CANCELLED) {
|
|
237
237
|
this.clearWebhookRegistrations(event.brainRunId);
|
|
238
|
+
// Note: Non-persistent page cleanup is handled by PageAdapter which has access to R2
|
|
239
|
+
// We just track pages here, actual R2 deletion happens in the adapter
|
|
238
240
|
}
|
|
239
241
|
this.broadcastRunningBrains();
|
|
240
242
|
}
|
|
@@ -395,6 +397,44 @@ export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
|
|
|
395
397
|
value: function clearWebhookRegistrations(brainRunId) {
|
|
396
398
|
this.storage.exec("\n DELETE FROM webhook_registrations\n WHERE brain_run_id = ?\n ", brainRunId);
|
|
397
399
|
}
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
/**
|
|
403
|
+
* Register a page for tracking
|
|
404
|
+
* Called when a page is created via the API
|
|
405
|
+
*/ key: "registerPage",
|
|
406
|
+
value: function registerPage(slug, brainRunId, persist) {
|
|
407
|
+
this.storage.exec("\n INSERT INTO page_registrations (slug, brain_run_id, persist, created_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(slug) DO UPDATE SET\n brain_run_id = excluded.brain_run_id,\n persist = excluded.persist\n ", slug, brainRunId, persist ? 1 : 0, Date.now());
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
/**
|
|
412
|
+
* Unregister a page (when deleted via API)
|
|
413
|
+
*/ key: "unregisterPage",
|
|
414
|
+
value: function unregisterPage(slug) {
|
|
415
|
+
this.storage.exec("\n DELETE FROM page_registrations\n WHERE slug = ?\n ", slug);
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
/**
|
|
420
|
+
* Get all non-persistent page slugs for a brain run
|
|
421
|
+
* Used by PageAdapter to clean up pages when brain terminates
|
|
422
|
+
*/ key: "getNonPersistentPagesForRun",
|
|
423
|
+
value: function getNonPersistentPagesForRun(brainRunId) {
|
|
424
|
+
var results = this.storage.exec("\n SELECT slug\n FROM page_registrations\n WHERE brain_run_id = ? AND persist = 0\n ", brainRunId).toArray();
|
|
425
|
+
return results.map(function(r) {
|
|
426
|
+
return r.slug;
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
/**
|
|
432
|
+
* Clear all page registrations for a brain run
|
|
433
|
+
* Called after pages are cleaned up
|
|
434
|
+
*/ key: "clearPageRegistrations",
|
|
435
|
+
value: function clearPageRegistrations(brainRunId) {
|
|
436
|
+
this.storage.exec("\n DELETE FROM page_registrations\n WHERE brain_run_id = ? AND persist = 0\n ", brainRunId);
|
|
437
|
+
}
|
|
398
438
|
}
|
|
399
439
|
]);
|
|
400
440
|
return MonitorDO;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _class_call_check(instance, Constructor) {
|
|
31
|
+
if (!(instance instanceof Constructor)) {
|
|
32
|
+
throw new TypeError("Cannot call a class as a function");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _defineProperties(target, props) {
|
|
36
|
+
for(var i = 0; i < props.length; i++){
|
|
37
|
+
var descriptor = props[i];
|
|
38
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
39
|
+
descriptor.configurable = true;
|
|
40
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
41
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
45
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
46
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
47
|
+
return Constructor;
|
|
48
|
+
}
|
|
49
|
+
function _define_property(obj, key, value) {
|
|
50
|
+
if (key in obj) {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
value: value,
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true
|
|
56
|
+
});
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = value;
|
|
59
|
+
}
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
function _ts_generator(thisArg, body) {
|
|
63
|
+
var f, y, t, _ = {
|
|
64
|
+
label: 0,
|
|
65
|
+
sent: function() {
|
|
66
|
+
if (t[0] & 1) throw t[1];
|
|
67
|
+
return t[1];
|
|
68
|
+
},
|
|
69
|
+
trys: [],
|
|
70
|
+
ops: []
|
|
71
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
72
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
73
|
+
return this;
|
|
74
|
+
}), g;
|
|
75
|
+
function verb(n) {
|
|
76
|
+
return function(v) {
|
|
77
|
+
return step([
|
|
78
|
+
n,
|
|
79
|
+
v
|
|
80
|
+
]);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function step(op) {
|
|
84
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
85
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
86
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
87
|
+
if (y = 0, t) op = [
|
|
88
|
+
op[0] & 2,
|
|
89
|
+
t.value
|
|
90
|
+
];
|
|
91
|
+
switch(op[0]){
|
|
92
|
+
case 0:
|
|
93
|
+
case 1:
|
|
94
|
+
t = op;
|
|
95
|
+
break;
|
|
96
|
+
case 4:
|
|
97
|
+
_.label++;
|
|
98
|
+
return {
|
|
99
|
+
value: op[1],
|
|
100
|
+
done: false
|
|
101
|
+
};
|
|
102
|
+
case 5:
|
|
103
|
+
_.label++;
|
|
104
|
+
y = op[1];
|
|
105
|
+
op = [
|
|
106
|
+
0
|
|
107
|
+
];
|
|
108
|
+
continue;
|
|
109
|
+
case 7:
|
|
110
|
+
op = _.ops.pop();
|
|
111
|
+
_.trys.pop();
|
|
112
|
+
continue;
|
|
113
|
+
default:
|
|
114
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
115
|
+
_ = 0;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
119
|
+
_.label = op[1];
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
123
|
+
_.label = t[1];
|
|
124
|
+
t = op;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
if (t && _.label < t[2]) {
|
|
128
|
+
_.label = t[2];
|
|
129
|
+
_.ops.push(op);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
if (t[2]) _.ops.pop();
|
|
133
|
+
_.trys.pop();
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
op = body.call(thisArg, _);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
op = [
|
|
139
|
+
6,
|
|
140
|
+
e
|
|
141
|
+
];
|
|
142
|
+
y = 0;
|
|
143
|
+
} finally{
|
|
144
|
+
f = t = 0;
|
|
145
|
+
}
|
|
146
|
+
if (op[0] & 5) throw op[1];
|
|
147
|
+
return {
|
|
148
|
+
value: op[0] ? op[1] : void 0,
|
|
149
|
+
done: true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
import { BRAIN_EVENTS } from '@positronic/core';
|
|
154
|
+
/**
|
|
155
|
+
* Adapter that handles page cleanup when brains terminate.
|
|
156
|
+
* Non-persistent pages are deleted from R2 when a brain completes, errors, or is cancelled.
|
|
157
|
+
*/ export var PageAdapter = /*#__PURE__*/ function() {
|
|
158
|
+
"use strict";
|
|
159
|
+
function PageAdapter(monitorStub, resourcesBucket) {
|
|
160
|
+
_class_call_check(this, PageAdapter);
|
|
161
|
+
_define_property(this, "monitorStub", void 0);
|
|
162
|
+
_define_property(this, "resourcesBucket", void 0);
|
|
163
|
+
this.monitorStub = monitorStub;
|
|
164
|
+
this.resourcesBucket = resourcesBucket;
|
|
165
|
+
}
|
|
166
|
+
_create_class(PageAdapter, [
|
|
167
|
+
{
|
|
168
|
+
key: "dispatch",
|
|
169
|
+
value: function dispatch(event) {
|
|
170
|
+
return _async_to_generator(function() {
|
|
171
|
+
var pageSlugs, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, slug, key, err, error;
|
|
172
|
+
return _ts_generator(this, function(_state) {
|
|
173
|
+
switch(_state.label){
|
|
174
|
+
case 0:
|
|
175
|
+
// Only handle terminal events
|
|
176
|
+
if (event.type !== BRAIN_EVENTS.COMPLETE && event.type !== BRAIN_EVENTS.ERROR && event.type !== BRAIN_EVENTS.CANCELLED) {
|
|
177
|
+
return [
|
|
178
|
+
2
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
_state.label = 1;
|
|
182
|
+
case 1:
|
|
183
|
+
_state.trys.push([
|
|
184
|
+
1,
|
|
185
|
+
12,
|
|
186
|
+
,
|
|
187
|
+
13
|
|
188
|
+
]);
|
|
189
|
+
return [
|
|
190
|
+
4,
|
|
191
|
+
this.monitorStub.getNonPersistentPagesForRun(event.brainRunId)
|
|
192
|
+
];
|
|
193
|
+
case 2:
|
|
194
|
+
pageSlugs = _state.sent();
|
|
195
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
196
|
+
_state.label = 3;
|
|
197
|
+
case 3:
|
|
198
|
+
_state.trys.push([
|
|
199
|
+
3,
|
|
200
|
+
8,
|
|
201
|
+
9,
|
|
202
|
+
10
|
|
203
|
+
]);
|
|
204
|
+
_iterator = pageSlugs[Symbol.iterator]();
|
|
205
|
+
_state.label = 4;
|
|
206
|
+
case 4:
|
|
207
|
+
if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
|
|
208
|
+
3,
|
|
209
|
+
7
|
|
210
|
+
];
|
|
211
|
+
slug = _step.value;
|
|
212
|
+
key = "pages/".concat(slug, ".html");
|
|
213
|
+
return [
|
|
214
|
+
4,
|
|
215
|
+
this.resourcesBucket.delete(key)
|
|
216
|
+
];
|
|
217
|
+
case 5:
|
|
218
|
+
_state.sent();
|
|
219
|
+
_state.label = 6;
|
|
220
|
+
case 6:
|
|
221
|
+
_iteratorNormalCompletion = true;
|
|
222
|
+
return [
|
|
223
|
+
3,
|
|
224
|
+
4
|
|
225
|
+
];
|
|
226
|
+
case 7:
|
|
227
|
+
return [
|
|
228
|
+
3,
|
|
229
|
+
10
|
|
230
|
+
];
|
|
231
|
+
case 8:
|
|
232
|
+
err = _state.sent();
|
|
233
|
+
_didIteratorError = true;
|
|
234
|
+
_iteratorError = err;
|
|
235
|
+
return [
|
|
236
|
+
3,
|
|
237
|
+
10
|
|
238
|
+
];
|
|
239
|
+
case 9:
|
|
240
|
+
try {
|
|
241
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
242
|
+
_iterator.return();
|
|
243
|
+
}
|
|
244
|
+
} finally{
|
|
245
|
+
if (_didIteratorError) {
|
|
246
|
+
throw _iteratorError;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return [
|
|
250
|
+
7
|
|
251
|
+
];
|
|
252
|
+
case 10:
|
|
253
|
+
// Clear the page registrations from MonitorDO
|
|
254
|
+
return [
|
|
255
|
+
4,
|
|
256
|
+
this.monitorStub.clearPageRegistrations(event.brainRunId)
|
|
257
|
+
];
|
|
258
|
+
case 11:
|
|
259
|
+
_state.sent();
|
|
260
|
+
return [
|
|
261
|
+
3,
|
|
262
|
+
13
|
|
263
|
+
];
|
|
264
|
+
case 12:
|
|
265
|
+
error = _state.sent();
|
|
266
|
+
console.error("[PageAdapter] Error cleaning up pages for brain run ".concat(event.brainRunId, ":"), error);
|
|
267
|
+
return [
|
|
268
|
+
3,
|
|
269
|
+
13
|
|
270
|
+
];
|
|
271
|
+
case 13:
|
|
272
|
+
return [
|
|
273
|
+
2
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}).call(this);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
]);
|
|
281
|
+
return PageAdapter;
|
|
282
|
+
}();
|
package/dist/types/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAI1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,2BAA2B,CAAC;AAGpE,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACvD,UAAU,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAC9C,WAAW,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAChD,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAmBF,QAAA,MAAM,GAAG;cAAwB,QAAQ;yCAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAI1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,2BAA2B,CAAC;AAGpE,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACvD,UAAU,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAC9C,WAAW,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAChD,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAmBF,QAAA,MAAM,GAAG;cAAwB,QAAQ;yCAAK,CAAC;AAojC/C,eAAe,GAAG,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brain-runner-do.d.ts","sourceRoot":"","sources":["../../src/brain-runner-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"brain-runner-do.d.ts","sourceRoot":"","sources":["../../src/brain-runner-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG1D,wBAAgB,WAAW,CAAC,iBAAiB,EAAE,kBAAkB,QAEhE;AAED,wBAAgB,WAAW,IAAI,kBAAkB,GAAG,IAAI,CAEvD;AAGD,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,QAEjD;AAGD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAE/D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAE/D;AAED,MAAM,WAAW,GAAG;IAClB,eAAe,EAAE,sBAAsB,CAAC;IACxC,UAAU,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAC9C,WAAW,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAChD,gBAAgB,EAAE,QAAQ,CAAC;CAC5B;AAwDD,qBAAa,aAAc,SAAQ,aAAa,CAAC,GAAG,CAAC;IACnD,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,eAAe,CAAgC;gBAE3C,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG;YAOjC,mBAAmB;IA0E3B,IAAI,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAStD,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAyF7B,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAyHhC,KAAK,CAAC,OAAO,EAAE,OAAO;CA4E7B"}
|
|
@@ -27,5 +27,24 @@ export declare class MonitorDO extends DurableObject<Env> {
|
|
|
27
27
|
* Called when brain completes, errors, or is cancelled
|
|
28
28
|
*/
|
|
29
29
|
clearWebhookRegistrations(brainRunId: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Register a page for tracking
|
|
32
|
+
* Called when a page is created via the API
|
|
33
|
+
*/
|
|
34
|
+
registerPage(slug: string, brainRunId: string, persist: boolean): void;
|
|
35
|
+
/**
|
|
36
|
+
* Unregister a page (when deleted via API)
|
|
37
|
+
*/
|
|
38
|
+
unregisterPage(slug: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get all non-persistent page slugs for a brain run
|
|
41
|
+
* Used by PageAdapter to clean up pages when brain terminates
|
|
42
|
+
*/
|
|
43
|
+
getNonPersistentPagesForRun(brainRunId: string): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Clear all page registrations for a brain run
|
|
46
|
+
* Called after pages are cleaned up
|
|
47
|
+
*/
|
|
48
|
+
clearPageRegistrations(brainRunId: string): void;
|
|
30
49
|
}
|
|
31
50
|
//# sourceMappingURL=monitor-do.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-do.d.ts","sourceRoot":"","sources":["../../src/monitor-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,GAAG;CAEnB;AAED,qBAAa,SAAU,SAAQ,aAAa,CAAC,GAAG,CAAC;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,kBAAkB,CAA4B;gBAE1C,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG;
|
|
1
|
+
{"version":3,"file":"monitor-do.d.ts","sourceRoot":"","sources":["../../src/monitor-do.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,GAAG;CAEnB;AAED,qBAAa,SAAU,SAAQ,aAAa,CAAC,GAAG,CAAC;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,kBAAkB,CAA4B;gBAE1C,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG;IAuD/C,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC;YA8DzB,sBAAsB;IA0B9B,KAAK,CAAC,OAAO,EAAE,OAAO;IA0D5B,YAAY,CAAC,UAAU,EAAE,MAAM;IAc/B,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW;IA6B9C,UAAU,CAAC,UAAU,EAAE,MAAM;IAyB7B;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAapE;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiBjE;;;OAGG;IACH,yBAAyB,CAAC,UAAU,EAAE,MAAM;IAU5C;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAgB/D;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM;IAU3B;;;OAGG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAezD;;;OAGG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM;CAS1C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Adapter, BrainEvent } from '@positronic/core';
|
|
2
|
+
import type { R2Bucket } from '@cloudflare/workers-types';
|
|
3
|
+
/**
|
|
4
|
+
* Adapter that handles page cleanup when brains terminate.
|
|
5
|
+
* Non-persistent pages are deleted from R2 when a brain completes, errors, or is cancelled.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PageAdapter implements Adapter {
|
|
8
|
+
private monitorStub;
|
|
9
|
+
private resourcesBucket;
|
|
10
|
+
constructor(monitorStub: {
|
|
11
|
+
getNonPersistentPagesForRun: (brainRunId: string) => Promise<string[]>;
|
|
12
|
+
clearPageRegistrations: (brainRunId: string) => Promise<void>;
|
|
13
|
+
}, resourcesBucket: R2Bucket);
|
|
14
|
+
dispatch(event: BrainEvent): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=page-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-adapter.d.ts","sourceRoot":"","sources":["../../src/page-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D;;;GAGG;AACH,qBAAa,WAAY,YAAW,OAAO;IAEvC,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,eAAe;gBAJf,WAAW,EAAE;QACnB,2BAA2B,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/D,EACO,eAAe,EAAE,QAAQ;IAG7B,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAgCjD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@positronic/cloudflare",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"clean": "rm -rf tsconfig.tsbuildinfo dist"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@positronic/core": "^0.0.
|
|
35
|
-
"@positronic/spec": "^0.0.
|
|
36
|
-
"@positronic/template-new-project": "^0.0.
|
|
34
|
+
"@positronic/core": "^0.0.22",
|
|
35
|
+
"@positronic/spec": "^0.0.22",
|
|
36
|
+
"@positronic/template-new-project": "^0.0.22",
|
|
37
37
|
"aws4fetch": "^1.0.18",
|
|
38
38
|
"caz": "^2.0.0",
|
|
39
39
|
"cron-schedule": "^5.0.4",
|