@astrosheep/square 0.3.25 → 0.3.27
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/extensions/square-pi.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { presentPendingAtBoundary, renderPendingAtBoundary } from '../dist/boundary-presentation.js';
|
|
2
2
|
import { automaticSessionEnd, automaticSessionStart } from '../dist/automatic-session.js';
|
|
3
3
|
import { waitForSessionPending } from '../dist/inbox.js';
|
|
4
|
+
import { lookupSessionBindings } from '../dist/registry.js';
|
|
5
|
+
|
|
6
|
+
const PI_SEND_TIMEOUT_MS = 5_000;
|
|
4
7
|
|
|
5
8
|
export function pendingInbox(inbox) {
|
|
6
9
|
return inbox.filter((item) => item.notifications?.length > 0);
|
|
@@ -44,8 +47,30 @@ export default function squarePiExtension(pi) {
|
|
|
44
47
|
});
|
|
45
48
|
};
|
|
46
49
|
|
|
50
|
+
// A transport may keep its promise pending while Pi is shutting down or
|
|
51
|
+
// replacing a session. Never make a lifecycle hook wait for that transport.
|
|
52
|
+
const stopWatcher = () => {
|
|
53
|
+
watcherAbort?.abort();
|
|
54
|
+
watcher = undefined;
|
|
55
|
+
watcherAbort = undefined;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const pause = (signal, delayMs) => new Promise((resolve) => {
|
|
59
|
+
const finish = () => {
|
|
60
|
+
signal.removeEventListener('abort', finish);
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
resolve();
|
|
63
|
+
};
|
|
64
|
+
const timer = setTimeout(finish, delayMs);
|
|
65
|
+
signal.addEventListener('abort', finish, { once: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
47
68
|
const wake = async (piContext, token, signal) => {
|
|
48
69
|
while (sessionId !== undefined && token === generation && !signal.aborted) {
|
|
70
|
+
if (lookupSessionBindings(sessionId).length === 0) {
|
|
71
|
+
await pause(signal, 1_000);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
49
74
|
const deferredRetry = retryAfterChange;
|
|
50
75
|
const pending = await waitForSessionPending(sessionId, 30_000, {
|
|
51
76
|
signal,
|
|
@@ -70,10 +95,21 @@ export default function squarePiExtension(pi) {
|
|
|
70
95
|
const delivered = await presentPendingAtBoundary(
|
|
71
96
|
sessionId,
|
|
72
97
|
async (content) => {
|
|
73
|
-
|
|
98
|
+
const send = Promise.resolve(pi.sendMessage(
|
|
74
99
|
{ customType: 'square', content, display: true },
|
|
75
100
|
{ deliverAs: 'steer', triggerTurn: true },
|
|
76
|
-
);
|
|
101
|
+
));
|
|
102
|
+
let timer;
|
|
103
|
+
try {
|
|
104
|
+
await Promise.race([
|
|
105
|
+
send,
|
|
106
|
+
new Promise((_, reject) => {
|
|
107
|
+
timer = setTimeout(() => reject(new Error('Pi native injection timed out')), PI_SEND_TIMEOUT_MS);
|
|
108
|
+
}),
|
|
109
|
+
]);
|
|
110
|
+
} finally {
|
|
111
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
112
|
+
}
|
|
77
113
|
return true;
|
|
78
114
|
},
|
|
79
115
|
);
|
|
@@ -91,17 +127,15 @@ export default function squarePiExtension(pi) {
|
|
|
91
127
|
|
|
92
128
|
pi.on('session_start', async (_event, ctx) => {
|
|
93
129
|
generation += 1;
|
|
94
|
-
|
|
95
|
-
if (watcher) await watcher;
|
|
96
|
-
watcher = undefined;
|
|
97
|
-
watcherAbort = undefined;
|
|
130
|
+
stopWatcher();
|
|
98
131
|
handledPending.clear();
|
|
99
132
|
retryAfterChange = false;
|
|
100
133
|
sessionId = ctx.sessionManager.getSessionId();
|
|
101
134
|
sessionCwd = ctx.cwd || process.cwd();
|
|
102
135
|
previousSessionId = process.env.SQUARE_PI_SESSION_ID;
|
|
103
136
|
process.env.SQUARE_PI_SESSION_ID = sessionId;
|
|
104
|
-
|
|
137
|
+
joiningContext = undefined;
|
|
138
|
+
void automaticSessionStart('pi', sessionId, sessionCwd).catch(() => undefined);
|
|
105
139
|
watcherAbort = new AbortController();
|
|
106
140
|
const token = generation;
|
|
107
141
|
watcher = wake(ctx, token, watcherAbort.signal).catch(() => undefined);
|
|
@@ -130,13 +164,10 @@ export default function squarePiExtension(pi) {
|
|
|
130
164
|
|
|
131
165
|
pi.on('session_shutdown', async () => {
|
|
132
166
|
generation += 1;
|
|
133
|
-
|
|
134
|
-
if (watcher) await watcher;
|
|
135
|
-
watcher = undefined;
|
|
136
|
-
watcherAbort = undefined;
|
|
167
|
+
stopWatcher();
|
|
137
168
|
for (const waiter of settledWaiters) waiter.resolve();
|
|
138
169
|
settledWaiters = [];
|
|
139
|
-
if (sessionId && sessionCwd)
|
|
170
|
+
if (sessionId && sessionCwd) void automaticSessionEnd('pi', sessionId, sessionCwd).catch(() => undefined);
|
|
140
171
|
if (process.env.SQUARE_PI_SESSION_ID === sessionId) {
|
|
141
172
|
if (previousSessionId === undefined) delete process.env.SQUARE_PI_SESSION_ID;
|
|
142
173
|
else process.env.SQUARE_PI_SESSION_ID = previousSessionId;
|