codex-autorunner 0.1.2__py3-none-any.whl → 1.0.0__py3-none-any.whl
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.
- codex_autorunner/__main__.py +4 -0
- codex_autorunner/agents/opencode/client.py +68 -35
- codex_autorunner/agents/opencode/logging.py +21 -5
- codex_autorunner/agents/opencode/run_prompt.py +1 -0
- codex_autorunner/agents/opencode/runtime.py +118 -30
- codex_autorunner/agents/opencode/supervisor.py +36 -48
- codex_autorunner/agents/registry.py +136 -8
- codex_autorunner/api.py +25 -0
- codex_autorunner/bootstrap.py +16 -35
- codex_autorunner/cli.py +157 -139
- codex_autorunner/core/about_car.py +44 -32
- codex_autorunner/core/adapter_utils.py +21 -0
- codex_autorunner/core/app_server_logging.py +7 -3
- codex_autorunner/core/app_server_prompts.py +27 -260
- codex_autorunner/core/app_server_threads.py +15 -26
- codex_autorunner/core/codex_runner.py +6 -0
- codex_autorunner/core/config.py +390 -100
- codex_autorunner/core/docs.py +10 -2
- codex_autorunner/core/drafts.py +82 -0
- codex_autorunner/core/engine.py +278 -262
- codex_autorunner/core/flows/__init__.py +25 -0
- codex_autorunner/core/flows/controller.py +178 -0
- codex_autorunner/core/flows/definition.py +82 -0
- codex_autorunner/core/flows/models.py +75 -0
- codex_autorunner/core/flows/runtime.py +351 -0
- codex_autorunner/core/flows/store.py +485 -0
- codex_autorunner/core/flows/transition.py +133 -0
- codex_autorunner/core/flows/worker_process.py +242 -0
- codex_autorunner/core/hub.py +15 -9
- codex_autorunner/core/locks.py +4 -0
- codex_autorunner/core/prompt.py +15 -7
- codex_autorunner/core/redaction.py +29 -0
- codex_autorunner/core/review_context.py +5 -8
- codex_autorunner/core/run_index.py +6 -0
- codex_autorunner/core/runner_process.py +5 -2
- codex_autorunner/core/state.py +0 -88
- codex_autorunner/core/static_assets.py +55 -0
- codex_autorunner/core/supervisor_utils.py +67 -0
- codex_autorunner/core/update.py +20 -11
- codex_autorunner/core/update_runner.py +2 -0
- codex_autorunner/core/utils.py +29 -2
- codex_autorunner/discovery.py +2 -4
- codex_autorunner/flows/ticket_flow/__init__.py +3 -0
- codex_autorunner/flows/ticket_flow/definition.py +91 -0
- codex_autorunner/integrations/agents/__init__.py +27 -0
- codex_autorunner/integrations/agents/agent_backend.py +142 -0
- codex_autorunner/integrations/agents/codex_backend.py +307 -0
- codex_autorunner/integrations/agents/opencode_backend.py +325 -0
- codex_autorunner/integrations/agents/run_event.py +71 -0
- codex_autorunner/integrations/app_server/client.py +576 -92
- codex_autorunner/integrations/app_server/supervisor.py +59 -33
- codex_autorunner/integrations/telegram/adapter.py +141 -167
- codex_autorunner/integrations/telegram/api_schemas.py +120 -0
- codex_autorunner/integrations/telegram/config.py +175 -0
- codex_autorunner/integrations/telegram/constants.py +16 -1
- codex_autorunner/integrations/telegram/dispatch.py +17 -0
- codex_autorunner/integrations/telegram/doctor.py +47 -0
- codex_autorunner/integrations/telegram/handlers/callbacks.py +0 -4
- codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
- codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
- codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
- codex_autorunner/integrations/telegram/handlers/commands/flows.py +227 -0
- codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
- codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
- codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +133 -475
- codex_autorunner/integrations/telegram/handlers/commands_spec.py +11 -4
- codex_autorunner/integrations/telegram/handlers/messages.py +120 -9
- codex_autorunner/integrations/telegram/helpers.py +88 -16
- codex_autorunner/integrations/telegram/outbox.py +208 -37
- codex_autorunner/integrations/telegram/progress_stream.py +3 -10
- codex_autorunner/integrations/telegram/service.py +214 -40
- codex_autorunner/integrations/telegram/state.py +100 -2
- codex_autorunner/integrations/telegram/ticket_flow_bridge.py +322 -0
- codex_autorunner/integrations/telegram/transport.py +36 -3
- codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
- codex_autorunner/manifest.py +2 -0
- codex_autorunner/plugin_api.py +22 -0
- codex_autorunner/routes/__init__.py +23 -14
- codex_autorunner/routes/analytics.py +239 -0
- codex_autorunner/routes/base.py +81 -109
- codex_autorunner/routes/file_chat.py +836 -0
- codex_autorunner/routes/flows.py +980 -0
- codex_autorunner/routes/messages.py +459 -0
- codex_autorunner/routes/system.py +6 -1
- codex_autorunner/routes/usage.py +87 -0
- codex_autorunner/routes/workspace.py +271 -0
- codex_autorunner/server.py +2 -1
- codex_autorunner/static/agentControls.js +1 -0
- codex_autorunner/static/agentEvents.js +248 -0
- codex_autorunner/static/app.js +25 -22
- codex_autorunner/static/autoRefresh.js +29 -1
- codex_autorunner/static/bootstrap.js +1 -0
- codex_autorunner/static/bus.js +1 -0
- codex_autorunner/static/cache.js +1 -0
- codex_autorunner/static/constants.js +20 -4
- codex_autorunner/static/dashboard.js +162 -196
- codex_autorunner/static/diffRenderer.js +37 -0
- codex_autorunner/static/docChatCore.js +324 -0
- codex_autorunner/static/docChatStorage.js +65 -0
- codex_autorunner/static/docChatVoice.js +65 -0
- codex_autorunner/static/docEditor.js +133 -0
- codex_autorunner/static/env.js +1 -0
- codex_autorunner/static/eventSummarizer.js +166 -0
- codex_autorunner/static/fileChat.js +182 -0
- codex_autorunner/static/health.js +155 -0
- codex_autorunner/static/hub.js +41 -118
- codex_autorunner/static/index.html +787 -858
- codex_autorunner/static/liveUpdates.js +1 -0
- codex_autorunner/static/loader.js +1 -0
- codex_autorunner/static/messages.js +470 -0
- codex_autorunner/static/mobileCompact.js +2 -1
- codex_autorunner/static/settings.js +24 -211
- codex_autorunner/static/styles.css +7567 -3865
- codex_autorunner/static/tabs.js +28 -5
- codex_autorunner/static/terminal.js +14 -0
- codex_autorunner/static/terminalManager.js +34 -59
- codex_autorunner/static/ticketChatActions.js +333 -0
- codex_autorunner/static/ticketChatEvents.js +16 -0
- codex_autorunner/static/ticketChatStorage.js +16 -0
- codex_autorunner/static/ticketChatStream.js +264 -0
- codex_autorunner/static/ticketEditor.js +750 -0
- codex_autorunner/static/ticketVoice.js +9 -0
- codex_autorunner/static/tickets.js +1315 -0
- codex_autorunner/static/utils.js +32 -3
- codex_autorunner/static/voice.js +1 -0
- codex_autorunner/static/workspace.js +672 -0
- codex_autorunner/static/workspaceApi.js +53 -0
- codex_autorunner/static/workspaceFileBrowser.js +504 -0
- codex_autorunner/tickets/__init__.py +20 -0
- codex_autorunner/tickets/agent_pool.py +377 -0
- codex_autorunner/tickets/files.py +85 -0
- codex_autorunner/tickets/frontmatter.py +55 -0
- codex_autorunner/tickets/lint.py +102 -0
- codex_autorunner/tickets/models.py +95 -0
- codex_autorunner/tickets/outbox.py +232 -0
- codex_autorunner/tickets/replies.py +179 -0
- codex_autorunner/tickets/runner.py +823 -0
- codex_autorunner/tickets/spec_ingest.py +77 -0
- codex_autorunner/web/app.py +269 -91
- codex_autorunner/web/middleware.py +3 -4
- codex_autorunner/web/schemas.py +89 -109
- codex_autorunner/web/static_assets.py +1 -44
- codex_autorunner/workspace/__init__.py +40 -0
- codex_autorunner/workspace/paths.py +319 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/METADATA +18 -21
- codex_autorunner-1.0.0.dist-info/RECORD +251 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/WHEEL +1 -1
- codex_autorunner/agents/execution/policy.py +0 -292
- codex_autorunner/agents/factory.py +0 -52
- codex_autorunner/agents/orchestrator.py +0 -358
- codex_autorunner/core/doc_chat.py +0 -1446
- codex_autorunner/core/snapshot.py +0 -580
- codex_autorunner/integrations/github/chatops.py +0 -268
- codex_autorunner/integrations/github/pr_flow.py +0 -1314
- codex_autorunner/routes/docs.py +0 -381
- codex_autorunner/routes/github.py +0 -327
- codex_autorunner/routes/runs.py +0 -250
- codex_autorunner/spec_ingest.py +0 -812
- codex_autorunner/static/docChatActions.js +0 -287
- codex_autorunner/static/docChatEvents.js +0 -300
- codex_autorunner/static/docChatRender.js +0 -205
- codex_autorunner/static/docChatStream.js +0 -361
- codex_autorunner/static/docs.js +0 -20
- codex_autorunner/static/docsClipboard.js +0 -69
- codex_autorunner/static/docsCrud.js +0 -257
- codex_autorunner/static/docsDocUpdates.js +0 -62
- codex_autorunner/static/docsDrafts.js +0 -16
- codex_autorunner/static/docsElements.js +0 -69
- codex_autorunner/static/docsInit.js +0 -285
- codex_autorunner/static/docsParse.js +0 -160
- codex_autorunner/static/docsSnapshot.js +0 -87
- codex_autorunner/static/docsSpecIngest.js +0 -263
- codex_autorunner/static/docsState.js +0 -127
- codex_autorunner/static/docsThreadRegistry.js +0 -44
- codex_autorunner/static/docsUi.js +0 -153
- codex_autorunner/static/docsVoice.js +0 -56
- codex_autorunner/static/github.js +0 -504
- codex_autorunner/static/logs.js +0 -678
- codex_autorunner/static/review.js +0 -157
- codex_autorunner/static/runs.js +0 -418
- codex_autorunner/static/snapshot.js +0 -124
- codex_autorunner/static/state.js +0 -94
- codex_autorunner/static/todoPreview.js +0 -27
- codex_autorunner/workspace.py +0 -16
- codex_autorunner-0.1.2.dist-info/RECORD +0 -222
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/entry_points.txt +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import { api, flash, confirmModal } from "./utils.js";
|
|
2
|
-
import { chatUI } from "./docsElements.js";
|
|
3
|
-
import { CHAT_HISTORY_LIMIT, DOC_TYPES, docsState, getActiveDoc, getChatState, getDocChatViewing, getDraft, isDraftPreview, setDraft, setDraftPreview, setHistoryNavIndex, resetChatEvents, } from "./docsState.js";
|
|
4
|
-
import { normalizeDraftPayload, parseChatPayload } from "./docsParse.js";
|
|
5
|
-
import { renderChat } from "./docChatRender.js";
|
|
6
|
-
import { performDocChatRequest } from "./docChatStream.js";
|
|
7
|
-
import { applyDocUpdateFromChat } from "./docsDocUpdates.js";
|
|
8
|
-
import { autoResizeTextarea, getDocTextarea, syncDocEditor } from "./docsUi.js";
|
|
9
|
-
import { getSelectedAgent, getSelectedModel, getSelectedReasoning, } from "./agentControls.js";
|
|
10
|
-
function markChatError(state, entry, message) {
|
|
11
|
-
entry.status = "error";
|
|
12
|
-
entry.error = message;
|
|
13
|
-
state.error = message;
|
|
14
|
-
state.status = "error";
|
|
15
|
-
renderChat();
|
|
16
|
-
}
|
|
17
|
-
function restoreChatInput(entry) {
|
|
18
|
-
if (!entry?.prompt || chatUI.input.value)
|
|
19
|
-
return;
|
|
20
|
-
chatUI.input.value = entry.prompt;
|
|
21
|
-
autoResizeTextarea(chatUI.input);
|
|
22
|
-
}
|
|
23
|
-
async function interruptDocChat() {
|
|
24
|
-
try {
|
|
25
|
-
await api("/api/docs/chat/interrupt", { method: "POST" });
|
|
26
|
-
}
|
|
27
|
-
catch (err) {
|
|
28
|
-
const error = err;
|
|
29
|
-
flash(error.message || "Failed to interrupt doc chat", "error");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export function cancelDocChat() {
|
|
33
|
-
const state = getChatState();
|
|
34
|
-
if (state.status !== "running")
|
|
35
|
-
return;
|
|
36
|
-
interruptDocChat();
|
|
37
|
-
if (state.controller)
|
|
38
|
-
state.controller.abort();
|
|
39
|
-
resetChatEvents(state, { preserve: true });
|
|
40
|
-
const entry = state.history[0];
|
|
41
|
-
if (entry && entry.status === "running") {
|
|
42
|
-
entry.status = "interrupted";
|
|
43
|
-
entry.error = "Interrupted";
|
|
44
|
-
}
|
|
45
|
-
state.status = "interrupted";
|
|
46
|
-
state.error = "";
|
|
47
|
-
state.streamText = "";
|
|
48
|
-
state.statusText = "";
|
|
49
|
-
state.controller = null;
|
|
50
|
-
renderChat();
|
|
51
|
-
}
|
|
52
|
-
export async function startNewDocChatThread() {
|
|
53
|
-
const state = getChatState();
|
|
54
|
-
if (state.status === "running") {
|
|
55
|
-
cancelDocChat();
|
|
56
|
-
}
|
|
57
|
-
const agent = getSelectedAgent();
|
|
58
|
-
const key = agent === "opencode" ? "doc_chat.opencode" : "doc_chat";
|
|
59
|
-
try {
|
|
60
|
-
await api("/api/app-server/threads/reset", {
|
|
61
|
-
method: "POST",
|
|
62
|
-
body: { key },
|
|
63
|
-
});
|
|
64
|
-
state.history = [];
|
|
65
|
-
state.status = "idle";
|
|
66
|
-
state.statusText = "";
|
|
67
|
-
state.error = "";
|
|
68
|
-
state.streamText = "";
|
|
69
|
-
setHistoryNavIndex(-1);
|
|
70
|
-
resetChatEvents(state);
|
|
71
|
-
chatUI.input.value = "";
|
|
72
|
-
renderChat();
|
|
73
|
-
flash("Started a new doc chat thread");
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
const error = err;
|
|
77
|
-
flash(error.message || "Failed to start a new doc chat thread", "error");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
export async function sendDocChat() {
|
|
81
|
-
const message = (chatUI.input.value || "").trim();
|
|
82
|
-
const state = getChatState();
|
|
83
|
-
if (!message) {
|
|
84
|
-
state.error = "Enter a message to send.";
|
|
85
|
-
renderChat();
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
if (state.status === "running") {
|
|
89
|
-
state.error = "Doc chat already running.";
|
|
90
|
-
renderChat();
|
|
91
|
-
flash("Doc chat already running", "error");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
resetChatEvents(state);
|
|
95
|
-
const viewing = getDocChatViewing();
|
|
96
|
-
const entry = {
|
|
97
|
-
id: `${Date.now()}`,
|
|
98
|
-
prompt: message,
|
|
99
|
-
viewing,
|
|
100
|
-
agent: getSelectedAgent(),
|
|
101
|
-
model: getSelectedModel(),
|
|
102
|
-
reasoning: getSelectedReasoning(),
|
|
103
|
-
response: "",
|
|
104
|
-
status: "running",
|
|
105
|
-
time: String(Date.now()),
|
|
106
|
-
drafts: {},
|
|
107
|
-
updated: [],
|
|
108
|
-
};
|
|
109
|
-
state.history.unshift(entry);
|
|
110
|
-
if (state.history.length > CHAT_HISTORY_LIMIT * 2) {
|
|
111
|
-
state.history.length = CHAT_HISTORY_LIMIT * 2;
|
|
112
|
-
}
|
|
113
|
-
state.status = "running";
|
|
114
|
-
state.error = "";
|
|
115
|
-
state.streamText = "";
|
|
116
|
-
state.statusText = "queued";
|
|
117
|
-
state.controller = new AbortController();
|
|
118
|
-
renderChat();
|
|
119
|
-
chatUI.input.value = "";
|
|
120
|
-
chatUI.input.style.height = "auto";
|
|
121
|
-
chatUI.input.focus();
|
|
122
|
-
try {
|
|
123
|
-
await performDocChatRequest(entry, state);
|
|
124
|
-
refreshAllDrafts().catch(() => { });
|
|
125
|
-
if (entry.status === "interrupted") {
|
|
126
|
-
state.status = "interrupted";
|
|
127
|
-
state.error = "";
|
|
128
|
-
}
|
|
129
|
-
else if (entry.status !== "error") {
|
|
130
|
-
state.status = "idle";
|
|
131
|
-
state.error = "";
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
catch (err) {
|
|
135
|
-
const error = err;
|
|
136
|
-
if (error.name === "AbortError") {
|
|
137
|
-
entry.status = "interrupted";
|
|
138
|
-
entry.error = "Interrupted";
|
|
139
|
-
state.error = "";
|
|
140
|
-
state.status = "interrupted";
|
|
141
|
-
resetChatEvents(state, { preserve: true });
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
restoreChatInput(entry);
|
|
145
|
-
markChatError(state, entry, error.message || "Doc chat failed");
|
|
146
|
-
resetChatEvents(state, { preserve: true });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
finally {
|
|
150
|
-
state.controller = null;
|
|
151
|
-
if (state.status !== "running") {
|
|
152
|
-
renderChat();
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
export async function toggleDraftPreview(kind = getActiveDoc()) {
|
|
157
|
-
const draft = getDraft(kind);
|
|
158
|
-
if (!draft)
|
|
159
|
-
return;
|
|
160
|
-
const nextValue = !isDraftPreview(kind);
|
|
161
|
-
if (nextValue) {
|
|
162
|
-
const textarea = getDocTextarea();
|
|
163
|
-
if (textarea) {
|
|
164
|
-
const cached = docsState.docsCache[kind || ""] || "";
|
|
165
|
-
if (textarea.value !== cached) {
|
|
166
|
-
const ok = await confirmModal(`You have unsaved ${(kind || "").toUpperCase()} edits. Overwrite with draft preview?`);
|
|
167
|
-
if (!ok)
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
setDraftPreview(kind, nextValue);
|
|
173
|
-
syncDocEditor(kind, { force: true });
|
|
174
|
-
renderChat();
|
|
175
|
-
}
|
|
176
|
-
export async function applyPatch(kind = getActiveDoc()) {
|
|
177
|
-
const state = getChatState();
|
|
178
|
-
const draft = getDraft(kind);
|
|
179
|
-
if (!draft) {
|
|
180
|
-
flash("No draft to apply", "error");
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
try {
|
|
184
|
-
const res = await api(`/api/docs/${kind}/chat/apply`, { method: "POST" });
|
|
185
|
-
const applied = parseChatPayload(res);
|
|
186
|
-
if (applied.error)
|
|
187
|
-
throw new Error(applied.error);
|
|
188
|
-
setDraftPreview(kind, false);
|
|
189
|
-
setDraft(kind, null);
|
|
190
|
-
if (applied.content) {
|
|
191
|
-
await applyDocUpdateFromChat(kind, applied.content, { force: true });
|
|
192
|
-
}
|
|
193
|
-
const latest = state.history[0];
|
|
194
|
-
if (latest)
|
|
195
|
-
latest.status = "done";
|
|
196
|
-
flash("Draft applied");
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
const error = err;
|
|
200
|
-
flash(error.message || "Failed to apply draft", "error");
|
|
201
|
-
}
|
|
202
|
-
finally {
|
|
203
|
-
renderChat();
|
|
204
|
-
syncDocEditor(kind, { force: true });
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
export async function discardPatch(kind = getActiveDoc()) {
|
|
208
|
-
const state = getChatState();
|
|
209
|
-
const draft = getDraft(kind);
|
|
210
|
-
if (!draft)
|
|
211
|
-
return;
|
|
212
|
-
try {
|
|
213
|
-
const res = await api(`/api/docs/${kind}/chat/discard`, { method: "POST" });
|
|
214
|
-
const parsed = parseChatPayload(res);
|
|
215
|
-
setDraftPreview(kind, false);
|
|
216
|
-
setDraft(kind, null);
|
|
217
|
-
if (parsed.content) {
|
|
218
|
-
await applyDocUpdateFromChat(kind, parsed.content, { force: true });
|
|
219
|
-
}
|
|
220
|
-
const latest = state.history[0];
|
|
221
|
-
if (latest) {
|
|
222
|
-
latest.status = latest.status === "running" ? "done" : latest.status;
|
|
223
|
-
if (latest.drafts) {
|
|
224
|
-
delete latest.drafts[kind];
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
flash("Draft discarded");
|
|
228
|
-
}
|
|
229
|
-
catch (err) {
|
|
230
|
-
const error = err;
|
|
231
|
-
flash(error.message || "Failed to discard draft", "error");
|
|
232
|
-
}
|
|
233
|
-
finally {
|
|
234
|
-
renderChat();
|
|
235
|
-
syncDocEditor(kind, { force: true });
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
export async function reloadPatch(kind = getActiveDoc(), silent = false) {
|
|
239
|
-
try {
|
|
240
|
-
const res = await api(`/api/docs/${kind}/chat/pending`, { method: "GET" });
|
|
241
|
-
const parsed = parseChatPayload(res);
|
|
242
|
-
if (parsed.error)
|
|
243
|
-
throw new Error(parsed.error);
|
|
244
|
-
const normalized = normalizeDraftPayload({
|
|
245
|
-
content: parsed.content,
|
|
246
|
-
patch: parsed.patch,
|
|
247
|
-
agent_message: parsed.agentMessage || parsed.response || "",
|
|
248
|
-
created_at: parsed.createdAt || "",
|
|
249
|
-
base_hash: parsed.baseHash || "",
|
|
250
|
-
});
|
|
251
|
-
if (normalized) {
|
|
252
|
-
setDraft(kind, normalized);
|
|
253
|
-
if (isDraftPreview(kind)) {
|
|
254
|
-
syncDocEditor(kind, { force: true });
|
|
255
|
-
}
|
|
256
|
-
renderChat();
|
|
257
|
-
if (!silent)
|
|
258
|
-
flash("Loaded pending draft");
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
catch (err) {
|
|
263
|
-
const error = err;
|
|
264
|
-
const message = error?.message || "";
|
|
265
|
-
if (message.includes("No pending")) {
|
|
266
|
-
setDraft(kind, null);
|
|
267
|
-
if (isDraftPreview(kind)) {
|
|
268
|
-
setDraftPreview(kind, false);
|
|
269
|
-
syncDocEditor(kind, { force: true });
|
|
270
|
-
}
|
|
271
|
-
if (!silent)
|
|
272
|
-
flash("No pending draft");
|
|
273
|
-
}
|
|
274
|
-
else if (message.includes("Autorunner") &&
|
|
275
|
-
(message.includes("running") || message.includes("lock") || message.includes("blocked"))) {
|
|
276
|
-
if (!silent)
|
|
277
|
-
flash(message || "Repo busy; try again later", "info");
|
|
278
|
-
}
|
|
279
|
-
else if (!silent) {
|
|
280
|
-
flash(message || "Failed to load pending draft", "error");
|
|
281
|
-
}
|
|
282
|
-
renderChat();
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
export async function refreshAllDrafts() {
|
|
286
|
-
await Promise.all(DOC_TYPES.map((kind) => reloadPatch(kind, true)));
|
|
287
|
-
}
|
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
import { chatUI } from "./docsElements.js";
|
|
2
|
-
import { CHAT_EVENT_LIMIT, CHAT_EVENT_MAX, getActiveDoc, } from "./docsState.js";
|
|
3
|
-
function extractCommand(item, params) {
|
|
4
|
-
const command = item?.command ?? params?.command;
|
|
5
|
-
if (Array.isArray(command)) {
|
|
6
|
-
return command.map((part) => String(part)).join(" ").trim();
|
|
7
|
-
}
|
|
8
|
-
if (typeof command === "string")
|
|
9
|
-
return command.trim();
|
|
10
|
-
return "";
|
|
11
|
-
}
|
|
12
|
-
function extractFiles(payload) {
|
|
13
|
-
const files = [];
|
|
14
|
-
const addEntry = (entry) => {
|
|
15
|
-
if (typeof entry === "string" && entry.trim()) {
|
|
16
|
-
files.push(entry.trim());
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (entry && typeof entry === "object") {
|
|
20
|
-
const entryObj = entry;
|
|
21
|
-
const path = entryObj.path || entryObj.file || entryObj.name;
|
|
22
|
-
if (typeof path === "string" && path.trim()) {
|
|
23
|
-
files.push(path.trim());
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
if (!payload || typeof payload !== "object")
|
|
28
|
-
return files;
|
|
29
|
-
for (const key of ["files", "fileChanges", "paths"]) {
|
|
30
|
-
const value = payload[key];
|
|
31
|
-
if (Array.isArray(value)) {
|
|
32
|
-
value.forEach(addEntry);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
for (const key of ["path", "file", "name"]) {
|
|
36
|
-
addEntry(payload[key]);
|
|
37
|
-
}
|
|
38
|
-
return files;
|
|
39
|
-
}
|
|
40
|
-
function extractErrorMessage(params) {
|
|
41
|
-
if (!params || typeof params !== "object")
|
|
42
|
-
return "";
|
|
43
|
-
const err = params.error;
|
|
44
|
-
if (err && typeof err === "object") {
|
|
45
|
-
const errObj = err;
|
|
46
|
-
const message = typeof errObj.message === "string" ? errObj.message : "";
|
|
47
|
-
const details = typeof errObj.additionalDetails === "string"
|
|
48
|
-
? errObj.additionalDetails
|
|
49
|
-
: typeof errObj.details === "string"
|
|
50
|
-
? errObj.details
|
|
51
|
-
: "";
|
|
52
|
-
if (message && details && message !== details) {
|
|
53
|
-
return `${message} (${details})`;
|
|
54
|
-
}
|
|
55
|
-
return message || details;
|
|
56
|
-
}
|
|
57
|
-
if (typeof err === "string")
|
|
58
|
-
return err;
|
|
59
|
-
if (typeof params.message === "string")
|
|
60
|
-
return params.message;
|
|
61
|
-
return "";
|
|
62
|
-
}
|
|
63
|
-
export function extractOutputDelta(payload) {
|
|
64
|
-
const message = payload && typeof payload === "object"
|
|
65
|
-
? payload.message || payload
|
|
66
|
-
: payload;
|
|
67
|
-
if (!message || typeof message !== "object")
|
|
68
|
-
return "";
|
|
69
|
-
const method = String(message.method || "").toLowerCase();
|
|
70
|
-
if (!method.includes("outputdelta"))
|
|
71
|
-
return "";
|
|
72
|
-
const params = message.params || {};
|
|
73
|
-
if (typeof params.delta === "string")
|
|
74
|
-
return params.delta;
|
|
75
|
-
if (typeof params.text === "string")
|
|
76
|
-
return params.text;
|
|
77
|
-
if (typeof params.output === "string")
|
|
78
|
-
return params.output;
|
|
79
|
-
return "";
|
|
80
|
-
}
|
|
81
|
-
function addChatEvent(state, entry) {
|
|
82
|
-
state.events.push(entry);
|
|
83
|
-
if (state.events.length > CHAT_EVENT_MAX) {
|
|
84
|
-
state.events = state.events.slice(-CHAT_EVENT_MAX);
|
|
85
|
-
state.eventItemIndex = {};
|
|
86
|
-
state.events.forEach((evt, idx) => {
|
|
87
|
-
const chatEvent = evt;
|
|
88
|
-
if (chatEvent.itemId)
|
|
89
|
-
state.eventItemIndex[chatEvent.itemId] = idx;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export function applyAppServerEvent(state, payload) {
|
|
94
|
-
const message = payload && typeof payload === "object"
|
|
95
|
-
? payload.message || payload
|
|
96
|
-
: payload;
|
|
97
|
-
if (!message || typeof message !== "object")
|
|
98
|
-
return;
|
|
99
|
-
const messageObj = message;
|
|
100
|
-
const method = messageObj.method || "app-server";
|
|
101
|
-
const params = messageObj.params || {};
|
|
102
|
-
const item = params.item || {};
|
|
103
|
-
const itemId = params.itemId || item.id || item.itemId || null;
|
|
104
|
-
const receivedAt = payload && typeof payload === "object"
|
|
105
|
-
? payload.received_at ||
|
|
106
|
-
payload.receivedAt ||
|
|
107
|
-
Date.now()
|
|
108
|
-
: Date.now();
|
|
109
|
-
if (method === "item/reasoning/summaryTextDelta") {
|
|
110
|
-
const delta = params.delta || "";
|
|
111
|
-
if (!delta)
|
|
112
|
-
return;
|
|
113
|
-
const existingIndex = itemId && state.eventItemIndex[itemId] !== undefined
|
|
114
|
-
? state.eventItemIndex[itemId]
|
|
115
|
-
: null;
|
|
116
|
-
if (existingIndex !== null) {
|
|
117
|
-
const existing = state.events[existingIndex];
|
|
118
|
-
existing.summary = `${existing.summary || ""}${delta}`;
|
|
119
|
-
existing.time = receivedAt;
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const entry = {
|
|
123
|
-
id: payload?.id || `${Date.now()}`,
|
|
124
|
-
title: "Thinking",
|
|
125
|
-
summary: delta,
|
|
126
|
-
detail: "",
|
|
127
|
-
kind: "thinking",
|
|
128
|
-
time: receivedAt,
|
|
129
|
-
itemId,
|
|
130
|
-
method,
|
|
131
|
-
};
|
|
132
|
-
addChatEvent(state, entry);
|
|
133
|
-
if (itemId)
|
|
134
|
-
state.eventItemIndex[itemId] = state.events.length - 1;
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
if (method === "item/reasoning/summaryPartAdded") {
|
|
138
|
-
const existingIndex = itemId && state.eventItemIndex[itemId] !== undefined
|
|
139
|
-
? state.eventItemIndex[itemId]
|
|
140
|
-
: null;
|
|
141
|
-
if (existingIndex !== null) {
|
|
142
|
-
const existing = state.events[existingIndex];
|
|
143
|
-
existing.summary = `${existing.summary || ""}\n\n`;
|
|
144
|
-
existing.time = receivedAt;
|
|
145
|
-
}
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
let title = method;
|
|
149
|
-
let summary = "";
|
|
150
|
-
let detail = "";
|
|
151
|
-
let kind = "event";
|
|
152
|
-
if (method === "item/completed") {
|
|
153
|
-
const itemType = item.type;
|
|
154
|
-
if (itemType === "commandExecution") {
|
|
155
|
-
title = "Command";
|
|
156
|
-
summary = extractCommand(item, params);
|
|
157
|
-
kind = "command";
|
|
158
|
-
if (item.exitCode !== undefined && item.exitCode !== null) {
|
|
159
|
-
detail = `exit ${item.exitCode}`;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
else if (itemType === "fileChange") {
|
|
163
|
-
title = "File change";
|
|
164
|
-
const files = extractFiles(item);
|
|
165
|
-
summary = files.join(", ") || "Updated files";
|
|
166
|
-
kind = "file";
|
|
167
|
-
}
|
|
168
|
-
else if (itemType === "tool") {
|
|
169
|
-
title = "Tool";
|
|
170
|
-
summary = item.name || item.tool || item.id || "Tool call";
|
|
171
|
-
kind = "command";
|
|
172
|
-
}
|
|
173
|
-
else if (itemType === "agentMessage") {
|
|
174
|
-
title = "Agent";
|
|
175
|
-
summary = item.text || "Agent message";
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
title = itemType ? `Item ${itemType}` : "Item completed";
|
|
179
|
-
summary = item.text || item.message || "";
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else if (method === "item/commandExecution/requestApproval") {
|
|
183
|
-
title = "Command approval";
|
|
184
|
-
summary = extractCommand(item, params) || "Approval requested";
|
|
185
|
-
kind = "command";
|
|
186
|
-
}
|
|
187
|
-
else if (method === "item/fileChange/requestApproval") {
|
|
188
|
-
title = "File approval";
|
|
189
|
-
const files = extractFiles(params);
|
|
190
|
-
summary = files.join(", ") || "Approval requested";
|
|
191
|
-
kind = "file";
|
|
192
|
-
}
|
|
193
|
-
else if (method === "turn/completed") {
|
|
194
|
-
title = "Turn completed";
|
|
195
|
-
summary = params.status || "completed";
|
|
196
|
-
kind = "status";
|
|
197
|
-
}
|
|
198
|
-
else if (method === "error") {
|
|
199
|
-
title = "Error";
|
|
200
|
-
summary = extractErrorMessage(params) || "App-server error";
|
|
201
|
-
kind = "error";
|
|
202
|
-
}
|
|
203
|
-
else if (method.includes("outputDelta")) {
|
|
204
|
-
title = "Output";
|
|
205
|
-
summary = params.delta || params.text || "";
|
|
206
|
-
}
|
|
207
|
-
else if (params.delta) {
|
|
208
|
-
title = "Delta";
|
|
209
|
-
summary = params.delta;
|
|
210
|
-
}
|
|
211
|
-
const entry = {
|
|
212
|
-
id: payload?.id || `${Date.now()}`,
|
|
213
|
-
title,
|
|
214
|
-
summary: summary || "(no details)",
|
|
215
|
-
detail,
|
|
216
|
-
kind,
|
|
217
|
-
time: receivedAt,
|
|
218
|
-
itemId,
|
|
219
|
-
method,
|
|
220
|
-
};
|
|
221
|
-
addChatEvent(state, entry);
|
|
222
|
-
if (itemId)
|
|
223
|
-
state.eventItemIndex[itemId] = state.events.length - 1;
|
|
224
|
-
}
|
|
225
|
-
export function renderChatEvents(state) {
|
|
226
|
-
if (getActiveDoc() === "snapshot")
|
|
227
|
-
return;
|
|
228
|
-
if (!chatUI.eventsMain || !chatUI.eventsList || !chatUI.eventsCount)
|
|
229
|
-
return;
|
|
230
|
-
const hasEvents = state.events.length > 0;
|
|
231
|
-
const isRunning = state.status === "running";
|
|
232
|
-
const showEvents = hasEvents || isRunning;
|
|
233
|
-
chatUI.eventsMain.classList.toggle("hidden", !showEvents);
|
|
234
|
-
chatUI.eventsCount.textContent = String(state.events.length);
|
|
235
|
-
if (!showEvents)
|
|
236
|
-
return;
|
|
237
|
-
const limit = CHAT_EVENT_LIMIT;
|
|
238
|
-
const expanded = !!state.eventsExpanded;
|
|
239
|
-
const showCount = expanded
|
|
240
|
-
? state.events.length
|
|
241
|
-
: Math.min(state.events.length, limit);
|
|
242
|
-
const visible = state.events.slice(-showCount);
|
|
243
|
-
if (chatUI.eventsToggle) {
|
|
244
|
-
const hiddenCount = Math.max(0, state.events.length - showCount);
|
|
245
|
-
chatUI.eventsToggle.classList.toggle("hidden", hiddenCount === 0);
|
|
246
|
-
chatUI.eventsToggle.textContent = expanded
|
|
247
|
-
? "Show recent"
|
|
248
|
-
: `Show more (${hiddenCount})`;
|
|
249
|
-
}
|
|
250
|
-
chatUI.eventsList.innerHTML = "";
|
|
251
|
-
if (state.eventError) {
|
|
252
|
-
const error = document.createElement("div");
|
|
253
|
-
error.className = "doc-chat-event error";
|
|
254
|
-
const title = document.createElement("div");
|
|
255
|
-
title.className = "doc-chat-event-title";
|
|
256
|
-
title.textContent = "Event stream error";
|
|
257
|
-
const summary = document.createElement("div");
|
|
258
|
-
summary.className = "doc-chat-event-summary";
|
|
259
|
-
summary.textContent = state.eventError;
|
|
260
|
-
error.appendChild(title);
|
|
261
|
-
error.appendChild(summary);
|
|
262
|
-
chatUI.eventsList.appendChild(error);
|
|
263
|
-
}
|
|
264
|
-
if (!hasEvents) {
|
|
265
|
-
const empty = document.createElement("div");
|
|
266
|
-
empty.className = "doc-chat-events-empty";
|
|
267
|
-
empty.textContent = isRunning ? "Waiting for updates..." : "No updates yet.";
|
|
268
|
-
chatUI.eventsList.appendChild(empty);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
visible.forEach((entry) => {
|
|
272
|
-
const chatEvent = entry;
|
|
273
|
-
const wrapper = document.createElement("div");
|
|
274
|
-
wrapper.className = `doc-chat-event ${chatEvent.kind || ""}`.trim();
|
|
275
|
-
const title = document.createElement("div");
|
|
276
|
-
title.className = "doc-chat-event-title";
|
|
277
|
-
title.textContent = chatEvent.title || chatEvent.method || "Update";
|
|
278
|
-
const summary = document.createElement("div");
|
|
279
|
-
summary.className = "doc-chat-event-summary";
|
|
280
|
-
summary.textContent = chatEvent.summary || "(no details)";
|
|
281
|
-
wrapper.appendChild(title);
|
|
282
|
-
wrapper.appendChild(summary);
|
|
283
|
-
if (chatEvent.detail) {
|
|
284
|
-
const detail = document.createElement("div");
|
|
285
|
-
detail.className = "doc-chat-event-detail";
|
|
286
|
-
detail.textContent = chatEvent.detail;
|
|
287
|
-
wrapper.appendChild(detail);
|
|
288
|
-
}
|
|
289
|
-
const meta = document.createElement("div");
|
|
290
|
-
meta.className = "doc-chat-event-meta";
|
|
291
|
-
meta.textContent = chatEvent.time
|
|
292
|
-
? new Date(chatEvent.time).toLocaleTimeString([], {
|
|
293
|
-
hour: "2-digit",
|
|
294
|
-
minute: "2-digit",
|
|
295
|
-
})
|
|
296
|
-
: "";
|
|
297
|
-
wrapper.appendChild(meta);
|
|
298
|
-
chatUI.eventsList.appendChild(wrapper);
|
|
299
|
-
});
|
|
300
|
-
}
|