@muyichengshayu/promptx 0.1.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/README.md +80 -0
- package/apps/server/src/appPaths.js +102 -0
- package/apps/server/src/codex.js +585 -0
- package/apps/server/src/codexRunRuntime.js +212 -0
- package/apps/server/src/codexRuns.js +525 -0
- package/apps/server/src/codexSessions.js +149 -0
- package/apps/server/src/db.js +389 -0
- package/apps/server/src/gitDiff.js +1425 -0
- package/apps/server/src/index.js +909 -0
- package/apps/server/src/pdf.js +383 -0
- package/apps/server/src/repository.js +484 -0
- package/apps/server/src/sseHub.js +69 -0
- package/apps/server/src/upload.js +22 -0
- package/apps/server/src/workspaceFiles.js +662 -0
- package/apps/web/dist/assets/CodexSessionManagerDialog-c35LrKjV.js +6 -0
- package/apps/web/dist/assets/TaskDiffReviewDialog-BYcla0q4.js +12 -0
- package/apps/web/dist/assets/WorkbenchSettingsDialog-C0uQRStP.js +1 -0
- package/apps/web/dist/assets/WorkbenchView-Cp_qHNdX.js +216 -0
- package/apps/web/dist/assets/index-D9ui_gwj.js +25 -0
- package/apps/web/dist/assets/index-DDNrspNi.css +1 -0
- package/apps/web/dist/index.html +16 -0
- package/bin/promptx.js +60 -0
- package/package.json +58 -0
- package/packages/shared/src/index.js +121 -0
- package/scripts/doctor.mjs +251 -0
- package/scripts/service.mjs +308 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { getPromptxCodexSessionById, updatePromptxCodexSession } from './codexSessions.js'
|
|
2
|
+
import { streamPromptToCodexSession } from './codex.js'
|
|
3
|
+
import { appendCodexRunEvent, updateCodexRun } from './codexRuns.js'
|
|
4
|
+
|
|
5
|
+
export function createCodexRunRuntime(options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
decorateSession = (session) => session,
|
|
8
|
+
onRunEvent = () => {},
|
|
9
|
+
onRunUpdated = () => {},
|
|
10
|
+
onSessionChanged = () => {},
|
|
11
|
+
} = options
|
|
12
|
+
|
|
13
|
+
const activeControllers = new Map()
|
|
14
|
+
|
|
15
|
+
function getController(runId = '') {
|
|
16
|
+
return activeControllers.get(String(runId || '').trim()) || null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function setController(runId = '', controller) {
|
|
20
|
+
const normalizedRunId = String(runId || '').trim()
|
|
21
|
+
if (!normalizedRunId || !controller) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
activeControllers.set(normalizedRunId, controller)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function clearController(runId = '') {
|
|
29
|
+
const normalizedRunId = String(runId || '').trim()
|
|
30
|
+
if (!normalizedRunId) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
activeControllers.delete(normalizedRunId)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function notifyListeners(runId = '', payload = {}) {
|
|
38
|
+
const controller = getController(runId)
|
|
39
|
+
if (!controller?.listeners?.size) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
controller.listeners.forEach((listener) => {
|
|
44
|
+
try {
|
|
45
|
+
listener(payload)
|
|
46
|
+
} catch {
|
|
47
|
+
// Ignore observer failures to avoid affecting the run lifecycle.
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function subscribe(runId = '', listener) {
|
|
53
|
+
const controller = getController(runId)
|
|
54
|
+
if (!controller || typeof listener !== 'function') {
|
|
55
|
+
return () => {}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
controller.listeners.add(listener)
|
|
59
|
+
return () => {
|
|
60
|
+
controller.listeners.delete(listener)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function start(runRecord) {
|
|
65
|
+
const runId = String(runRecord?.id || '').trim()
|
|
66
|
+
if (!runId) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const session = getPromptxCodexSessionById(runRecord.sessionId)
|
|
71
|
+
if (!session) {
|
|
72
|
+
updateCodexRun(runId, {
|
|
73
|
+
status: 'error',
|
|
74
|
+
errorMessage: '没有找到对应的 PromptX 项目。',
|
|
75
|
+
finishedAt: new Date().toISOString(),
|
|
76
|
+
})
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let eventSeq = 0
|
|
81
|
+
let stopRequested = false
|
|
82
|
+
|
|
83
|
+
const persistRunEvent = (payload) => {
|
|
84
|
+
eventSeq += 1
|
|
85
|
+
const event = appendCodexRunEvent(runId, eventSeq, payload)
|
|
86
|
+
if (event) {
|
|
87
|
+
onRunEvent({
|
|
88
|
+
taskSlug: runRecord.taskSlug,
|
|
89
|
+
runId,
|
|
90
|
+
event,
|
|
91
|
+
})
|
|
92
|
+
notifyListeners(runId, {
|
|
93
|
+
type: 'event',
|
|
94
|
+
event,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
return event
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
persistRunEvent({
|
|
101
|
+
type: 'session',
|
|
102
|
+
session: decorateSession(session),
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const stream = streamPromptToCodexSession(session, runRecord.prompt, {
|
|
106
|
+
onEvent(payload) {
|
|
107
|
+
persistRunEvent(payload)
|
|
108
|
+
},
|
|
109
|
+
onThreadStarted(threadId) {
|
|
110
|
+
const updatedSession = updatePromptxCodexSession(session.id, {
|
|
111
|
+
codexThreadId: threadId,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
if (updatedSession) {
|
|
115
|
+
persistRunEvent({
|
|
116
|
+
type: 'session.updated',
|
|
117
|
+
session: decorateSession(updatedSession),
|
|
118
|
+
})
|
|
119
|
+
onSessionChanged({
|
|
120
|
+
sessionId: session.id,
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const controller = {
|
|
127
|
+
listeners: new Set(),
|
|
128
|
+
cancel() {
|
|
129
|
+
stopRequested = true
|
|
130
|
+
stream.cancel()
|
|
131
|
+
},
|
|
132
|
+
get stopRequested() {
|
|
133
|
+
return stopRequested
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
setController(runId, controller)
|
|
137
|
+
|
|
138
|
+
stream.result
|
|
139
|
+
.then((result) => {
|
|
140
|
+
const nextRun = updateCodexRun(runId, {
|
|
141
|
+
status: 'completed',
|
|
142
|
+
responseMessage: result.message || '',
|
|
143
|
+
errorMessage: '',
|
|
144
|
+
finishedAt: new Date().toISOString(),
|
|
145
|
+
})
|
|
146
|
+
notifyListeners(runId, {
|
|
147
|
+
type: 'run',
|
|
148
|
+
run: nextRun,
|
|
149
|
+
})
|
|
150
|
+
onRunUpdated({
|
|
151
|
+
taskSlug: runRecord.taskSlug,
|
|
152
|
+
runId,
|
|
153
|
+
})
|
|
154
|
+
onSessionChanged({
|
|
155
|
+
sessionId: session.id,
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
.catch((error) => {
|
|
159
|
+
if (stopRequested) {
|
|
160
|
+
persistRunEvent({
|
|
161
|
+
type: 'stopped',
|
|
162
|
+
message: '执行已手动停止。',
|
|
163
|
+
})
|
|
164
|
+
const nextRun = updateCodexRun(runId, {
|
|
165
|
+
status: 'stopped',
|
|
166
|
+
responseMessage: '',
|
|
167
|
+
errorMessage: '',
|
|
168
|
+
finishedAt: new Date().toISOString(),
|
|
169
|
+
})
|
|
170
|
+
notifyListeners(runId, {
|
|
171
|
+
type: 'run',
|
|
172
|
+
run: nextRun,
|
|
173
|
+
})
|
|
174
|
+
onRunUpdated({
|
|
175
|
+
taskSlug: runRecord.taskSlug,
|
|
176
|
+
runId,
|
|
177
|
+
})
|
|
178
|
+
onSessionChanged({
|
|
179
|
+
sessionId: session.id,
|
|
180
|
+
})
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const nextRun = updateCodexRun(runId, {
|
|
185
|
+
status: 'error',
|
|
186
|
+
errorMessage: error.message || 'Codex 执行失败。',
|
|
187
|
+
finishedAt: new Date().toISOString(),
|
|
188
|
+
})
|
|
189
|
+
notifyListeners(runId, {
|
|
190
|
+
type: 'run',
|
|
191
|
+
run: nextRun,
|
|
192
|
+
})
|
|
193
|
+
onRunUpdated({
|
|
194
|
+
taskSlug: runRecord.taskSlug,
|
|
195
|
+
runId,
|
|
196
|
+
})
|
|
197
|
+
onSessionChanged({
|
|
198
|
+
sessionId: session.id,
|
|
199
|
+
})
|
|
200
|
+
})
|
|
201
|
+
.finally(() => {
|
|
202
|
+
notifyListeners(runId, { type: 'close' })
|
|
203
|
+
clearController(runId)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
getController,
|
|
209
|
+
subscribe,
|
|
210
|
+
start,
|
|
211
|
+
}
|
|
212
|
+
}
|