@muyichengshayu/promptx 0.2.7 → 0.2.8
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/CHANGELOG.md +5 -0
- package/apps/runner/src/engines/claudeCodeRunner.js +69 -1
- package/apps/runner/src/engines/claudeCodeRunner.test.js +279 -0
- package/apps/runner/src/engines/openCodeRunner.test.js +73 -0
- package/apps/runner/src/engines/shellRunner.test.js +46 -0
- package/apps/runner/src/runManager.js +110 -11
- package/apps/runner/src/runManager.test.js +913 -0
- package/apps/runner/src/serverClient.test.js +93 -0
- package/apps/server/src/agentSessionDiscovery.test.js +127 -0
- package/apps/server/src/agents/claudeCodeRunner.test.js +433 -0
- package/apps/server/src/agents/openCodeRunner.test.js +236 -0
- package/apps/server/src/agents/runnerContract.test.js +382 -0
- package/apps/server/src/appPaths.test.js +52 -0
- package/apps/server/src/assetRoutes.test.js +168 -0
- package/apps/server/src/codex.test.js +518 -0
- package/apps/server/src/codexRoutes.test.js +376 -0
- package/apps/server/src/codexRuns.test.js +160 -0
- package/apps/server/src/codexSessions.test.js +369 -0
- package/apps/server/src/db.test.js +182 -0
- package/apps/server/src/gitDiff.test.js +542 -0
- package/apps/server/src/gitDiffClient.test.js +140 -0
- package/apps/server/src/internalRoutes.test.js +134 -0
- package/apps/server/src/maintenance.test.js +154 -0
- package/apps/server/src/processControl.test.js +147 -0
- package/apps/server/src/relayClient.test.js +478 -0
- package/apps/server/src/relayConfig.test.js +73 -0
- package/apps/server/src/relayProtocol.test.js +49 -0
- package/apps/server/src/relayServer.test.js +798 -0
- package/apps/server/src/relayTenants.test.js +137 -0
- package/apps/server/src/relayUsageStore.test.js +65 -0
- package/apps/server/src/repository.test.js +150 -0
- package/apps/server/src/runDispatchService.test.js +563 -0
- package/apps/server/src/runEventIngest.test.js +225 -0
- package/apps/server/src/runRecovery.test.js +73 -0
- package/apps/server/src/runnerClient.test.js +80 -0
- package/apps/server/src/runnerDispatch.test.js +136 -0
- package/apps/server/src/systemConfig.test.js +112 -0
- package/apps/server/src/systemRoutes.test.js +319 -0
- package/apps/server/src/taskRoutes.test.js +726 -0
- package/apps/server/src/upload.test.js +30 -0
- package/apps/server/src/webAppRoutes.test.js +67 -0
- package/apps/server/src/workspaceFiles.test.js +262 -0
- package/package.json +14 -21
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSessionEnvelopeEvent,
|
|
3
3
|
createSessionUpdatedEnvelopeEvent,
|
|
4
|
+
createStatusEnvelopeEvent,
|
|
4
5
|
createStoppedEnvelopeEvent,
|
|
6
|
+
getAgentEngineLabel,
|
|
5
7
|
} from '../../../packages/shared/src/index.js'
|
|
6
8
|
import { assertAgentRunner } from './engines/index.js'
|
|
7
9
|
import { getChildStopDiagnostics } from './processControl.js'
|
|
@@ -23,6 +25,14 @@ const DEFAULT_EVENT_BATCH_BYTES = Math.max(
|
|
|
23
25
|
64 * 1024,
|
|
24
26
|
Number(process.env.PROMPTX_RUNNER_EVENT_BATCH_BYTES) || 512 * 1024
|
|
25
27
|
)
|
|
28
|
+
const DEFAULT_IDLE_PROGRESS_EVENT_MS = Math.max(
|
|
29
|
+
5000,
|
|
30
|
+
Number(process.env.PROMPTX_RUNNER_IDLE_PROGRESS_EVENT_MS) || 15000
|
|
31
|
+
)
|
|
32
|
+
const DEFAULT_IDLE_PROGRESS_EVENT_REPEAT_MS = Math.max(
|
|
33
|
+
DEFAULT_IDLE_PROGRESS_EVENT_MS,
|
|
34
|
+
Number(process.env.PROMPTX_RUNNER_IDLE_PROGRESS_EVENT_REPEAT_MS) || DEFAULT_IDLE_PROGRESS_EVENT_MS
|
|
35
|
+
)
|
|
26
36
|
const RUNNER_ID = String(process.env.PROMPTX_RUNNER_ID || 'local-runner').trim() || 'local-runner'
|
|
27
37
|
const DISPOSE_POLL_INTERVAL_MS = Math.max(50, Number(process.env.PROMPTX_RUNNER_DISPOSE_POLL_MS) || 100)
|
|
28
38
|
|
|
@@ -195,10 +205,57 @@ function sleep(ms) {
|
|
|
195
205
|
})
|
|
196
206
|
}
|
|
197
207
|
|
|
208
|
+
function isProgressPayload(payload = {}) {
|
|
209
|
+
const type = String(payload?.type || '').trim()
|
|
210
|
+
return !['status', 'session', 'session.updated'].includes(type)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function createIdleProgressEvent(context = {}) {
|
|
214
|
+
const status = String(context.status || '').trim()
|
|
215
|
+
if (status === 'queued') {
|
|
216
|
+
return createStatusEnvelopeEvent({
|
|
217
|
+
stage: 'queued',
|
|
218
|
+
message: '当前仍在排队,等待 runner 空闲后开始执行。',
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (status === 'stopping') {
|
|
223
|
+
return createStatusEnvelopeEvent({
|
|
224
|
+
stage: 'stopping',
|
|
225
|
+
message: '正在停止执行,等待引擎退出...',
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return createStatusEnvelopeEvent({
|
|
230
|
+
stage: 'running',
|
|
231
|
+
message: `${getAgentEngineLabel(context.engine || 'codex')} 仍在执行中,最近暂无新的过程输出。`,
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
198
235
|
export function createRunManager(options = {}) {
|
|
199
236
|
const serverClient = options.serverClient
|
|
200
237
|
const logger = options.logger || console
|
|
201
238
|
const resolveRunner = typeof options.resolveRunner === 'function' ? options.resolveRunner : assertAgentRunner
|
|
239
|
+
const eventFlushIntervalMs = Math.max(20, Number(options.eventFlushIntervalMs) || EVENT_FLUSH_INTERVAL_MS)
|
|
240
|
+
const heartbeatIntervalMs = Math.max(100, Number(options.heartbeatIntervalMs) || HEARTBEAT_INTERVAL_MS)
|
|
241
|
+
const stoppingHeartbeatIntervalMs = Math.max(
|
|
242
|
+
100,
|
|
243
|
+
Number(options.stoppingHeartbeatIntervalMs) || STOPPING_HEARTBEAT_INTERVAL_MS
|
|
244
|
+
)
|
|
245
|
+
const queuedHeartbeatIntervalMs = Math.max(
|
|
246
|
+
100,
|
|
247
|
+
Number(options.queuedHeartbeatIntervalMs) || QUEUED_HEARTBEAT_INTERVAL_MS
|
|
248
|
+
)
|
|
249
|
+
const defaultStopTimeoutMs = Math.max(1000, Number(options.defaultStopTimeoutMs) || DEFAULT_STOP_TIMEOUT_MS)
|
|
250
|
+
const stopTimeoutBufferMs = Math.max(200, Number(options.stopTimeoutBufferMs) || STOP_TIMEOUT_BUFFER_MS)
|
|
251
|
+
const idleProgressEventMs = Math.max(
|
|
252
|
+
heartbeatIntervalMs,
|
|
253
|
+
Number(options.idleProgressEventMs) || DEFAULT_IDLE_PROGRESS_EVENT_MS
|
|
254
|
+
)
|
|
255
|
+
const idleProgressEventRepeatMs = Math.max(
|
|
256
|
+
idleProgressEventMs,
|
|
257
|
+
Number(options.idleProgressEventRepeatMs) || DEFAULT_IDLE_PROGRESS_EVENT_REPEAT_MS
|
|
258
|
+
)
|
|
202
259
|
const runtimeConfig = {
|
|
203
260
|
maxConcurrentRuns: normalizeMaxConcurrentRuns(options.maxConcurrentRuns, DEFAULT_MAX_CONCURRENT_RUNS),
|
|
204
261
|
}
|
|
@@ -268,6 +325,11 @@ export function createRunManager(options = {}) {
|
|
|
268
325
|
? payload
|
|
269
326
|
: { type: 'status', message: String(payload || '') }
|
|
270
327
|
|
|
328
|
+
if (isProgressPayload(normalizedPayload)) {
|
|
329
|
+
context.lastProgressEventAt = Date.now()
|
|
330
|
+
context.lastIdleProgressEventAt = 0
|
|
331
|
+
}
|
|
332
|
+
|
|
271
333
|
context.lastSeq += 1
|
|
272
334
|
context.eventBuffer.push({
|
|
273
335
|
runId: context.runId,
|
|
@@ -371,10 +433,40 @@ export function createRunManager(options = {}) {
|
|
|
371
433
|
context.flushTimer = setTimeout(() => {
|
|
372
434
|
context.flushTimer = null
|
|
373
435
|
flushEvents(context).catch(() => {})
|
|
374
|
-
},
|
|
436
|
+
}, eventFlushIntervalMs)
|
|
375
437
|
context.flushTimer.unref?.()
|
|
376
438
|
}
|
|
377
439
|
|
|
440
|
+
function maybeQueueIdleProgressEvent(context) {
|
|
441
|
+
if (!context || context.finalized) {
|
|
442
|
+
return
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const status = String(context.status || '').trim()
|
|
446
|
+
if (!['queued', 'starting', 'running', 'stopping'].includes(status)) {
|
|
447
|
+
return
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const now = Date.now()
|
|
451
|
+
const lastProgressAt = Math.max(
|
|
452
|
+
0,
|
|
453
|
+
Number(context.lastProgressEventAt) || 0,
|
|
454
|
+
Date.parse(String(context.startedAt || '')) || 0
|
|
455
|
+
)
|
|
456
|
+
const lastIdleProgressEventAt = Math.max(0, Number(context.lastIdleProgressEventAt) || 0)
|
|
457
|
+
|
|
458
|
+
if (!lastProgressAt || now - lastProgressAt < idleProgressEventMs) {
|
|
459
|
+
return
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (lastIdleProgressEventAt && now - lastIdleProgressEventAt < idleProgressEventRepeatMs) {
|
|
463
|
+
return
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
queueEvent(context, createIdleProgressEvent(context))
|
|
467
|
+
context.lastIdleProgressEventAt = now
|
|
468
|
+
}
|
|
469
|
+
|
|
378
470
|
function startHeartbeat(context) {
|
|
379
471
|
if (context.heartbeatTimer) {
|
|
380
472
|
return
|
|
@@ -384,8 +476,9 @@ export function createRunManager(options = {}) {
|
|
|
384
476
|
if (context.finalized) {
|
|
385
477
|
return
|
|
386
478
|
}
|
|
479
|
+
maybeQueueIdleProgressEvent(context)
|
|
387
480
|
postStatus(context).catch(() => {})
|
|
388
|
-
},
|
|
481
|
+
}, heartbeatIntervalMs)
|
|
389
482
|
context.heartbeatTimer.unref?.()
|
|
390
483
|
}
|
|
391
484
|
|
|
@@ -405,8 +498,9 @@ export function createRunManager(options = {}) {
|
|
|
405
498
|
if (context.finalized || !isQueuedRunStatus(context.status)) {
|
|
406
499
|
return
|
|
407
500
|
}
|
|
501
|
+
maybeQueueIdleProgressEvent(context)
|
|
408
502
|
postStatus(context).catch(() => {})
|
|
409
|
-
},
|
|
503
|
+
}, queuedHeartbeatIntervalMs)
|
|
410
504
|
context.queueHeartbeatTimer.unref?.()
|
|
411
505
|
}
|
|
412
506
|
|
|
@@ -426,10 +520,11 @@ export function createRunManager(options = {}) {
|
|
|
426
520
|
if (context.finalized || !context.stopRequestedAt) {
|
|
427
521
|
return
|
|
428
522
|
}
|
|
523
|
+
maybeQueueIdleProgressEvent(context)
|
|
429
524
|
postStatus(context, {
|
|
430
525
|
stopRequestedAt: context.stopRequestedAt,
|
|
431
526
|
}).catch(() => {})
|
|
432
|
-
},
|
|
527
|
+
}, stoppingHeartbeatIntervalMs)
|
|
433
528
|
context.stopProgressTimer.unref?.()
|
|
434
529
|
}
|
|
435
530
|
|
|
@@ -706,11 +801,13 @@ export function createRunManager(options = {}) {
|
|
|
706
801
|
},
|
|
707
802
|
config: {
|
|
708
803
|
maxConcurrentRuns: runtimeConfig.maxConcurrentRuns,
|
|
709
|
-
eventFlushIntervalMs
|
|
710
|
-
heartbeatIntervalMs
|
|
711
|
-
queuedHeartbeatIntervalMs
|
|
712
|
-
stoppingHeartbeatIntervalMs
|
|
713
|
-
|
|
804
|
+
eventFlushIntervalMs,
|
|
805
|
+
heartbeatIntervalMs,
|
|
806
|
+
queuedHeartbeatIntervalMs,
|
|
807
|
+
stoppingHeartbeatIntervalMs,
|
|
808
|
+
idleProgressEventMs,
|
|
809
|
+
idleProgressEventRepeatMs,
|
|
810
|
+
defaultStopTimeoutMs,
|
|
714
811
|
},
|
|
715
812
|
}
|
|
716
813
|
},
|
|
@@ -752,6 +849,8 @@ export function createRunManager(options = {}) {
|
|
|
752
849
|
finishedAt: '',
|
|
753
850
|
stopRequestedAt: '',
|
|
754
851
|
lastHeartbeatAt: '',
|
|
852
|
+
lastProgressEventAt: Date.now(),
|
|
853
|
+
lastIdleProgressEventAt: 0,
|
|
755
854
|
lastSeq: 0,
|
|
756
855
|
eventBuffer: [],
|
|
757
856
|
flushTimer: null,
|
|
@@ -818,7 +917,7 @@ export function createRunManager(options = {}) {
|
|
|
818
917
|
|
|
819
918
|
const stopGraceMs = Math.max(200, Number(options.forceAfterMs) || 1500)
|
|
820
919
|
context.stopGraceMs = stopGraceMs
|
|
821
|
-
const stopTimeoutMs = Math.max(
|
|
920
|
+
const stopTimeoutMs = Math.max(defaultStopTimeoutMs, stopGraceMs + stopTimeoutBufferMs)
|
|
822
921
|
ensureStopTimeout(context, stopTimeoutMs)
|
|
823
922
|
|
|
824
923
|
try {
|
|
@@ -841,7 +940,7 @@ export function createRunManager(options = {}) {
|
|
|
841
940
|
)
|
|
842
941
|
)
|
|
843
942
|
|
|
844
|
-
const deadline = Date.now() +
|
|
943
|
+
const deadline = Date.now() + defaultStopTimeoutMs + stopTimeoutBufferMs
|
|
845
944
|
while (activeRuns.size && Date.now() < deadline) {
|
|
846
945
|
await sleep(DISPOSE_POLL_INTERVAL_MS)
|
|
847
946
|
}
|