@pinixai/core 0.5.1 → 0.6.0
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/package.json +1 -1
- package/src/clip.ts +8 -0
- package/src/ipc.ts +29 -1
package/package.json
CHANGED
package/src/clip.ts
CHANGED
|
@@ -25,6 +25,14 @@ export abstract class Clip {
|
|
|
25
25
|
dependencies: Record<string, { package: string; version: string }> = {};
|
|
26
26
|
entities: Record<string, z.ZodObject<any>> = {};
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* How long (ms) the process stays alive after the last invoke completes.
|
|
30
|
+
* - `30_000` (default): exit after 30s idle
|
|
31
|
+
* - `0`: exit immediately after each invoke
|
|
32
|
+
* - `Infinity`: never exit (persistent)
|
|
33
|
+
*/
|
|
34
|
+
idleTimeout: number = 30_000;
|
|
35
|
+
|
|
28
36
|
protected readonly commands = new Map<string, HandlerDef>();
|
|
29
37
|
protected readonly commandDescriptions = new Map<string, string>();
|
|
30
38
|
|
package/src/ipc.ts
CHANGED
|
@@ -176,10 +176,32 @@ export async function serveIPC(clip: Clip): Promise<void> {
|
|
|
176
176
|
const manifest = createIPCManifest(clip);
|
|
177
177
|
send({ type: "register", manifest });
|
|
178
178
|
|
|
179
|
+
// Idle timeout management
|
|
180
|
+
const idleTimeout = (clip as Clip & { idleTimeout?: number }).idleTimeout ?? 30_000;
|
|
181
|
+
let inflight = 0;
|
|
182
|
+
let idleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
183
|
+
|
|
184
|
+
function clearIdleTimer(): void {
|
|
185
|
+
if (idleTimer !== null) {
|
|
186
|
+
clearTimeout(idleTimer);
|
|
187
|
+
idleTimer = null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function resetIdleTimer(): void {
|
|
192
|
+
clearIdleTimer();
|
|
193
|
+
if (inflight > 0) return;
|
|
194
|
+
if (!Number.isFinite(idleTimeout) || idleTimeout < 0) return;
|
|
195
|
+
idleTimer = setTimeout(() => process.exit(0), idleTimeout);
|
|
196
|
+
}
|
|
197
|
+
|
|
179
198
|
// Read messages from stdin
|
|
180
199
|
const reader = createLineReader(process.stdin);
|
|
181
200
|
const commands = clip.getCommands();
|
|
182
201
|
|
|
202
|
+
// Start idle timer after registration
|
|
203
|
+
resetIdleTimer();
|
|
204
|
+
|
|
183
205
|
for await (const line of reader) {
|
|
184
206
|
let msg: BaseMessage;
|
|
185
207
|
try {
|
|
@@ -200,8 +222,13 @@ export async function serveIPC(clip: Clip): Promise<void> {
|
|
|
200
222
|
break;
|
|
201
223
|
|
|
202
224
|
case "invoke": {
|
|
225
|
+
clearIdleTimer();
|
|
226
|
+
inflight++;
|
|
203
227
|
const inv = msg as InvokeMessage;
|
|
204
|
-
handleInvoke(inv, commands)
|
|
228
|
+
handleInvoke(inv, commands).finally(() => {
|
|
229
|
+
inflight--;
|
|
230
|
+
resetIdleTimer();
|
|
231
|
+
});
|
|
205
232
|
break;
|
|
206
233
|
}
|
|
207
234
|
|
|
@@ -247,6 +274,7 @@ export async function serveIPC(clip: Clip): Promise<void> {
|
|
|
247
274
|
}
|
|
248
275
|
|
|
249
276
|
// Clean up pending invokes on EOF
|
|
277
|
+
clearIdleTimer();
|
|
250
278
|
for (const [id, pending] of pendingInvokes) {
|
|
251
279
|
pending.reject(new Error("IPC connection closed"));
|
|
252
280
|
}
|