@portel/photon 1.31.2 → 1.32.2
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 +3 -3
- package/dist/auto-ui/beam.d.ts +8 -0
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +88 -10
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +65 -21
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/daemon/manager.d.ts +11 -1
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +113 -8
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/server.js +26 -20
- package/dist/daemon/server.js.map +1 -1
- package/dist/loader.d.ts +11 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +169 -11
- package/dist/loader.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53 -16
- package/dist/server.js.map +1 -1
- package/dist/settings-persistence.d.ts.map +1 -1
- package/dist/settings-persistence.js +10 -3
- package/dist/settings-persistence.js.map +1 -1
- package/dist/telemetry/context.d.ts +7 -0
- package/dist/telemetry/context.d.ts.map +1 -1
- package/dist/telemetry/context.js +71 -0
- package/dist/telemetry/context.js.map +1 -1
- package/package.json +1 -1
|
@@ -722,6 +722,7 @@ const handlers = {
|
|
|
722
722
|
result = await ctx.loader.executeTool(mcp, methodName, args, {
|
|
723
723
|
outputHandler: agui.outputHandler,
|
|
724
724
|
caller: ctx.caller,
|
|
725
|
+
signal: ctx.signal,
|
|
725
726
|
});
|
|
726
727
|
}
|
|
727
728
|
else {
|
|
@@ -1718,19 +1719,21 @@ const handlers = {
|
|
|
1718
1719
|
try {
|
|
1719
1720
|
// Create outputHandler to capture emits for real-time UI updates
|
|
1720
1721
|
const outputHandler = (yieldValue) => {
|
|
1721
|
-
if (!ctx.broadcast)
|
|
1722
|
-
return;
|
|
1723
1722
|
// Echo the caller's progressToken when supplied so the client
|
|
1724
1723
|
// can route notifications back to the originating panel. Fall
|
|
1725
1724
|
// back to the synthetic `progress_<photon>_<method>` only when
|
|
1726
1725
|
// the caller didn't send one (e.g. server-initiated task
|
|
1727
1726
|
// progress with no user request to correlate against).
|
|
1728
1727
|
const progressToken = clientProgressToken ?? `progress_${photonName}_${methodName}`;
|
|
1728
|
+
const sendJsonRpcNotification = (message) => {
|
|
1729
|
+
ctx.broadcast?.(message);
|
|
1730
|
+
ctx.responseStream?.send(message);
|
|
1731
|
+
};
|
|
1729
1732
|
// Forward progress events as MCP notifications
|
|
1730
1733
|
if (yieldValue?.emit === 'progress') {
|
|
1731
1734
|
const rawValue = typeof yieldValue.value === 'number' ? yieldValue.value : 0;
|
|
1732
1735
|
const progress = rawValue <= 1 ? rawValue * 100 : rawValue;
|
|
1733
|
-
|
|
1736
|
+
sendJsonRpcNotification({
|
|
1734
1737
|
jsonrpc: '2.0',
|
|
1735
1738
|
method: 'notifications/progress',
|
|
1736
1739
|
params: {
|
|
@@ -1744,7 +1747,8 @@ const handlers = {
|
|
|
1744
1747
|
}
|
|
1745
1748
|
// Forward status events as MCP notifications
|
|
1746
1749
|
if (yieldValue?.emit === 'status') {
|
|
1747
|
-
|
|
1750
|
+
const payload = yieldValue.value ?? yieldValue.data;
|
|
1751
|
+
sendJsonRpcNotification({
|
|
1748
1752
|
jsonrpc: '2.0',
|
|
1749
1753
|
method: 'notifications/progress',
|
|
1750
1754
|
params: {
|
|
@@ -1752,13 +1756,14 @@ const handlers = {
|
|
|
1752
1756
|
progress: 0,
|
|
1753
1757
|
total: 100,
|
|
1754
1758
|
message: yieldValue.message || '',
|
|
1759
|
+
...(payload !== undefined && { data: payload }),
|
|
1755
1760
|
},
|
|
1756
1761
|
});
|
|
1757
1762
|
return;
|
|
1758
1763
|
}
|
|
1759
1764
|
// Forward toast events as beam notifications
|
|
1760
1765
|
if (yieldValue?.emit === 'toast') {
|
|
1761
|
-
ctx.broadcast({
|
|
1766
|
+
ctx.broadcast?.({
|
|
1762
1767
|
jsonrpc: '2.0',
|
|
1763
1768
|
method: 'beam/toast',
|
|
1764
1769
|
params: {
|
|
@@ -1771,7 +1776,7 @@ const handlers = {
|
|
|
1771
1776
|
}
|
|
1772
1777
|
// Forward thinking events as beam notifications
|
|
1773
1778
|
if (yieldValue?.emit === 'thinking') {
|
|
1774
|
-
ctx.broadcast({
|
|
1779
|
+
ctx.broadcast?.({
|
|
1775
1780
|
jsonrpc: '2.0',
|
|
1776
1781
|
method: 'beam/thinking',
|
|
1777
1782
|
params: {
|
|
@@ -1782,7 +1787,7 @@ const handlers = {
|
|
|
1782
1787
|
}
|
|
1783
1788
|
// Forward log events as beam notifications
|
|
1784
1789
|
if (yieldValue?.emit === 'log') {
|
|
1785
|
-
ctx.broadcast({
|
|
1790
|
+
ctx.broadcast?.({
|
|
1786
1791
|
jsonrpc: '2.0',
|
|
1787
1792
|
method: 'beam/log',
|
|
1788
1793
|
params: {
|
|
@@ -1795,7 +1800,7 @@ const handlers = {
|
|
|
1795
1800
|
}
|
|
1796
1801
|
// Forward render events — intermediate formatted results
|
|
1797
1802
|
if (yieldValue?.emit === 'render') {
|
|
1798
|
-
ctx.broadcast({
|
|
1803
|
+
ctx.broadcast?.({
|
|
1799
1804
|
jsonrpc: '2.0',
|
|
1800
1805
|
method: 'beam/render',
|
|
1801
1806
|
params: {
|
|
@@ -1809,7 +1814,7 @@ const handlers = {
|
|
|
1809
1814
|
}
|
|
1810
1815
|
// Forward canvas:ui events — AI-generated UI layout with data-slot placeholders
|
|
1811
1816
|
if (yieldValue?.emit === 'canvas:ui') {
|
|
1812
|
-
ctx.broadcast({
|
|
1817
|
+
ctx.broadcast?.({
|
|
1813
1818
|
jsonrpc: '2.0',
|
|
1814
1819
|
method: 'beam/canvas',
|
|
1815
1820
|
params: {
|
|
@@ -1823,7 +1828,7 @@ const handlers = {
|
|
|
1823
1828
|
}
|
|
1824
1829
|
// Forward canvas:data events — data targeting named slots
|
|
1825
1830
|
if (yieldValue?.emit === 'canvas:data') {
|
|
1826
|
-
ctx.broadcast({
|
|
1831
|
+
ctx.broadcast?.({
|
|
1827
1832
|
jsonrpc: '2.0',
|
|
1828
1833
|
method: 'beam/canvas',
|
|
1829
1834
|
params: {
|
|
@@ -1838,7 +1843,7 @@ const handlers = {
|
|
|
1838
1843
|
}
|
|
1839
1844
|
// Forward render:clear events — clear the render zone
|
|
1840
1845
|
if (yieldValue?.emit === 'render:clear') {
|
|
1841
|
-
ctx.broadcast({
|
|
1846
|
+
ctx.broadcast?.({
|
|
1842
1847
|
jsonrpc: '2.0',
|
|
1843
1848
|
method: 'beam/render',
|
|
1844
1849
|
params: { photon: photonName, method: methodName, clear: true },
|
|
@@ -1847,7 +1852,7 @@ const handlers = {
|
|
|
1847
1852
|
}
|
|
1848
1853
|
// Forward channel events (task-moved, task-updated, etc.) with full delta
|
|
1849
1854
|
// These contain specific event type + data for efficient UI updates
|
|
1850
|
-
if (yieldValue?.channel && yieldValue?.event) {
|
|
1855
|
+
if (yieldValue?.channel && yieldValue?.event && ctx.broadcast) {
|
|
1851
1856
|
ctx.broadcast({
|
|
1852
1857
|
type: 'channel-event',
|
|
1853
1858
|
photon: photonName,
|
|
@@ -1941,6 +1946,7 @@ const handlers = {
|
|
|
1941
1946
|
inputProvider,
|
|
1942
1947
|
samplingProvider,
|
|
1943
1948
|
caller: ctx.caller,
|
|
1949
|
+
signal: ctx.signal,
|
|
1944
1950
|
});
|
|
1945
1951
|
}
|
|
1946
1952
|
else {
|
|
@@ -1973,7 +1979,10 @@ const handlers = {
|
|
|
1973
1979
|
board: value.board,
|
|
1974
1980
|
});
|
|
1975
1981
|
}
|
|
1976
|
-
else if (value?.emit
|
|
1982
|
+
else if (value?.emit) {
|
|
1983
|
+
outputHandler(value);
|
|
1984
|
+
}
|
|
1985
|
+
else {
|
|
1977
1986
|
chunks.push(value);
|
|
1978
1987
|
}
|
|
1979
1988
|
}
|
|
@@ -3830,6 +3839,33 @@ export async function handleStreamableHTTP(req, res, options) {
|
|
|
3830
3839
|
if (req.method === 'POST') {
|
|
3831
3840
|
const accept = req.headers.accept || '';
|
|
3832
3841
|
const wantsSSE = accept.includes('text/event-stream');
|
|
3842
|
+
const requestAbort = new AbortController();
|
|
3843
|
+
const abortRequest = () => requestAbort.abort();
|
|
3844
|
+
req.on('aborted', abortRequest);
|
|
3845
|
+
res.on('close', abortRequest);
|
|
3846
|
+
res.on('error', abortRequest);
|
|
3847
|
+
req.socket?.on('close', abortRequest);
|
|
3848
|
+
res.socket?.on('close', abortRequest);
|
|
3849
|
+
let responseStreamStarted = false;
|
|
3850
|
+
const ensureResponseStream = () => {
|
|
3851
|
+
if (responseStreamStarted)
|
|
3852
|
+
return;
|
|
3853
|
+
res.writeHead(200, {
|
|
3854
|
+
'Content-Type': 'text/event-stream',
|
|
3855
|
+
'Cache-Control': 'no-cache',
|
|
3856
|
+
Connection: 'keep-alive',
|
|
3857
|
+
'X-Accel-Buffering': 'no',
|
|
3858
|
+
'Mcp-Session-Id': session.id,
|
|
3859
|
+
});
|
|
3860
|
+
res.socket?.setNoDelay(true);
|
|
3861
|
+
responseStreamStarted = true;
|
|
3862
|
+
};
|
|
3863
|
+
const sendResponseStreamMessage = (message) => {
|
|
3864
|
+
if (!wantsSSE || res.writableEnded || res.destroyed)
|
|
3865
|
+
return;
|
|
3866
|
+
ensureResponseStream();
|
|
3867
|
+
res.write(`data: ${JSON.stringify(message)}\n\n`);
|
|
3868
|
+
};
|
|
3833
3869
|
// Read body
|
|
3834
3870
|
let body = '';
|
|
3835
3871
|
for await (const chunk of req) {
|
|
@@ -3862,6 +3898,8 @@ export async function handleStreamableHTTP(req, res, options) {
|
|
|
3862
3898
|
generatePhotonHelp: options.generatePhotonHelp,
|
|
3863
3899
|
loader: options.loader,
|
|
3864
3900
|
broadcast: options.broadcast,
|
|
3901
|
+
responseStream: wantsSSE ? { send: sendResponseStreamMessage } : undefined,
|
|
3902
|
+
signal: requestAbort.signal,
|
|
3865
3903
|
subscriptionManager: options.subscriptionManager,
|
|
3866
3904
|
workingDir: options.workingDir,
|
|
3867
3905
|
caller,
|
|
@@ -3917,18 +3955,19 @@ export async function handleStreamableHTTP(req, res, options) {
|
|
|
3917
3955
|
// Send response
|
|
3918
3956
|
if (responses.length === 0) {
|
|
3919
3957
|
// All were notifications
|
|
3920
|
-
|
|
3921
|
-
|
|
3958
|
+
if (responseStreamStarted) {
|
|
3959
|
+
res.end();
|
|
3960
|
+
}
|
|
3961
|
+
else {
|
|
3962
|
+
res.writeHead(202);
|
|
3963
|
+
res.end();
|
|
3964
|
+
}
|
|
3922
3965
|
}
|
|
3923
3966
|
else if (wantsSSE) {
|
|
3924
3967
|
// SSE response
|
|
3925
|
-
|
|
3926
|
-
'Content-Type': 'text/event-stream',
|
|
3927
|
-
'Cache-Control': 'no-cache',
|
|
3928
|
-
'Mcp-Session-Id': session.id,
|
|
3929
|
-
});
|
|
3968
|
+
ensureResponseStream();
|
|
3930
3969
|
for (const response of responses) {
|
|
3931
|
-
|
|
3970
|
+
sendResponseStreamMessage(response);
|
|
3932
3971
|
}
|
|
3933
3972
|
res.end();
|
|
3934
3973
|
}
|
|
@@ -3941,6 +3980,11 @@ export async function handleStreamableHTTP(req, res, options) {
|
|
|
3941
3980
|
const result = responses.length === 1 ? responses[0] : responses;
|
|
3942
3981
|
res.end(JSON.stringify(result));
|
|
3943
3982
|
}
|
|
3983
|
+
res.off('close', abortRequest);
|
|
3984
|
+
res.off('error', abortRequest);
|
|
3985
|
+
req.off('aborted', abortRequest);
|
|
3986
|
+
req.socket?.off('close', abortRequest);
|
|
3987
|
+
res.socket?.off('close', abortRequest);
|
|
3944
3988
|
return true;
|
|
3945
3989
|
}
|
|
3946
3990
|
// Method not allowed
|