@agimon-ai/po 0.0.0-alpha.103 → 0.0.0-alpha.105
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/catalog/index.json +59 -59
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/src/builders/server/idleRestart.cjs +47 -17
- package/dist/src/builders/server/idleRestart.cjs.map +1 -1
- package/dist/src/builders/server/idleRestart.mjs +47 -17
- package/dist/src/builders/server/idleRestart.mjs.map +1 -1
- package/dist/src/builders/server/packageReloadCheck.cjs +39 -0
- package/dist/src/builders/server/packageReloadCheck.cjs.map +1 -1
- package/dist/src/builders/server/packageReloadCheck.mjs +39 -1
- package/dist/src/builders/server/packageReloadCheck.mjs.map +1 -1
- package/dist/src/builders/server/runtime.cjs +30 -8
- package/dist/src/builders/server/runtime.cjs.map +1 -1
- package/dist/src/builders/server/runtime.mjs +31 -9
- package/dist/src/builders/server/runtime.mjs.map +1 -1
- package/package.json +27 -27
package/dist/catalog/index.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 1,
|
|
3
3
|
"packages": {
|
|
4
4
|
"@agimon-ai/po": {
|
|
5
|
-
"version": "0.0.0-alpha.
|
|
5
|
+
"version": "0.0.0-alpha.105",
|
|
6
6
|
"dependencies": [
|
|
7
7
|
"@agimon-ai/po-approval",
|
|
8
8
|
"@agimon-ai/po-artifact",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"@agimon-ai/po-approval": {
|
|
31
|
-
"version": "0.0.0-alpha.
|
|
31
|
+
"version": "0.0.0-alpha.104",
|
|
32
32
|
"dependencies": [
|
|
33
33
|
"@agimon-ai/po-core",
|
|
34
34
|
"@agimon-ai/po-web-components"
|
|
35
35
|
]
|
|
36
36
|
},
|
|
37
37
|
"@agimon-ai/po-artifact": {
|
|
38
|
-
"version": "0.0.0-alpha.
|
|
38
|
+
"version": "0.0.0-alpha.103",
|
|
39
39
|
"dependencies": [
|
|
40
40
|
"@agimon-ai/po-core",
|
|
41
41
|
"@agimon-ai/po-web-components",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
45
|
"@agimon-ai/po-author": {
|
|
46
|
-
"version": "0.0.0-alpha.
|
|
46
|
+
"version": "0.0.0-alpha.104",
|
|
47
47
|
"dependencies": [
|
|
48
48
|
"@agimon-ai/po-artifact",
|
|
49
49
|
"@agimon-ai/po-core",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
]
|
|
54
54
|
},
|
|
55
55
|
"@agimon-ai/po-autocompact": {
|
|
56
|
-
"version": "0.0.0-alpha.
|
|
56
|
+
"version": "0.0.0-alpha.104",
|
|
57
57
|
"dependencies": [
|
|
58
58
|
"@agimon-ai/po-artifact",
|
|
59
59
|
"@agimon-ai/po-config",
|
|
@@ -62,24 +62,24 @@
|
|
|
62
62
|
]
|
|
63
63
|
},
|
|
64
64
|
"@agimon-ai/po-autostop": {
|
|
65
|
-
"version": "0.0.0-alpha.
|
|
65
|
+
"version": "0.0.0-alpha.104",
|
|
66
66
|
"dependencies": [
|
|
67
67
|
"@agimon-ai/po-core"
|
|
68
68
|
]
|
|
69
69
|
},
|
|
70
70
|
"@agimon-ai/po-browse": {
|
|
71
|
-
"version": "0.0.1-alpha.
|
|
71
|
+
"version": "0.0.1-alpha.102",
|
|
72
72
|
"dependencies": [
|
|
73
73
|
"@agimon-ai/po-core",
|
|
74
74
|
"@agimon-ai/po-web-components"
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
"@agimon-ai/po-build": {
|
|
78
|
-
"version": "0.0.0-alpha.
|
|
78
|
+
"version": "0.0.0-alpha.104",
|
|
79
79
|
"dependencies": []
|
|
80
80
|
},
|
|
81
81
|
"@agimon-ai/po-cache": {
|
|
82
|
-
"version": "0.0.0-alpha.
|
|
82
|
+
"version": "0.0.0-alpha.104",
|
|
83
83
|
"dependencies": [
|
|
84
84
|
"@agimon-ai/po-config",
|
|
85
85
|
"@agimon-ai/po-core",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
]
|
|
88
88
|
},
|
|
89
89
|
"@agimon-ai/po-calendar": {
|
|
90
|
-
"version": "0.0.1-alpha.
|
|
90
|
+
"version": "0.0.1-alpha.63",
|
|
91
91
|
"dependencies": [
|
|
92
92
|
"@agimon-ai/po-config",
|
|
93
93
|
"@agimon-ai/po-core",
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
]
|
|
99
99
|
},
|
|
100
100
|
"@agimon-ai/po-claude-bridge": {
|
|
101
|
-
"version": "0.1.1-alpha.
|
|
101
|
+
"version": "0.1.1-alpha.84",
|
|
102
102
|
"dependencies": []
|
|
103
103
|
},
|
|
104
104
|
"@agimon-ai/po-codemode": {
|
|
105
|
-
"version": "0.0.1-alpha.
|
|
105
|
+
"version": "0.0.1-alpha.77",
|
|
106
106
|
"dependencies": [
|
|
107
107
|
"@agimon-ai/po-config",
|
|
108
108
|
"@agimon-ai/po-core",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
]
|
|
111
111
|
},
|
|
112
112
|
"@agimon-ai/po-computer-use": {
|
|
113
|
-
"version": "0.0.0-alpha.
|
|
113
|
+
"version": "0.0.0-alpha.104",
|
|
114
114
|
"dependencies": [
|
|
115
115
|
"@agimon-ai/po-config",
|
|
116
116
|
"@agimon-ai/po-core",
|
|
@@ -120,26 +120,26 @@
|
|
|
120
120
|
]
|
|
121
121
|
},
|
|
122
122
|
"@agimon-ai/po-config": {
|
|
123
|
-
"version": "0.0.0-alpha.
|
|
123
|
+
"version": "0.0.0-alpha.104",
|
|
124
124
|
"dependencies": [
|
|
125
125
|
"@agimon-ai/po-core",
|
|
126
126
|
"@agimon-ai/po-web-components"
|
|
127
127
|
]
|
|
128
128
|
},
|
|
129
129
|
"@agimon-ai/po-core": {
|
|
130
|
-
"version": "0.0.0-alpha.
|
|
130
|
+
"version": "0.0.0-alpha.104",
|
|
131
131
|
"dependencies": [
|
|
132
132
|
"@agimon-ai/po-web-security"
|
|
133
133
|
]
|
|
134
134
|
},
|
|
135
135
|
"@agimon-ai/po-db": {
|
|
136
|
-
"version": "0.0.0-alpha.
|
|
136
|
+
"version": "0.0.0-alpha.104",
|
|
137
137
|
"dependencies": [
|
|
138
138
|
"@agimon-ai/po-core"
|
|
139
139
|
]
|
|
140
140
|
},
|
|
141
141
|
"@agimon-ai/po-domain": {
|
|
142
|
-
"version": "0.0.0-alpha.
|
|
142
|
+
"version": "0.0.0-alpha.104",
|
|
143
143
|
"dependencies": [
|
|
144
144
|
"@agimon-ai/po-config",
|
|
145
145
|
"@agimon-ai/po-core",
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
]
|
|
148
148
|
},
|
|
149
149
|
"@agimon-ai/po-edit": {
|
|
150
|
-
"version": "0.0.0-alpha.
|
|
150
|
+
"version": "0.0.0-alpha.104",
|
|
151
151
|
"dependencies": [
|
|
152
152
|
"@agimon-ai/po-core",
|
|
153
153
|
"@agimon-ai/po-hashline",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
]
|
|
157
157
|
},
|
|
158
158
|
"@agimon-ai/po-file-edit": {
|
|
159
|
-
"version": "0.0.0-alpha.
|
|
159
|
+
"version": "0.0.0-alpha.104",
|
|
160
160
|
"dependencies": [
|
|
161
161
|
"@agimon-ai/po-config",
|
|
162
162
|
"@agimon-ai/po-core",
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
]
|
|
167
167
|
},
|
|
168
168
|
"@agimon-ai/po-git": {
|
|
169
|
-
"version": "0.0.0-alpha.
|
|
169
|
+
"version": "0.0.0-alpha.104",
|
|
170
170
|
"dependencies": [
|
|
171
171
|
"@agimon-ai/po-core",
|
|
172
172
|
"@agimon-ai/po-session",
|
|
@@ -175,7 +175,7 @@
|
|
|
175
175
|
]
|
|
176
176
|
},
|
|
177
177
|
"@agimon-ai/po-goal": {
|
|
178
|
-
"version": "0.0.0-alpha.
|
|
178
|
+
"version": "0.0.0-alpha.104",
|
|
179
179
|
"dependencies": [
|
|
180
180
|
"@agimon-ai/po-core",
|
|
181
181
|
"@agimon-ai/po-minor-mode",
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
]
|
|
185
185
|
},
|
|
186
186
|
"@agimon-ai/po-grep": {
|
|
187
|
-
"version": "0.0.0-alpha.
|
|
187
|
+
"version": "0.0.0-alpha.104",
|
|
188
188
|
"dependencies": [
|
|
189
189
|
"@agimon-ai/po-core",
|
|
190
190
|
"@agimon-ai/po-hashline",
|
|
@@ -193,11 +193,11 @@
|
|
|
193
193
|
]
|
|
194
194
|
},
|
|
195
195
|
"@agimon-ai/po-hashline": {
|
|
196
|
-
"version": "0.0.0-alpha.
|
|
196
|
+
"version": "0.0.0-alpha.104",
|
|
197
197
|
"dependencies": []
|
|
198
198
|
},
|
|
199
199
|
"@agimon-ai/po-help": {
|
|
200
|
-
"version": "0.0.0-alpha.
|
|
200
|
+
"version": "0.0.0-alpha.104",
|
|
201
201
|
"dependencies": [
|
|
202
202
|
"@agimon-ai/po-core",
|
|
203
203
|
"@agimon-ai/po-minor-mode",
|
|
@@ -205,14 +205,14 @@
|
|
|
205
205
|
]
|
|
206
206
|
},
|
|
207
207
|
"@agimon-ai/po-identity": {
|
|
208
|
-
"version": "0.0.2-alpha.
|
|
208
|
+
"version": "0.0.2-alpha.51",
|
|
209
209
|
"dependencies": [
|
|
210
210
|
"@agimon-ai/po-core",
|
|
211
211
|
"@agimon-ai/po-web-security"
|
|
212
212
|
]
|
|
213
213
|
},
|
|
214
214
|
"@agimon-ai/po-image-gen": {
|
|
215
|
-
"version": "0.0.0-alpha.
|
|
215
|
+
"version": "0.0.0-alpha.103",
|
|
216
216
|
"dependencies": [
|
|
217
217
|
"@agimon-ai/po-core",
|
|
218
218
|
"@agimon-ai/po-web-components",
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
]
|
|
221
221
|
},
|
|
222
222
|
"@agimon-ai/po-ios": {
|
|
223
|
-
"version": "0.0.1-alpha.
|
|
223
|
+
"version": "0.0.1-alpha.39",
|
|
224
224
|
"dependencies": [
|
|
225
225
|
"@agimon-ai/po-artifact",
|
|
226
226
|
"@agimon-ai/po-config",
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
]
|
|
231
231
|
},
|
|
232
232
|
"@agimon-ai/po-log": {
|
|
233
|
-
"version": "0.0.0-alpha.
|
|
233
|
+
"version": "0.0.0-alpha.104",
|
|
234
234
|
"dependencies": [
|
|
235
235
|
"@agimon-ai/po-core",
|
|
236
236
|
"@agimon-ai/po-web-components",
|
|
@@ -238,7 +238,7 @@
|
|
|
238
238
|
]
|
|
239
239
|
},
|
|
240
240
|
"@agimon-ai/po-major-mode": {
|
|
241
|
-
"version": "0.0.0-alpha.
|
|
241
|
+
"version": "0.0.0-alpha.104",
|
|
242
242
|
"dependencies": [
|
|
243
243
|
"@agimon-ai/po-config",
|
|
244
244
|
"@agimon-ai/po-core",
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
]
|
|
247
247
|
},
|
|
248
248
|
"@agimon-ai/po-mcp": {
|
|
249
|
-
"version": "0.0.0-alpha.
|
|
249
|
+
"version": "0.0.0-alpha.104",
|
|
250
250
|
"dependencies": [
|
|
251
251
|
"@agimon-ai/po-config",
|
|
252
252
|
"@agimon-ai/po-core",
|
|
@@ -257,43 +257,43 @@
|
|
|
257
257
|
]
|
|
258
258
|
},
|
|
259
259
|
"@agimon-ai/po-mcp-proxy": {
|
|
260
|
-
"version": "0.0.1-alpha.
|
|
260
|
+
"version": "0.0.1-alpha.83",
|
|
261
261
|
"dependencies": []
|
|
262
262
|
},
|
|
263
263
|
"@agimon-ai/po-minor-mode": {
|
|
264
|
-
"version": "0.0.0-alpha.
|
|
264
|
+
"version": "0.0.0-alpha.104",
|
|
265
265
|
"dependencies": [
|
|
266
266
|
"@agimon-ai/po-core"
|
|
267
267
|
]
|
|
268
268
|
},
|
|
269
269
|
"@agimon-ai/po-model-guidance": {
|
|
270
|
-
"version": "0.0.0-alpha.
|
|
270
|
+
"version": "0.0.0-alpha.104",
|
|
271
271
|
"dependencies": [
|
|
272
272
|
"@agimon-ai/po-config",
|
|
273
273
|
"@agimon-ai/po-core"
|
|
274
274
|
]
|
|
275
275
|
},
|
|
276
276
|
"@agimon-ai/po-native-components": {
|
|
277
|
-
"version": "0.0.0-alpha.
|
|
277
|
+
"version": "0.0.0-alpha.104",
|
|
278
278
|
"dependencies": [
|
|
279
279
|
"@agimon-ai/po-web-components"
|
|
280
280
|
]
|
|
281
281
|
},
|
|
282
282
|
"@agimon-ai/po-network": {
|
|
283
|
-
"version": "0.0.2-alpha.
|
|
283
|
+
"version": "0.0.2-alpha.51",
|
|
284
284
|
"dependencies": [
|
|
285
285
|
"@agimon-ai/po-core",
|
|
286
286
|
"@agimon-ai/po-web-security"
|
|
287
287
|
]
|
|
288
288
|
},
|
|
289
289
|
"@agimon-ai/po-notification": {
|
|
290
|
-
"version": "0.0.0-alpha.
|
|
290
|
+
"version": "0.0.0-alpha.104",
|
|
291
291
|
"dependencies": [
|
|
292
292
|
"@agimon-ai/po-core"
|
|
293
293
|
]
|
|
294
294
|
},
|
|
295
295
|
"@agimon-ai/po-plan": {
|
|
296
|
-
"version": "0.0.0-alpha.
|
|
296
|
+
"version": "0.0.0-alpha.104",
|
|
297
297
|
"dependencies": [
|
|
298
298
|
"@agimon-ai/po-config",
|
|
299
299
|
"@agimon-ai/po-core",
|
|
@@ -303,7 +303,7 @@
|
|
|
303
303
|
]
|
|
304
304
|
},
|
|
305
305
|
"@agimon-ai/po-profile": {
|
|
306
|
-
"version": "0.0.0-alpha.
|
|
306
|
+
"version": "0.0.0-alpha.104",
|
|
307
307
|
"dependencies": [
|
|
308
308
|
"@agimon-ai/po-config",
|
|
309
309
|
"@agimon-ai/po-core",
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
]
|
|
312
312
|
},
|
|
313
313
|
"@agimon-ai/po-prompt": {
|
|
314
|
-
"version": "0.0.0-alpha.
|
|
314
|
+
"version": "0.0.0-alpha.104",
|
|
315
315
|
"dependencies": [
|
|
316
316
|
"@agimon-ai/po-core",
|
|
317
317
|
"@agimon-ai/po-web-components",
|
|
@@ -319,7 +319,7 @@
|
|
|
319
319
|
]
|
|
320
320
|
},
|
|
321
321
|
"@agimon-ai/po-read": {
|
|
322
|
-
"version": "0.0.0-alpha.
|
|
322
|
+
"version": "0.0.0-alpha.104",
|
|
323
323
|
"dependencies": [
|
|
324
324
|
"@agimon-ai/po-config",
|
|
325
325
|
"@agimon-ai/po-core",
|
|
@@ -329,7 +329,7 @@
|
|
|
329
329
|
]
|
|
330
330
|
},
|
|
331
331
|
"@agimon-ai/po-runner": {
|
|
332
|
-
"version": "0.0.0-alpha.
|
|
332
|
+
"version": "0.0.0-alpha.104",
|
|
333
333
|
"dependencies": [
|
|
334
334
|
"@agimon-ai/po-core",
|
|
335
335
|
"@agimon-ai/po-ui",
|
|
@@ -338,13 +338,13 @@
|
|
|
338
338
|
]
|
|
339
339
|
},
|
|
340
340
|
"@agimon-ai/po-sandbox": {
|
|
341
|
-
"version": "0.0.0-alpha.
|
|
341
|
+
"version": "0.0.0-alpha.104",
|
|
342
342
|
"dependencies": [
|
|
343
343
|
"@agimon-ai/po-core"
|
|
344
344
|
]
|
|
345
345
|
},
|
|
346
346
|
"@agimon-ai/po-session": {
|
|
347
|
-
"version": "0.0.0-alpha.
|
|
347
|
+
"version": "0.0.0-alpha.104",
|
|
348
348
|
"dependencies": [
|
|
349
349
|
"@agimon-ai/po-config",
|
|
350
350
|
"@agimon-ai/po-core",
|
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
]
|
|
353
353
|
},
|
|
354
354
|
"@agimon-ai/po-skill": {
|
|
355
|
-
"version": "0.0.0-alpha.
|
|
355
|
+
"version": "0.0.0-alpha.104",
|
|
356
356
|
"dependencies": [
|
|
357
357
|
"@agimon-ai/po-config",
|
|
358
358
|
"@agimon-ai/po-core",
|
|
@@ -361,7 +361,7 @@
|
|
|
361
361
|
]
|
|
362
362
|
},
|
|
363
363
|
"@agimon-ai/po-style-system": {
|
|
364
|
-
"version": "0.0.0-alpha.
|
|
364
|
+
"version": "0.0.0-alpha.104",
|
|
365
365
|
"dependencies": [
|
|
366
366
|
"@agimon-ai/po-core",
|
|
367
367
|
"@agimon-ai/po-web-components",
|
|
@@ -369,7 +369,7 @@
|
|
|
369
369
|
]
|
|
370
370
|
},
|
|
371
371
|
"@agimon-ai/po-task": {
|
|
372
|
-
"version": "0.0.0-alpha.
|
|
372
|
+
"version": "0.0.0-alpha.104",
|
|
373
373
|
"dependencies": [
|
|
374
374
|
"@agimon-ai/po-core",
|
|
375
375
|
"@agimon-ai/po-ui",
|
|
@@ -377,7 +377,7 @@
|
|
|
377
377
|
]
|
|
378
378
|
},
|
|
379
379
|
"@agimon-ai/po-team": {
|
|
380
|
-
"version": "0.0.0-alpha.
|
|
380
|
+
"version": "0.0.0-alpha.104",
|
|
381
381
|
"dependencies": [
|
|
382
382
|
"@agimon-ai/po-cache",
|
|
383
383
|
"@agimon-ai/po-config",
|
|
@@ -389,7 +389,7 @@
|
|
|
389
389
|
]
|
|
390
390
|
},
|
|
391
391
|
"@agimon-ai/po-template-advanced": {
|
|
392
|
-
"version": "0.0.0-alpha.
|
|
392
|
+
"version": "0.0.0-alpha.104",
|
|
393
393
|
"dependencies": [
|
|
394
394
|
"@agimon-ai/po-core",
|
|
395
395
|
"@agimon-ai/po-web-components",
|
|
@@ -397,7 +397,7 @@
|
|
|
397
397
|
]
|
|
398
398
|
},
|
|
399
399
|
"@agimon-ai/po-template-elegant": {
|
|
400
|
-
"version": "0.0.0-alpha.
|
|
400
|
+
"version": "0.0.0-alpha.104",
|
|
401
401
|
"dependencies": [
|
|
402
402
|
"@agimon-ai/po-core",
|
|
403
403
|
"@agimon-ai/po-web-components",
|
|
@@ -405,7 +405,7 @@
|
|
|
405
405
|
]
|
|
406
406
|
},
|
|
407
407
|
"@agimon-ai/po-ui": {
|
|
408
|
-
"version": "0.0.0-alpha.
|
|
408
|
+
"version": "0.0.0-alpha.104",
|
|
409
409
|
"dependencies": [
|
|
410
410
|
"@agimon-ai/po-core",
|
|
411
411
|
"@agimon-ai/po-hashline",
|
|
@@ -414,7 +414,7 @@
|
|
|
414
414
|
]
|
|
415
415
|
},
|
|
416
416
|
"@agimon-ai/po-user-feedback": {
|
|
417
|
-
"version": "0.0.0-alpha.
|
|
417
|
+
"version": "0.0.0-alpha.104",
|
|
418
418
|
"dependencies": [
|
|
419
419
|
"@agimon-ai/po-core",
|
|
420
420
|
"@agimon-ai/po-minor-mode",
|
|
@@ -423,14 +423,14 @@
|
|
|
423
423
|
]
|
|
424
424
|
},
|
|
425
425
|
"@agimon-ai/po-vault": {
|
|
426
|
-
"version": "0.0.0-alpha.
|
|
426
|
+
"version": "0.0.0-alpha.104",
|
|
427
427
|
"dependencies": [
|
|
428
428
|
"@agimon-ai/po-core",
|
|
429
429
|
"@agimon-ai/po-db"
|
|
430
430
|
]
|
|
431
431
|
},
|
|
432
432
|
"@agimon-ai/po-vibe-lint": {
|
|
433
|
-
"version": "0.0.1-alpha.
|
|
433
|
+
"version": "0.0.1-alpha.73",
|
|
434
434
|
"dependencies": [
|
|
435
435
|
"@agimon-ai/po-config",
|
|
436
436
|
"@agimon-ai/po-core",
|
|
@@ -440,7 +440,7 @@
|
|
|
440
440
|
]
|
|
441
441
|
},
|
|
442
442
|
"@agimon-ai/po-voice": {
|
|
443
|
-
"version": "0.0.0-alpha.
|
|
443
|
+
"version": "0.0.0-alpha.104",
|
|
444
444
|
"dependencies": [
|
|
445
445
|
"@agimon-ai/po-config",
|
|
446
446
|
"@agimon-ai/po-core",
|
|
@@ -452,11 +452,11 @@
|
|
|
452
452
|
]
|
|
453
453
|
},
|
|
454
454
|
"@agimon-ai/po-web-components": {
|
|
455
|
-
"version": "0.0.0-alpha.
|
|
455
|
+
"version": "0.0.0-alpha.104",
|
|
456
456
|
"dependencies": []
|
|
457
457
|
},
|
|
458
458
|
"@agimon-ai/po-web-dashboard": {
|
|
459
|
-
"version": "0.0.0-alpha.
|
|
459
|
+
"version": "0.0.0-alpha.104",
|
|
460
460
|
"dependencies": [
|
|
461
461
|
"@agimon-ai/po-core",
|
|
462
462
|
"@agimon-ai/po-web-components",
|
|
@@ -464,18 +464,18 @@
|
|
|
464
464
|
]
|
|
465
465
|
},
|
|
466
466
|
"@agimon-ai/po-web-search": {
|
|
467
|
-
"version": "0.0.0-alpha.
|
|
467
|
+
"version": "0.0.0-alpha.103",
|
|
468
468
|
"dependencies": [
|
|
469
469
|
"@agimon-ai/po-core",
|
|
470
470
|
"@agimon-ai/po-web-components"
|
|
471
471
|
]
|
|
472
472
|
},
|
|
473
473
|
"@agimon-ai/po-web-security": {
|
|
474
|
-
"version": "0.0.0-alpha.
|
|
474
|
+
"version": "0.0.0-alpha.104",
|
|
475
475
|
"dependencies": []
|
|
476
476
|
},
|
|
477
477
|
"@agimon-ai/po-workflow": {
|
|
478
|
-
"version": "0.0.0-alpha.
|
|
478
|
+
"version": "0.0.0-alpha.104",
|
|
479
479
|
"dependencies": [
|
|
480
480
|
"@agimon-ai/po-core",
|
|
481
481
|
"@agimon-ai/po-ui",
|
package/dist/package.cjs
CHANGED
package/dist/package.mjs
CHANGED
|
@@ -21,14 +21,14 @@ const RESTART_BLOCKING_PROVIDERS = [
|
|
|
21
21
|
];
|
|
22
22
|
const RUNNER_PROVIDER = "po-runner";
|
|
23
23
|
const RUNNER_WORKING_STATUS = "running";
|
|
24
|
-
/**
|
|
25
|
-
function
|
|
26
|
-
if (snapshot.errors.some((error) => RESTART_BLOCKING_PROVIDERS.includes(error.provider))) return
|
|
27
|
-
|
|
28
|
-
if (!RESTART_BLOCKING_PROVIDERS.includes(item.provider))
|
|
29
|
-
if (item.provider !== RUNNER_PROVIDER
|
|
30
|
-
|
|
31
|
-
}
|
|
24
|
+
/** Fixed categories only, never provider messages or item identifiers. */
|
|
25
|
+
function backgroundRestartBlocker(snapshot) {
|
|
26
|
+
if (snapshot.errors.some((error) => RESTART_BLOCKING_PROVIDERS.includes(error.provider))) return "provider_error";
|
|
27
|
+
for (const item of snapshot.items) {
|
|
28
|
+
if (!RESTART_BLOCKING_PROVIDERS.includes(item.provider)) continue;
|
|
29
|
+
if (item.provider !== RUNNER_PROVIDER) return "team_task";
|
|
30
|
+
if (item.status === void 0 || item.status === RUNNER_WORKING_STATUS) return "runner";
|
|
31
|
+
}
|
|
32
32
|
}
|
|
33
33
|
/** Test-only: lowers the superseded-version limit so e2e tests can force an idle restart. */
|
|
34
34
|
const TEST_IDLE_RESTART_LIMIT_ENV = "PO_TEST_IDLE_RESTART_LIMIT";
|
|
@@ -73,6 +73,8 @@ function createIdleRestart(options) {
|
|
|
73
73
|
const superseded = /* @__PURE__ */ new Set();
|
|
74
74
|
let cancel;
|
|
75
75
|
let checking = false;
|
|
76
|
+
let cancelDeadline;
|
|
77
|
+
let busyCheck;
|
|
76
78
|
let fired = false;
|
|
77
79
|
let pendingSince;
|
|
78
80
|
const pending = () => superseded.size >= limit;
|
|
@@ -81,14 +83,38 @@ function createIdleRestart(options) {
|
|
|
81
83
|
cancel = setTimer(() => {
|
|
82
84
|
cancel = void 0;
|
|
83
85
|
checking = true;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
let settled = false;
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
busyCheck = controller;
|
|
89
|
+
const finish = (busy, error) => {
|
|
90
|
+
if (settled) return;
|
|
91
|
+
settled = true;
|
|
92
|
+
controller.abort();
|
|
93
|
+
busyCheck = void 0;
|
|
94
|
+
cancelDeadline?.();
|
|
95
|
+
cancelDeadline = void 0;
|
|
96
|
+
try {
|
|
97
|
+
if (fired) return;
|
|
98
|
+
if (error !== void 0) {
|
|
99
|
+
options.onBlocked?.("check_failed", pendingSince === void 0 ? 0 : Date.now() - pendingSince);
|
|
100
|
+
options.onError(error);
|
|
101
|
+
} else if (!busy && !fired) {
|
|
102
|
+
fired = true;
|
|
103
|
+
options.restart();
|
|
104
|
+
}
|
|
105
|
+
} catch (failure) {
|
|
106
|
+
options.onError(failure);
|
|
107
|
+
} finally {
|
|
108
|
+
checking = false;
|
|
109
|
+
poke();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
cancelDeadline = defaultTimer(() => {
|
|
113
|
+
if (settled || fired) return;
|
|
114
|
+
options.onBlocked?.("timeout", pendingSince === void 0 ? 0 : Date.now() - pendingSince);
|
|
115
|
+
finish(true);
|
|
116
|
+
}, options.busyTimeoutMs ?? 1e4);
|
|
117
|
+
Promise.resolve().then(() => options.busy(controller.signal)).then((busy) => finish(busy), (error) => finish(true, error));
|
|
92
118
|
}, debounceMs);
|
|
93
119
|
};
|
|
94
120
|
return {
|
|
@@ -103,6 +129,10 @@ function createIdleRestart(options) {
|
|
|
103
129
|
pendingAgeMs: () => pendingSince === void 0 || fired ? 0 : Math.max(0, Date.now() - pendingSince),
|
|
104
130
|
dispose() {
|
|
105
131
|
cancel?.();
|
|
132
|
+
cancelDeadline?.();
|
|
133
|
+
busyCheck?.abort();
|
|
134
|
+
busyCheck = void 0;
|
|
135
|
+
cancelDeadline = void 0;
|
|
106
136
|
cancel = void 0;
|
|
107
137
|
fired = true;
|
|
108
138
|
}
|
|
@@ -206,8 +236,8 @@ exports.RESTART_DEBOUNCE_MS = RESTART_DEBOUNCE_MS;
|
|
|
206
236
|
exports.TEST_IDLE_RESTART_DEBOUNCE_ENV = TEST_IDLE_RESTART_DEBOUNCE_ENV;
|
|
207
237
|
exports.TEST_IDLE_RESTART_LIMIT_ENV = TEST_IDLE_RESTART_LIMIT_ENV;
|
|
208
238
|
exports.TUNNEL_INTENT_FILE = TUNNEL_INTENT_FILE;
|
|
239
|
+
exports.backgroundRestartBlocker = backgroundRestartBlocker;
|
|
209
240
|
exports.createIdleRestart = createIdleRestart;
|
|
210
|
-
exports.holdsRestart = holdsRestart;
|
|
211
241
|
exports.keepTunnelIntent = keepTunnelIntent;
|
|
212
242
|
exports.prepareSessionRestore = prepareSessionRestore;
|
|
213
243
|
exports.readRecycleFile = readRecycleFile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idleRestart.cjs","names":["fs","path"],"sources":["../../../../src/builders/server/idleRestart.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { PoBackgroundWorkSnapshot } from '@agimon-ai/po-core/backgroundWork';\n\n/** Superseded package versions held in memory before a restart is pending. */\nexport const SUPERSEDED_LIMIT = 8;\n/** Wait before each idle-restart check; activity never pushes it back. */\nexport const RESTART_DEBOUNCE_MS = 30_000;\n/** Live intent and deliberate recycle state; normal shutdown removes it. */\nexport const RECYCLE_FILE = 'recycle.json';\n/** Named tunnel intent kept across a normal shutdown; the next boot consumes it. */\nexport const TUNNEL_INTENT_FILE = 'tunnel-intent.json';\n/** Temporary failure: a supervisor restarts the server on the same port and token. */\nexport const RESTART_EXIT_CODE = 75;\n\n/**\n * Background work a restart would kill, matching po-autostop's gate: runners (open\n * terminals and background commands) and running subagents. Workflow runs are left out,\n * as they are there. Subagents count because a restart ends them mid-run just like a turn.\n */\nconst RESTART_BLOCKING_PROVIDERS: readonly string[] = ['po-runner', 'team-direct-runs', 'po-task'];\nconst RUNNER_PROVIDER = 'po-runner';\nconst RUNNER_WORKING_STATUS = 'running';\n\n/** True when a session's background-work snapshot holds work a restart would kill; fails closed. */\nexport function holdsRestart(snapshot: PoBackgroundWorkSnapshot): boolean {\n if (snapshot.errors.some((error) => RESTART_BLOCKING_PROVIDERS.includes(error.provider))) return true;\n return snapshot.items.some((item) => {\n if (!RESTART_BLOCKING_PROVIDERS.includes(item.provider)) return false;\n // A runner item without a status is not known to be done.\n if (item.provider !== RUNNER_PROVIDER || item.status === undefined) return true;\n return item.status === RUNNER_WORKING_STATUS;\n });\n}\n\n/** Test-only: lowers the superseded-version limit so e2e tests can force an idle restart. */\nexport const TEST_IDLE_RESTART_LIMIT_ENV = 'PO_TEST_IDLE_RESTART_LIMIT';\n/** Test-only: shortens the idle-restart debounce for e2e tests. */\nexport const TEST_IDLE_RESTART_DEBOUNCE_ENV = 'PO_TEST_IDLE_RESTART_DEBOUNCE_MS';\n\nfunction parseTestOverride(environment: NodeJS.ProcessEnv, name: string, minimum: number): number | undefined {\n const raw = environment[name];\n if (raw === undefined || raw === '') return undefined;\n const value = Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum)\n throw new Error(`${name} must be an integer of at least ${String(minimum)}; got '${raw}'.`);\n return value;\n}\n\n/**\n * Test-only overrides for the idle restart limit and debounce, read from the environment.\n * Production never sets these; an invalid value fails startup rather than being ignored.\n */\nexport function testIdleRestartOverrides(\n environment: NodeJS.ProcessEnv,\n): Pick<IdleRestartOptions, 'limit' | 'debounceMs'> {\n const limit = parseTestOverride(environment, TEST_IDLE_RESTART_LIMIT_ENV, 1);\n const debounceMs = parseTestOverride(environment, TEST_IDLE_RESTART_DEBOUNCE_ENV, 0);\n return { ...(limit === undefined ? {} : { limit }), ...(debounceMs === undefined ? {} : { debounceMs }) };\n}\n\nexport interface IdleRestartOptions {\n /** True while any session runs a turn or a compaction, or a terminal is open. */\n readonly busy: () => Promise<boolean>;\n /** Starts the restart. Called at most once. */\n readonly restart: () => void;\n readonly limit?: number;\n readonly debounceMs?: number;\n readonly setTimer?: (callback: () => void, ms: number) => () => void;\n /** Receives a failed busy check or restart; required so no failure is dropped. */\n readonly onError: (error: unknown) => void;\n}\n\nexport interface IdleRestart {\n /** Records package URLs replaced by newer ones; each URL counts once. */\n supersede(urls: readonly string[]): void;\n /** Arms the check when a restart is pending and none is armed; never delays an armed check. */\n poke(): void;\n readonly pending: () => boolean;\n supersededCount(): number;\n pendingAgeMs(): number;\n dispose(): void;\n}\n\nconst defaultTimer = (callback: () => void, ms: number): (() => void) => {\n const timer = setTimeout(callback, ms);\n timer.unref();\n return () => clearTimeout(timer);\n};\n\n/**\n * Restarts the server at idle once old package versions pile up in memory.\n *\n * Native `import()` never unloads a module, so every superseded URL stays resident. At\n * `limit` the restart is pending; a check runs `debounceMs` later and restarts when nothing\n * is busy. Pokes never push an armed check back, so steady harmless events cannot starve\n * it. A busy or failed check arms the next one, one at a time.\n */\nexport function createIdleRestart(options: IdleRestartOptions): IdleRestart {\n const limit = options.limit ?? SUPERSEDED_LIMIT;\n const debounceMs = options.debounceMs ?? RESTART_DEBOUNCE_MS;\n const setTimer = options.setTimer ?? defaultTimer;\n const superseded = new Set<string>();\n let cancel: (() => void) | undefined;\n let checking = false;\n let fired = false;\n let pendingSince: number | undefined;\n const pending = () => superseded.size >= limit;\n const poke = (): void => {\n if (!pending() || fired || cancel || checking) return;\n cancel = setTimer(() => {\n cancel = undefined;\n checking = true;\n void options\n .busy()\n .then((busy) => {\n if (busy || fired) return;\n fired = true;\n options.restart();\n })\n .catch((error: unknown) => options.onError(error))\n .finally(() => {\n checking = false;\n poke();\n });\n }, debounceMs);\n };\n return {\n supersede(urls) {\n for (const url of urls) superseded.add(url);\n if (pending() && pendingSince === undefined) pendingSince = Date.now();\n poke();\n },\n poke,\n pending,\n supersededCount: () => superseded.size,\n pendingAgeMs: () => (pendingSince === undefined || fired ? 0 : Math.max(0, Date.now() - pendingSince)),\n dispose() {\n cancel?.();\n cancel = undefined;\n fired = true;\n },\n };\n}\n\nexport interface RecycleState {\n sessionIds: string[];\n kind?: 'live';\n crashRestores?: number[];\n tunnel?: { hostname: string; closesAt?: number };\n}\n\nexport async function writeRecycleFile(\n directory: string,\n sessionIds: readonly string[],\n details: Omit<RecycleState, 'sessionIds'> = {},\n): Promise<void> {\n await fs.mkdir(directory, { recursive: true });\n const target = path.join(directory, RECYCLE_FILE);\n const staging = `${target}.${String(process.pid)}.tmp`;\n await fs.writeFile(staging, `${JSON.stringify({ ...details, sessionIds }, null, 2)}\\n`);\n await fs.rename(staging, target);\n}\n\n/** Accept legacy recycle records, never trust arbitrary extra fields or tunnel secrets. */\nexport async function readRecycleState(directory: string): Promise<RecycleState | undefined> {\n try {\n const file = path.join(directory, RECYCLE_FILE);\n if ((await fs.stat(file)).size > 1024 * 1024) return undefined;\n const parsed = JSON.parse(await fs.readFile(file, 'utf8')) as Partial<RecycleState> | null;\n if (!parsed || !Array.isArray(parsed.sessionIds) || (parsed.kind !== undefined && parsed.kind !== 'live'))\n return undefined;\n const tunnel = parseTunnelIntent(parsed.tunnel);\n return {\n sessionIds: [...new Set(parsed.sessionIds.filter((id): id is string => typeof id === 'string'))],\n ...(parsed.kind === 'live' ? { kind: 'live' } : {}),\n crashRestores: Array.isArray(parsed.crashRestores)\n ? parsed.crashRestores.filter((at): at is number => Number.isSafeInteger(at) && at >= 0)\n : [],\n ...(tunnel === undefined ? {} : { tunnel }),\n };\n } catch {\n return undefined;\n }\n}\n\nfunction parseTunnelIntent(value: unknown): RecycleState['tunnel'] {\n const tunnel = value as Partial<NonNullable<RecycleState['tunnel']>> | null | undefined;\n if (!tunnel || typeof tunnel.hostname !== 'string') return undefined;\n if (tunnel.closesAt !== undefined && !(Number.isSafeInteger(tunnel.closesAt) && tunnel.closesAt >= 0))\n return undefined;\n return { hostname: tunnel.hostname, ...(tunnel.closesAt === undefined ? {} : { closesAt: tunnel.closesAt }) };\n}\n\n/** Keeps the named tunnel intent through a normal shutdown, or clears it when there is none. */\nexport async function keepTunnelIntent(directory: string, tunnel: RecycleState['tunnel']): Promise<void> {\n const target = path.join(directory, TUNNEL_INTENT_FILE);\n if (tunnel === undefined) {\n await fs.rm(target, { force: true });\n return;\n }\n await fs.mkdir(directory, { recursive: true });\n await fs.writeFile(target, `${JSON.stringify(tunnel)}\\n`, { mode: 0o600 });\n}\n\n/** Reads and removes the kept intent, so a later crash never revives a tunnel switched off since. */\nexport async function takeTunnelIntent(directory: string): Promise<RecycleState['tunnel']> {\n const target = path.join(directory, TUNNEL_INTENT_FILE);\n try {\n return parseTunnelIntent(JSON.parse(await fs.readFile(target, 'utf8')));\n } catch {\n return undefined;\n } finally {\n await fs.rm(target, { force: true });\n }\n}\n\n/** Two automatic crash restores in 15 minutes, then require an explicit Wake. */\nexport function prepareSessionRestore(state: RecycleState | undefined, now = Date.now()) {\n const crashRestores = (state?.crashRestores ?? []).filter((at) => at > now - 15 * 60_000 && at <= now);\n const crash = state?.kind === 'live' && state.sessionIds.length > 0;\n const blocked = crash && crashRestores.length >= 2;\n if (crash && !blocked) crashRestores.push(now);\n return { sessionIds: blocked ? [] : (state?.sessionIds ?? []), crashRestores, blocked };\n}\n\nexport async function readRecycleFile(directory: string): Promise<string[]> {\n return (await readRecycleState(directory))?.sessionIds ?? [];\n}\n\nexport async function removeRecycleFile(directory: string): Promise<void> {\n await fs.rm(path.join(directory, RECYCLE_FILE), { force: true });\n}\n\n/** Reopens exactly the recycled sessions, then deletes the file whatever the outcome. */\nexport async function reopenRecycledSessions(\n directory: string,\n reopen: (sessionId: string) => Promise<void>,\n onError: (sessionId: string, error: unknown) => void,\n options: { sessionIds?: readonly string[]; removeAfter?: boolean } = {},\n): Promise<string[]> {\n const ids = options.sessionIds ?? (await readRecycleFile(directory));\n const reopened: string[] = [];\n try {\n for (const id of ids) {\n try {\n await reopen(id);\n reopened.push(id);\n } catch (error) {\n onError(id, error);\n }\n }\n } finally {\n if (options.removeAfter !== false) await removeRecycleFile(directory);\n }\n return reopened;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"idleRestart.cjs","names":["fs","path"],"sources":["../../../../src/builders/server/idleRestart.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { PoBackgroundWorkSnapshot } from '@agimon-ai/po-core/backgroundWork';\n\n/** Superseded package versions held in memory before a restart is pending. */\nexport const SUPERSEDED_LIMIT = 8;\n/** Wait before each idle-restart check; activity never pushes it back. */\nexport const RESTART_DEBOUNCE_MS = 30_000;\n/** Live intent and deliberate recycle state; normal shutdown removes it. */\nexport const RECYCLE_FILE = 'recycle.json';\n/** Named tunnel intent kept across a normal shutdown; the next boot consumes it. */\nexport const TUNNEL_INTENT_FILE = 'tunnel-intent.json';\n/** Temporary failure: a supervisor restarts the server on the same port and token. */\nexport const RESTART_EXIT_CODE = 75;\n\n/**\n * Background work a restart would kill, matching po-autostop's gate: runners (open\n * terminals and background commands) and running subagents. Workflow runs are left out,\n * as they are there. Subagents count because a restart ends them mid-run just like a turn.\n */\nconst RESTART_BLOCKING_PROVIDERS: readonly string[] = ['po-runner', 'team-direct-runs', 'po-task'];\nconst RUNNER_PROVIDER = 'po-runner';\nconst RUNNER_WORKING_STATUS = 'running';\n\n/** True when a session's background-work snapshot holds work a restart would kill; fails closed. */\nexport function holdsRestart(snapshot: PoBackgroundWorkSnapshot): boolean {\n return backgroundRestartBlocker(snapshot) !== undefined;\n}\n\n/** Fixed categories only, never provider messages or item identifiers. */\nexport function backgroundRestartBlocker(\n snapshot: PoBackgroundWorkSnapshot,\n): 'provider_error' | 'runner' | 'team_task' | undefined {\n if (snapshot.errors.some((error) => RESTART_BLOCKING_PROVIDERS.includes(error.provider))) return 'provider_error';\n for (const item of snapshot.items) {\n if (!RESTART_BLOCKING_PROVIDERS.includes(item.provider)) continue;\n if (item.provider !== RUNNER_PROVIDER) return 'team_task';\n if (item.status === undefined || item.status === RUNNER_WORKING_STATUS) return 'runner';\n }\n return undefined;\n}\n\n/** Test-only: lowers the superseded-version limit so e2e tests can force an idle restart. */\nexport const TEST_IDLE_RESTART_LIMIT_ENV = 'PO_TEST_IDLE_RESTART_LIMIT';\n/** Test-only: shortens the idle-restart debounce for e2e tests. */\nexport const TEST_IDLE_RESTART_DEBOUNCE_ENV = 'PO_TEST_IDLE_RESTART_DEBOUNCE_MS';\n\nfunction parseTestOverride(environment: NodeJS.ProcessEnv, name: string, minimum: number): number | undefined {\n const raw = environment[name];\n if (raw === undefined || raw === '') return undefined;\n const value = Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum)\n throw new Error(`${name} must be an integer of at least ${String(minimum)}; got '${raw}'.`);\n return value;\n}\n\n/**\n * Test-only overrides for the idle restart limit and debounce, read from the environment.\n * Production never sets these; an invalid value fails startup rather than being ignored.\n */\nexport function testIdleRestartOverrides(\n environment: NodeJS.ProcessEnv,\n): Pick<IdleRestartOptions, 'limit' | 'debounceMs'> {\n const limit = parseTestOverride(environment, TEST_IDLE_RESTART_LIMIT_ENV, 1);\n const debounceMs = parseTestOverride(environment, TEST_IDLE_RESTART_DEBOUNCE_ENV, 0);\n return { ...(limit === undefined ? {} : { limit }), ...(debounceMs === undefined ? {} : { debounceMs }) };\n}\n\nexport interface IdleRestartOptions {\n /** True while any session runs a turn or a compaction, or a terminal is open. */\n readonly busy: (signal?: AbortSignal) => Promise<boolean>;\n /** Starts the restart. Called at most once. */\n readonly restart: () => void;\n readonly limit?: number;\n readonly debounceMs?: number;\n /** Deadline for the read-only busy check; never a deadline for running work. */\n readonly busyTimeoutMs?: number;\n readonly onBlocked?: (category: 'timeout' | 'check_failed', pendingAgeMs: number) => void;\n readonly setTimer?: (callback: () => void, ms: number) => () => void;\n /** Receives a failed busy check or restart; required so no failure is dropped. */\n readonly onError: (error: unknown) => void;\n}\n\nexport interface IdleRestart {\n /** Records package URLs replaced by newer ones; each URL counts once. */\n supersede(urls: readonly string[]): void;\n /** Arms the check when a restart is pending and none is armed; never delays an armed check. */\n poke(): void;\n readonly pending: () => boolean;\n supersededCount(): number;\n pendingAgeMs(): number;\n dispose(): void;\n}\n\nconst defaultTimer = (callback: () => void, ms: number): (() => void) => {\n const timer = setTimeout(callback, ms);\n timer.unref();\n return () => clearTimeout(timer);\n};\n\n/**\n * Restarts the server at idle once old package versions pile up in memory.\n *\n * Native `import()` never unloads a module, so every superseded URL stays resident. At\n * `limit` the restart is pending; a check runs `debounceMs` later and restarts when nothing\n * is busy. Pokes never push an armed check back, so steady harmless events cannot starve\n * it. A busy or failed check arms the next one, one at a time.\n */\nexport function createIdleRestart(options: IdleRestartOptions): IdleRestart {\n const limit = options.limit ?? SUPERSEDED_LIMIT;\n const debounceMs = options.debounceMs ?? RESTART_DEBOUNCE_MS;\n const setTimer = options.setTimer ?? defaultTimer;\n const superseded = new Set<string>();\n let cancel: (() => void) | undefined;\n let checking = false;\n let cancelDeadline: (() => void) | undefined;\n let busyCheck: AbortController | undefined;\n let fired = false;\n let pendingSince: number | undefined;\n const pending = () => superseded.size >= limit;\n const poke = (): void => {\n if (!pending() || fired || cancel || checking) return;\n cancel = setTimer(() => {\n cancel = undefined;\n checking = true;\n let settled = false;\n const controller = new AbortController();\n busyCheck = controller;\n const finish = (busy: boolean, error?: unknown): void => {\n if (settled) return;\n settled = true;\n controller.abort();\n busyCheck = undefined;\n cancelDeadline?.();\n cancelDeadline = undefined;\n try {\n if (fired) return;\n if (error !== undefined) {\n options.onBlocked?.('check_failed', pendingSince === undefined ? 0 : Date.now() - pendingSince);\n options.onError(error);\n } else if (!busy && !fired) {\n fired = true;\n options.restart();\n }\n } catch (failure) {\n options.onError(failure);\n } finally {\n checking = false;\n poke();\n }\n };\n cancelDeadline = defaultTimer(() => {\n if (settled || fired) return;\n options.onBlocked?.('timeout', pendingSince === undefined ? 0 : Date.now() - pendingSince);\n finish(true);\n }, options.busyTimeoutMs ?? 10_000);\n void Promise.resolve()\n .then(() => options.busy(controller.signal))\n .then(\n (busy) => finish(busy),\n (error: unknown) => finish(true, error),\n );\n }, debounceMs);\n };\n return {\n supersede(urls) {\n for (const url of urls) superseded.add(url);\n if (pending() && pendingSince === undefined) pendingSince = Date.now();\n poke();\n },\n poke,\n pending,\n supersededCount: () => superseded.size,\n pendingAgeMs: () => (pendingSince === undefined || fired ? 0 : Math.max(0, Date.now() - pendingSince)),\n dispose() {\n cancel?.();\n cancelDeadline?.();\n busyCheck?.abort();\n busyCheck = undefined;\n cancelDeadline = undefined;\n cancel = undefined;\n fired = true;\n },\n };\n}\n\nexport interface RecycleState {\n sessionIds: string[];\n kind?: 'live';\n crashRestores?: number[];\n tunnel?: { hostname: string; closesAt?: number };\n}\n\nexport async function writeRecycleFile(\n directory: string,\n sessionIds: readonly string[],\n details: Omit<RecycleState, 'sessionIds'> = {},\n): Promise<void> {\n await fs.mkdir(directory, { recursive: true });\n const target = path.join(directory, RECYCLE_FILE);\n const staging = `${target}.${String(process.pid)}.tmp`;\n await fs.writeFile(staging, `${JSON.stringify({ ...details, sessionIds }, null, 2)}\\n`);\n await fs.rename(staging, target);\n}\n\n/** Accept legacy recycle records, never trust arbitrary extra fields or tunnel secrets. */\nexport async function readRecycleState(directory: string): Promise<RecycleState | undefined> {\n try {\n const file = path.join(directory, RECYCLE_FILE);\n if ((await fs.stat(file)).size > 1024 * 1024) return undefined;\n const parsed = JSON.parse(await fs.readFile(file, 'utf8')) as Partial<RecycleState> | null;\n if (!parsed || !Array.isArray(parsed.sessionIds) || (parsed.kind !== undefined && parsed.kind !== 'live'))\n return undefined;\n const tunnel = parseTunnelIntent(parsed.tunnel);\n return {\n sessionIds: [...new Set(parsed.sessionIds.filter((id): id is string => typeof id === 'string'))],\n ...(parsed.kind === 'live' ? { kind: 'live' } : {}),\n crashRestores: Array.isArray(parsed.crashRestores)\n ? parsed.crashRestores.filter((at): at is number => Number.isSafeInteger(at) && at >= 0)\n : [],\n ...(tunnel === undefined ? {} : { tunnel }),\n };\n } catch {\n return undefined;\n }\n}\n\nfunction parseTunnelIntent(value: unknown): RecycleState['tunnel'] {\n const tunnel = value as Partial<NonNullable<RecycleState['tunnel']>> | null | undefined;\n if (!tunnel || typeof tunnel.hostname !== 'string') return undefined;\n if (tunnel.closesAt !== undefined && !(Number.isSafeInteger(tunnel.closesAt) && tunnel.closesAt >= 0))\n return undefined;\n return { hostname: tunnel.hostname, ...(tunnel.closesAt === undefined ? {} : { closesAt: tunnel.closesAt }) };\n}\n\n/** Keeps the named tunnel intent through a normal shutdown, or clears it when there is none. */\nexport async function keepTunnelIntent(directory: string, tunnel: RecycleState['tunnel']): Promise<void> {\n const target = path.join(directory, TUNNEL_INTENT_FILE);\n if (tunnel === undefined) {\n await fs.rm(target, { force: true });\n return;\n }\n await fs.mkdir(directory, { recursive: true });\n await fs.writeFile(target, `${JSON.stringify(tunnel)}\\n`, { mode: 0o600 });\n}\n\n/** Reads and removes the kept intent, so a later crash never revives a tunnel switched off since. */\nexport async function takeTunnelIntent(directory: string): Promise<RecycleState['tunnel']> {\n const target = path.join(directory, TUNNEL_INTENT_FILE);\n try {\n return parseTunnelIntent(JSON.parse(await fs.readFile(target, 'utf8')));\n } catch {\n return undefined;\n } finally {\n await fs.rm(target, { force: true });\n }\n}\n\n/** Two automatic crash restores in 15 minutes, then require an explicit Wake. */\nexport function prepareSessionRestore(state: RecycleState | undefined, now = Date.now()) {\n const crashRestores = (state?.crashRestores ?? []).filter((at) => at > now - 15 * 60_000 && at <= now);\n const crash = state?.kind === 'live' && state.sessionIds.length > 0;\n const blocked = crash && crashRestores.length >= 2;\n if (crash && !blocked) crashRestores.push(now);\n return { sessionIds: blocked ? [] : (state?.sessionIds ?? []), crashRestores, blocked };\n}\n\nexport async function readRecycleFile(directory: string): Promise<string[]> {\n return (await readRecycleState(directory))?.sessionIds ?? [];\n}\n\nexport async function removeRecycleFile(directory: string): Promise<void> {\n await fs.rm(path.join(directory, RECYCLE_FILE), { force: true });\n}\n\n/** Reopens exactly the recycled sessions, then deletes the file whatever the outcome. */\nexport async function reopenRecycledSessions(\n directory: string,\n reopen: (sessionId: string) => Promise<void>,\n onError: (sessionId: string, error: unknown) => void,\n options: { sessionIds?: readonly string[]; removeAfter?: boolean } = {},\n): Promise<string[]> {\n const ids = options.sessionIds ?? (await readRecycleFile(directory));\n const reopened: string[] = [];\n try {\n for (const id of ids) {\n try {\n await reopen(id);\n reopened.push(id);\n } catch (error) {\n onError(id, error);\n }\n }\n } finally {\n if (options.removeAfter !== false) await removeRecycleFile(directory);\n }\n return reopened;\n}\n"],"mappings":"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"}
|