@vibes.diy/api-svc 14.3.16 → 14.3.18
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/intern/agent-dispatcher.d.ts +1 -0
- package/intern/agent-dispatcher.js +2 -0
- package/intern/agent-dispatcher.js.map +1 -1
- package/intern/agent-session.d.ts +28 -1
- package/intern/agent-session.js +21 -1
- package/intern/agent-session.js.map +1 -1
- package/intern/agent-wake.d.ts +1 -0
- package/intern/agent-wake.js +1 -0
- package/intern/agent-wake.js.map +1 -1
- package/intern/builder-model.d.ts +4 -1
- package/intern/builder-model.js +12 -6
- package/intern/builder-model.js.map +1 -1
- package/intern/eval-handles.d.ts +1 -1
- package/intern/eval-handles.js +3 -3
- package/intern/eval-handles.js.map +1 -1
- package/intern/get-model-defaults.d.ts +1 -0
- package/intern/get-model-defaults.js +13 -0
- package/intern/get-model-defaults.js.map +1 -1
- package/intern/in-flight-turns.d.ts +1 -1
- package/intern/in-flight-turns.js +1 -1
- package/intern/in-flight-turns.js.map +1 -1
- package/intern/mint-fire-core.d.ts +2 -0
- package/intern/mint-fire-core.js +2 -0
- package/intern/mint-fire-core.js.map +1 -1
- package/intern/process-access-bindings.js +1 -1
- package/intern/process-access-bindings.js.map +1 -1
- package/intern/prompt-usage.js +20 -0
- package/intern/prompt-usage.js.map +1 -1
- package/intern/provider-sse.d.ts +1 -0
- package/intern/provider-sse.js +83 -2
- package/intern/provider-sse.js.map +1 -1
- package/intern/subagent-model.d.ts +20 -0
- package/intern/subagent-model.js +30 -0
- package/intern/subagent-model.js.map +1 -0
- package/intern/usage-rounds.d.ts +7 -0
- package/intern/usage-rounds.js +20 -0
- package/intern/usage-rounds.js.map +1 -0
- package/models.json +63 -1
- package/package.json +12 -12
- package/public/agent-turn-action.d.ts +30 -0
- package/public/agent-turn-action.js +374 -0
- package/public/agent-turn-action.js.map +1 -0
- package/public/agent-turn-assembly.d.ts +34 -0
- package/public/agent-turn-assembly.js +199 -0
- package/public/agent-turn-assembly.js.map +1 -0
- package/public/append-block-event.d.ts +31 -0
- package/public/append-block-event.js +121 -0
- package/public/append-block-event.js.map +1 -0
- package/public/auto-publish-on-persist.d.ts +10 -0
- package/public/auto-publish-on-persist.js +40 -0
- package/public/auto-publish-on-persist.js.map +1 -0
- package/public/codegen-turn-route.d.ts +40 -0
- package/public/codegen-turn-route.js +177 -0
- package/public/codegen-turn-route.js.map +1 -0
- package/public/draft-runtime.js +12 -2
- package/public/draft-runtime.js.map +1 -1
- package/public/guest-build-generation.js +2 -1
- package/public/guest-build-generation.js.map +1 -1
- package/public/handle-prompt-context.d.ts +41 -0
- package/public/handle-prompt-context.js +397 -0
- package/public/handle-prompt-context.js.map +1 -0
- package/public/handler-llm-request.d.ts +48 -0
- package/public/handler-llm-request.js +363 -0
- package/public/handler-llm-request.js.map +1 -0
- package/public/image-gen.js +1 -1
- package/public/image-gen.js.map +1 -1
- package/public/llm-dispatch-fallback.d.ts +46 -0
- package/public/llm-dispatch-fallback.js +293 -0
- package/public/llm-dispatch-fallback.js.map +1 -0
- package/public/llm-dispatch.d.ts +5 -180
- package/public/llm-dispatch.js +5 -1158
- package/public/llm-dispatch.js.map +1 -1
- package/public/open-chat.d.ts +5 -0
- package/public/open-chat.js +70 -7
- package/public/open-chat.js.map +1 -1
- package/public/prompt-chat-section.js +119 -1167
- package/public/prompt-chat-section.js.map +1 -1
- package/public/prompt-section-actions.d.ts +41 -0
- package/public/prompt-section-actions.js +161 -0
- package/public/prompt-section-actions.js.map +1 -0
- package/public/prompt-turn-envelope.d.ts +26 -0
- package/public/prompt-turn-envelope.js +120 -0
- package/public/prompt-turn-envelope.js.map +1 -0
- package/public/prompt-turn-settled.d.ts +32 -0
- package/public/prompt-turn-settled.js +157 -0
- package/public/prompt-turn-settled.js.map +1 -0
- package/public/prompt-turn-terminal.d.ts +22 -0
- package/public/prompt-turn-terminal.js +135 -0
- package/public/prompt-turn-terminal.js.map +1 -0
- package/public/prompt-turn-types.d.ts +37 -0
- package/public/prompt-turn-types.js +2 -0
- package/public/prompt-turn-types.js.map +1 -0
- package/public/social-store.js.map +1 -1
- package/public/stream-assembly.js +33 -51
- package/public/stream-assembly.js.map +1 -1
|
@@ -2,130 +2,32 @@ import { checkBuildAuth } from "../check-build-auth.js";
|
|
|
2
2
|
import { handleGuestPrompt } from "./guest-build-generation.js";
|
|
3
3
|
import { Result, Option, EventoResult, exception2Result } from "@adviser/cement";
|
|
4
4
|
import { scopey } from "@adviser/scopey";
|
|
5
|
-
import { isReqCreationPromptChatSection,
|
|
5
|
+
import { isReqCreationPromptChatSection, reqPromptChatSection, isBuildNotifyMode, isSourceChangingMode, } from "@vibes.diy/api-types";
|
|
6
6
|
import { type } from "arktype";
|
|
7
|
-
import { captureAccessVerdicts, captureCodegenTurnSettled } from "../analytics.js";
|
|
8
|
-
import { releaseAccessVerdicts } from "../intern/access-verdict-docs.js";
|
|
9
|
-
import { renderAccessVerdictLine } from "../intern/access-verdicts.js";
|
|
10
|
-
import { dispatchLookLint, loadTurnFilesByFsId, lookLintPlanned } from "../intern/look-lint.js";
|
|
11
|
-
import { postMakerFact } from "../intern/post-maker-fact.js";
|
|
12
|
-
import { postCapiBuildEvent } from "../intern/capi-build-event.js";
|
|
13
|
-
import { classifyTurnReach, projectTurnReach } from "../intern/turn-reach.js";
|
|
14
|
-
import { loadNotificationPrefs } from "../intern/notification-prefs.js";
|
|
15
|
-
import { resolveBuildOrdinal } from "../intern/build-version-ordinal.js";
|
|
16
7
|
import { checkAuth } from "../check-auth.js";
|
|
17
8
|
import { unwrapMsgBase, wrapMsgBase } from "../unwrap-msg-base.js";
|
|
18
9
|
import { assertChatShardIdentity } from "../shard-gate.js";
|
|
19
|
-
import { and, eq, ne } from "drizzle-orm/sql/expressions";
|
|
20
|
-
import { isChatMessage, isUserChatMessage } from "@vibes.diy/call-ai-v2";
|
|
21
|
-
import { getModelDefaults } from "../intern/get-model-defaults.js";
|
|
22
|
-
import { resolveSlotConfig } from "../intern/slot-assembler.js";
|
|
23
|
-
import { dryRunHandleIsForeign } from "../intern/ensure-chat-id.js";
|
|
24
|
-
import { resolveDeveloperAccess } from "./developer-grants.js";
|
|
25
10
|
import { createPromptAssetFetch, promptsPkgBaseUrl } from "../intern/prompt-asset-fetch.js";
|
|
26
11
|
import { resolveCodeBlocksToFileSystem, resolveCodeBlockChangedPaths, createStreamingResolver, createBlockAccumulator, logApplyError, } from "../intern/prompt-streaming.js";
|
|
27
12
|
import { reconstructConversationMessages, assemblePromptPayload, persistCodegenThemeMarker, ELIDED_CODE_NOTICE, } from "../intern/prompt-assembly.js";
|
|
28
13
|
import { bumpAppRecency } from "../intern/bump-app-recency.js";
|
|
29
14
|
import { waitChatPersistIdle } from "../intern/chat-persist-gate.js";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import { runEditVibeTool } from "../intern/agent-build-tools.js";
|
|
35
|
-
import { claimFirstTurnMint, claimMintJob, getMintJob } from "../intern/mint-job-store.js";
|
|
36
|
-
import { codegenTurnLane, mintRowSaysFirstTurnIsAgents, routeAgentTurn } from "../intern/agent-router.js";
|
|
37
|
-
import { assembleAgentPayload } from "../intern/agent-assembly.js";
|
|
38
|
-
import { claimAgentAppContext, composeAgentRequest, isAppContextMessage, markJournalCacheTail, } from "../intern/agent-request-frame.js";
|
|
39
|
-
import { createAgentBelt } from "../intern/agent-belt.js";
|
|
40
|
-
import { createAgentTurnStream, agentTotalBudgetMs } from "../intern/agent-turn.js";
|
|
41
|
-
import { createAgentBuildDispatcher } from "../intern/agent-dispatcher.js";
|
|
42
|
-
import { decideAgentWake, fireAgentWakeTurn, readAgentWakeBudget, renderAgentWakeNote } from "../intern/agent-wake.js";
|
|
43
|
-
import { settleTurnTerminal } from "../intern/turn-terminal.js";
|
|
44
|
-
import { resolveAgentActor, resolveChatApp } from "../intern/agent-actor.js";
|
|
45
|
-
import { langForFilename } from "../intern/ensure-push-seeded-chat.js";
|
|
46
|
-
import { promptDispatchContext } from "../intern/prompt-dispatch-context.js";
|
|
47
|
-
import { dispatchLlmRequestWithFallback } from "./llm-dispatch.js";
|
|
48
|
-
import { scheduleUrlResearch } from "../intern/url-research-queue.js";
|
|
49
|
-
import { createProviderSseStream } from "../intern/provider-sse.js";
|
|
50
|
-
import { activateWorkUrls, loadWorkFetchUrlContext, loadWorkVfs, withoutServerTools } from "../intern/work-tools.js";
|
|
51
|
-
import { closeTurn, extendOpenTurnDeadline, OPEN_TURN_AWAIT_BUILD_EXTENSION_MS, shouldCloseTurnRecord, } from "../intern/open-turn-store.js";
|
|
52
|
-
import { maxPersistedBlockSeq } from "../intern/persisted-block-seq.js";
|
|
53
|
-
import { appendBlockEvent, currentUserMessageText, handlerLlmRequest } from "./llm-dispatch.js";
|
|
54
|
-
import { createAgentEvidenceWriter, nextAgentSessionMessages } from "../intern/agent-evidence.js";
|
|
55
|
-
import { msSinceOrigin, observeEvidenceLine } from "../intern/turn-latency.js";
|
|
56
|
-
import { handleLlmResponse } from "./stream-assembly.js";
|
|
57
|
-
import { handleProdiaImageRequest } from "./image-gen.js";
|
|
15
|
+
import { acquireTurnBuildLock, releaseTurnBuildLock } from "../intern/codegen-build-lock.js";
|
|
16
|
+
import { agentSessionPinsFor } from "../intern/agent-session.js";
|
|
17
|
+
import { decideAgentWake } from "../intern/agent-wake.js";
|
|
18
|
+
import { appendBlockEvent } from "./llm-dispatch.js";
|
|
58
19
|
import { handleFSPrompt } from "./fs-prompt.js";
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
20
|
+
import { admitTurnOptions, getResChatFromMode, readTurnEnvelope } from "./prompt-turn-envelope.js";
|
|
21
|
+
import { assembleCodegenTurn, routeCodegenTurn } from "./codegen-turn-route.js";
|
|
22
|
+
import { assembleAgentTurn } from "./agent-turn-assembly.js";
|
|
23
|
+
import { resolveImageModel, selectPromptSectionAction } from "./prompt-section-actions.js";
|
|
24
|
+
import { finalizePromptTurn, recordTurnError } from "./prompt-turn-terminal.js";
|
|
25
|
+
import { settlePromptTurn } from "./prompt-turn-settled.js";
|
|
66
26
|
export { createPromptAssetFetch, promptsPkgBaseUrl };
|
|
67
27
|
export { resolveCodeBlocksToFileSystem, resolveCodeBlockChangedPaths, createStreamingResolver, createBlockAccumulator, logApplyError, };
|
|
68
28
|
export { reconstructConversationMessages, assemblePromptPayload, persistCodegenThemeMarker, ELIDED_CODE_NOTICE };
|
|
69
29
|
export { handlePromptContext } from "./llm-dispatch.js";
|
|
70
30
|
export { handleFSPrompt };
|
|
71
|
-
async function getResChatFromMode(vctx, req, orig) {
|
|
72
|
-
if (isReqCreationPromptChatSection(orig) &&
|
|
73
|
-
orig.dryRun === true &&
|
|
74
|
-
orig.ownerHandle !== undefined &&
|
|
75
|
-
orig.appSlug !== undefined) {
|
|
76
|
-
const anyRow = await vctx.sql.db
|
|
77
|
-
.select({ chatId: vctx.sql.tables.chatContexts.chatId })
|
|
78
|
-
.from(vctx.sql.tables.chatContexts)
|
|
79
|
-
.where(eq(vctx.sql.tables.chatContexts.chatId, req.chatId))
|
|
80
|
-
.limit(1)
|
|
81
|
-
.then((r) => r[0]);
|
|
82
|
-
if (!anyRow) {
|
|
83
|
-
const userId = req._auth.verifiedAuth.claims.userId;
|
|
84
|
-
const rForeign = await dryRunHandleIsForeign(vctx, orig.ownerHandle, userId);
|
|
85
|
-
if (rForeign.isErr())
|
|
86
|
-
return Result.Err(rForeign);
|
|
87
|
-
if (rForeign.Ok()) {
|
|
88
|
-
const dev = orig.appSlug !== undefined
|
|
89
|
-
? await resolveDeveloperAccess(vctx, { ownerHandle: orig.ownerHandle, appSlug: orig.appSlug, callerUserId: userId })
|
|
90
|
-
: null;
|
|
91
|
-
if (dev === null) {
|
|
92
|
-
return Result.Err(`ownerHandle "${orig.ownerHandle}" is owned by another user`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return Result.Ok({ appSlug: orig.appSlug, ownerHandle: orig.ownerHandle, mode: orig.mode });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
let iResChat;
|
|
99
|
-
if (isReqPromptApplicationChatSection(orig) || isReqPromptImageChatSection(orig)) {
|
|
100
|
-
iResChat = await vctx.sql.db
|
|
101
|
-
.select()
|
|
102
|
-
.from(vctx.sql.tables.applicationChats)
|
|
103
|
-
.where(and(eq(vctx.sql.tables.applicationChats.userId, req._auth.verifiedAuth.claims.userId), eq(vctx.sql.tables.applicationChats.chatId, req.chatId)))
|
|
104
|
-
.limit(1)
|
|
105
|
-
.then((r) => r[0]);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
iResChat = await vctx.sql.db
|
|
109
|
-
.select()
|
|
110
|
-
.from(vctx.sql.tables.chatContexts)
|
|
111
|
-
.where(and(eq(vctx.sql.tables.chatContexts.userId, req._auth.verifiedAuth.claims.userId), eq(vctx.sql.tables.chatContexts.chatId, req.chatId)))
|
|
112
|
-
.limit(1)
|
|
113
|
-
.then((r) => r[0]);
|
|
114
|
-
}
|
|
115
|
-
if (!iResChat) {
|
|
116
|
-
if (isReqCreationPromptChatSection(orig)) {
|
|
117
|
-
return Result.Err(`Creation Chat ID ${req.chatId} not found`);
|
|
118
|
-
}
|
|
119
|
-
else if (isReqPromptApplicationChatSection(orig)) {
|
|
120
|
-
return Result.Err(`Application Chat ID ${req.chatId} not found`);
|
|
121
|
-
}
|
|
122
|
-
else if (isReqPromptImageChatSection(orig)) {
|
|
123
|
-
return Result.Err(`Image Chat ID ${req.chatId} not found`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
const resChat = { ...iResChat, mode: orig.mode };
|
|
127
|
-
return Result.Ok(resChat);
|
|
128
|
-
}
|
|
129
31
|
const accountPromptChatSection = {
|
|
130
32
|
hash: "prompt-chat-section-handler",
|
|
131
33
|
validate: unwrapMsgBase(async (msg) => {
|
|
@@ -143,829 +45,117 @@ const accountPromptChatSection = {
|
|
|
143
45
|
const orig = ctx.enRequest.payload;
|
|
144
46
|
const vctx = ctx.ctx.getOrThrow("vibesApiCtx");
|
|
145
47
|
const turnStartedAt = Date.now();
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
Number.isFinite(submittedAtRaw) &&
|
|
149
|
-
submittedAtRaw <= turnStartedAt &&
|
|
150
|
-
turnStartedAt - submittedAtRaw <= 3_600_000
|
|
151
|
-
? submittedAtRaw
|
|
152
|
-
: undefined;
|
|
153
|
-
const directBuildRequested = orig.directBuild === true;
|
|
154
|
-
const agentDispatchedBuild = orig.agentDispatched === true;
|
|
155
|
-
const agentWakeTurn = orig.agentWake === true;
|
|
156
|
-
const agentWakeBudget = readAgentWakeBudget(orig.agentWakeBudget);
|
|
157
|
-
const agentWakeNoteRaw = orig.agentWakeNote;
|
|
158
|
-
const agentWakeNote = agentWakeTurn === true && typeof agentWakeNoteRaw === "string" ? agentWakeNoteRaw : undefined;
|
|
159
|
-
const firstTurnAgent = orig.firstTurnAgent === true;
|
|
160
|
-
const nonInteractive = orig.nonInteractive === true;
|
|
161
|
-
let agentFetchUrlContext;
|
|
48
|
+
const envelope = readTurnEnvelope(orig, turnStartedAt);
|
|
49
|
+
const { agentDispatchedBuild, agentWakeBudget } = envelope;
|
|
162
50
|
await waitChatPersistIdle(vctx.connections, req.chatId, { logger: vctx.logger });
|
|
163
51
|
const rResChat = await getResChatFromMode(vctx, req, orig);
|
|
164
52
|
if (rResChat.isErr()) {
|
|
165
53
|
return Result.Err(rResChat);
|
|
166
54
|
}
|
|
167
55
|
const resChat = rResChat.Ok();
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
170
|
-
return Result.Err(
|
|
171
|
-
const instructionVariant =
|
|
172
|
-
const rBuilderModel = await admitBuilderModel(vctx, orig.builderModel, resChat.ownerHandle);
|
|
173
|
-
if (rBuilderModel.isErr())
|
|
174
|
-
return Result.Err(rBuilderModel);
|
|
175
|
-
const builderModel = rBuilderModel.Ok();
|
|
176
|
-
const dispatchCarry = dispatchCarryFor({
|
|
177
|
-
apiKey: orig.apiKey,
|
|
178
|
-
model: orig.prompt?.model,
|
|
179
|
-
...(builderModel === undefined ? {} : { builderModel }),
|
|
180
|
-
focusPath: orig.focusPath,
|
|
181
|
-
...(instructionVariant === undefined ? {} : { instructionVariant }),
|
|
182
|
-
});
|
|
183
|
-
const wakeAgentModel = evalWakeAgentModel(resChat.ownerHandle, orig.agentModel);
|
|
56
|
+
const rAdmitted = await admitTurnOptions(vctx, orig, resChat);
|
|
57
|
+
if (rAdmitted.isErr())
|
|
58
|
+
return Result.Err(rAdmitted);
|
|
59
|
+
const { instructionVariant, builderModel, subagentModel, dispatchCarry, wakeAgentModel } = rAdmitted.Ok();
|
|
184
60
|
const oShardErr = assertChatShardIdentity(ctx, resChat.ownerHandle, resChat.appSlug);
|
|
185
61
|
if (oShardErr.IsSome()) {
|
|
186
62
|
await ctx.send.send(ctx, oShardErr.unwrap());
|
|
187
63
|
return Result.Ok(EventoResult.Continue);
|
|
188
64
|
}
|
|
189
65
|
let preAssembled;
|
|
190
|
-
let turnToolsOffered = [];
|
|
191
66
|
let agentAssembled;
|
|
192
67
|
let agentSession;
|
|
193
68
|
let agentEvidence;
|
|
69
|
+
let agentFetchUrlContext;
|
|
194
70
|
const turnLatency = {};
|
|
195
71
|
let agentFirstTurnMint = false;
|
|
196
|
-
let
|
|
197
|
-
|
|
72
|
+
let subagentCall;
|
|
73
|
+
const facts = { toolsOffered: [], errored: false };
|
|
198
74
|
if (isReqCreationPromptChatSection(orig)) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
directBuildRequested,
|
|
225
|
-
agentWake: agentWakeTurn,
|
|
226
|
-
hasPriorTurn,
|
|
227
|
-
firstTurnAgent,
|
|
228
|
-
};
|
|
229
|
-
let agentRoute = routeAgentTurn(routeInput);
|
|
230
|
-
const mintRowWorthReading = (agentRoute.route === "codegen" && agentRoute.skip === "first-turn") ||
|
|
231
|
-
(agentRoute.route === "agent" && hasPriorTurn === true);
|
|
232
|
-
if (mintRowWorthReading) {
|
|
233
|
-
const rJob = await getMintJob(vctx, req.chatId);
|
|
234
|
-
if (rJob.isErr()) {
|
|
235
|
-
vctx.logger
|
|
236
|
-
.Warn()
|
|
237
|
-
.Err(rJob)
|
|
238
|
-
.Str("chatId", req.chatId)
|
|
239
|
-
.Msg("first-turn mint-job read failed; keeping the codegen route");
|
|
240
|
-
}
|
|
241
|
-
else if (mintRowSaysFirstTurnIsAgents(rJob.Ok()?.status)) {
|
|
242
|
-
mintUnclaimed = true;
|
|
243
|
-
if (agentRoute.route === "codegen") {
|
|
244
|
-
lightMintedChat = true;
|
|
245
|
-
agentRoute = routeAgentTurn({ ...routeInput, firstTurnAgent: true });
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
agentFirstTurnMint =
|
|
250
|
-
agentRoute.route === "agent" &&
|
|
251
|
-
(firstTurnAgent || lightMintedChat || mintUnclaimed) &&
|
|
252
|
-
(hasPriorTurn === false || mintUnclaimed);
|
|
253
|
-
if (agentRoute.route === "agent") {
|
|
254
|
-
agentFetchUrlContext = await loadWorkFetchUrlContext(vctx, {
|
|
255
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
256
|
-
chatId: req.chatId,
|
|
257
|
-
ownerHandle: resChat.ownerHandle,
|
|
258
|
-
appSlug: resChat.appSlug,
|
|
259
|
-
activatedUrls: activateWorkUrls(currentUserMessageText(orig.prompt.messages.filter(isChatMessage))),
|
|
260
|
-
});
|
|
261
|
-
const buildInFlight = peekBuildLockEntry(vctx.connections, req.chatId);
|
|
262
|
-
const rSeenHead = await readAgentSession(vctx.sql, req.chatId);
|
|
263
|
-
if (rSeenHead.isErr())
|
|
264
|
-
vctx.logger.Warn().Err(rSeenHead).Str("chatId", req.chatId).Msg("agent-session-head-read-failed");
|
|
265
|
-
const lastSeenHeadFsId = rSeenHead.isOk() ? rSeenHead.Ok().snapshot?.headFsId : undefined;
|
|
266
|
-
const rAgent = await assembleAgentPayload(vctx, {
|
|
267
|
-
chatId: req.chatId,
|
|
268
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
269
|
-
model: orig.prompt.model ?? rDefaults.Ok().agent.model.id,
|
|
270
|
-
ownerHandle: resChat.ownerHandle,
|
|
271
|
-
appSlug: resChat.appSlug,
|
|
272
|
-
newUserMessages: orig.prompt.messages.filter(isChatMessage),
|
|
273
|
-
...(agentWakeNote === undefined ? {} : { wakeNote: agentWakeNote }),
|
|
274
|
-
...(buildInFlight === undefined ? {} : { buildInFlight: { promptId: buildInFlight.promptId } }),
|
|
275
|
-
...(agentFirstTurnMint ? { noAppYet: true } : {}),
|
|
276
|
-
...(nonInteractive ? { nonInteractive: true } : {}),
|
|
277
|
-
...(lastSeenHeadFsId === undefined ? {} : { lastSeenHeadFsId }),
|
|
278
|
-
...(instructionVariant === undefined ? {} : { instructionVariant }),
|
|
75
|
+
const rRoute = await routeCodegenTurn(vctx, {
|
|
76
|
+
req,
|
|
77
|
+
orig,
|
|
78
|
+
resChat,
|
|
79
|
+
envelope,
|
|
80
|
+
...(subagentModel === undefined ? {} : { subagentModel }),
|
|
81
|
+
});
|
|
82
|
+
if (rRoute.isErr())
|
|
83
|
+
return Result.Err(rRoute);
|
|
84
|
+
const route = rRoute.Ok();
|
|
85
|
+
agentFirstTurnMint = route.agentFirstTurnMint;
|
|
86
|
+
subagentCall = route.subagentCall;
|
|
87
|
+
if (route.agentRoute.route === "agent") {
|
|
88
|
+
const rAgent = await assembleAgentTurn({
|
|
89
|
+
ctx,
|
|
90
|
+
vctx,
|
|
91
|
+
req,
|
|
92
|
+
orig,
|
|
93
|
+
resChat,
|
|
94
|
+
defaults: route.defaults,
|
|
95
|
+
envelope,
|
|
96
|
+
agentFirstTurnMint,
|
|
97
|
+
instructionVariant,
|
|
98
|
+
turnLatency,
|
|
99
|
+
pins: agentSessionPinsFor(dispatchCarry),
|
|
279
100
|
});
|
|
280
101
|
if (rAgent.isErr())
|
|
281
102
|
return Result.Err(rAgent);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const newMessageCount = orig.prompt.messages.filter(isChatMessage).length;
|
|
285
|
-
const incoming = newMessageCount === 0 ? [] : rAgent.Ok().messages.slice(-newMessageCount).filter(isUserChatMessage);
|
|
286
|
-
const delivered = incoming.length === 0 && agentWakeTurn
|
|
287
|
-
? [
|
|
288
|
-
{
|
|
289
|
-
role: "user",
|
|
290
|
-
content: [
|
|
291
|
-
{
|
|
292
|
-
type: "text",
|
|
293
|
-
text: agentWakeNote ??
|
|
294
|
-
"[session resumed] Continue from your persisted context and pending results. Inspect outcomes before retrying interrupted tools.",
|
|
295
|
-
},
|
|
296
|
-
],
|
|
297
|
-
},
|
|
298
|
-
]
|
|
299
|
-
: incoming;
|
|
300
|
-
const acquired = await deliverAgentSession(vctx, {
|
|
301
|
-
chatId: req.chatId,
|
|
302
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
303
|
-
ownerHandle: resChat.ownerHandle,
|
|
304
|
-
appSlug: resChat.appSlug,
|
|
305
|
-
}, { id: ctx.validated.tid, messages: delivered }, rAgent.Ok().messages.filter((message) => message.role === "system" || isAppContextMessage(message)));
|
|
306
|
-
if (acquired.isErr())
|
|
307
|
-
return Result.Err(acquired.Err());
|
|
308
|
-
const { live, created } = acquired.Ok();
|
|
309
|
-
const composedHead = rAgent.Ok().headFsId;
|
|
310
|
-
if (composedHead !== undefined) {
|
|
311
|
-
const noted = await live.session.observeHead(composedHead);
|
|
312
|
-
if (noted.isErr())
|
|
313
|
-
vctx.logger.Warn().Err(noted).Str("chatId", req.chatId).Msg("agent-session-head-note-failed");
|
|
314
|
-
}
|
|
315
|
-
if (created === false) {
|
|
316
|
-
const receiptId = vctx.sthis.nextId(12).str;
|
|
317
|
-
const receiptEvidence = createAgentEvidenceWriter({
|
|
318
|
-
chatId: req.chatId,
|
|
319
|
-
promptId: receiptId,
|
|
320
|
-
sessionId: live.promptId,
|
|
321
|
-
append: (evt, blockSeq) => appendBlockEvent({ ctx, vctx, req, promptId: receiptId, blockSeq, evt }),
|
|
322
|
-
});
|
|
323
|
-
const linked = await receiptEvidence({ kind: "active" });
|
|
324
|
-
if (linked.isErr())
|
|
325
|
-
return Result.Err(linked.Err());
|
|
326
|
-
await ctx.send.send(ctx, wrapMsgBase(ctx.validated, {
|
|
327
|
-
payload: {
|
|
328
|
-
type: "vibes.diy.res-prompt-chat-section",
|
|
329
|
-
chatId: req.chatId,
|
|
330
|
-
ownerHandle: resChat.ownerHandle,
|
|
331
|
-
appSlug: resChat.appSlug,
|
|
332
|
-
promptId: receiptId,
|
|
333
|
-
outerTid: req.outerTid,
|
|
334
|
-
mode: req.mode,
|
|
335
|
-
},
|
|
336
|
-
tid: ctx.validated.tid,
|
|
337
|
-
src: "agentSession",
|
|
338
|
-
}));
|
|
339
|
-
const echo = await appendBlockEvent({
|
|
340
|
-
ctx,
|
|
341
|
-
vctx,
|
|
342
|
-
req,
|
|
343
|
-
promptId: receiptId,
|
|
344
|
-
blockSeq: 0,
|
|
345
|
-
evt: {
|
|
346
|
-
type: "prompt.req",
|
|
347
|
-
...(orig.mode === "codegen" && orig.source === "suggestion" ? { source: "suggestion" } : {}),
|
|
348
|
-
streamId: receiptId,
|
|
349
|
-
chatId: req.chatId,
|
|
350
|
-
seq: 0,
|
|
351
|
-
request: { messages: rawIncoming },
|
|
352
|
-
timestamp: new Date(),
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
if (echo.isErr())
|
|
356
|
-
return Result.Err(echo.Err());
|
|
357
|
-
const terminal = await appendBlockEvent({
|
|
358
|
-
ctx,
|
|
359
|
-
vctx,
|
|
360
|
-
req,
|
|
361
|
-
promptId: receiptId,
|
|
362
|
-
blockSeq: 1,
|
|
363
|
-
evt: {
|
|
364
|
-
type: "block.end",
|
|
365
|
-
streamId: receiptId,
|
|
366
|
-
blockId: receiptId,
|
|
367
|
-
blockNr: 0,
|
|
368
|
-
seq: 1,
|
|
369
|
-
timestamp: new Date(),
|
|
370
|
-
stats: {
|
|
371
|
-
toplevel: { lines: 0, bytes: 0 },
|
|
372
|
-
code: { lines: 0, bytes: 0 },
|
|
373
|
-
image: { lines: 0, bytes: 0 },
|
|
374
|
-
total: { lines: 0, bytes: 0 },
|
|
375
|
-
},
|
|
376
|
-
usage: { given: [], calculated: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 } },
|
|
377
|
-
},
|
|
378
|
-
});
|
|
379
|
-
if (terminal.isErr())
|
|
380
|
-
return Result.Err(terminal.Err());
|
|
381
|
-
const ended = await appendBlockEvent({
|
|
382
|
-
ctx,
|
|
383
|
-
vctx,
|
|
384
|
-
req,
|
|
385
|
-
promptId: receiptId,
|
|
386
|
-
blockSeq: 2,
|
|
387
|
-
evt: { type: "prompt.block-end", streamId: receiptId, chatId: req.chatId, seq: 2, timestamp: new Date() },
|
|
388
|
-
});
|
|
389
|
-
if (ended.isErr())
|
|
390
|
-
return Result.Err(ended.Err());
|
|
103
|
+
const agent = rAgent.Ok();
|
|
104
|
+
if (agent.kind === "receipt")
|
|
391
105
|
return Result.Ok(EventoResult.Continue);
|
|
392
|
-
|
|
393
|
-
agentSession =
|
|
394
|
-
agentEvidence =
|
|
395
|
-
|
|
396
|
-
promptId: live.promptId,
|
|
397
|
-
sessionId: live.promptId,
|
|
398
|
-
append: (evt, blockSeq) => appendBlockEvent({ ctx, vctx, req, promptId: live.promptId, blockSeq, evt }),
|
|
399
|
-
}), turnLatency);
|
|
400
|
-
const active = await agentEvidence({
|
|
401
|
-
kind: "active",
|
|
402
|
-
...(live.supersedes === undefined ? {} : { supersedes: live.supersedes }),
|
|
403
|
-
});
|
|
404
|
-
if (active.isErr()) {
|
|
405
|
-
live.close();
|
|
406
|
-
return Result.Err(active.Err());
|
|
407
|
-
}
|
|
408
|
-
if (live.session.messages().length === 0) {
|
|
409
|
-
const initial = agentAssembled.messages.slice(0, agentAssembled.messages.length - newMessageCount - (agentWakeNote === undefined ? 0 : 1));
|
|
410
|
-
const saved = await live.session.checkpoint(initial);
|
|
411
|
-
if (saved.isErr()) {
|
|
412
|
-
live.close();
|
|
413
|
-
return Result.Err(saved.Err());
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
const events = await nextAgentSessionMessages(live.session, agentEvidence);
|
|
417
|
-
if (events.isErr()) {
|
|
418
|
-
live.close();
|
|
419
|
-
return Result.Err(events.Err());
|
|
420
|
-
}
|
|
421
|
-
agentAssembled = {
|
|
422
|
-
...agentAssembled,
|
|
423
|
-
messages: composeAgentRequest({
|
|
424
|
-
system: agentAssembled.messages.filter((message) => message.role === "system"),
|
|
425
|
-
journal: markJournalCacheTail(live.session.messages()),
|
|
426
|
-
context: agentAssembled.messages.filter(isAppContextMessage),
|
|
427
|
-
tail: events.Ok() ?? [],
|
|
428
|
-
}),
|
|
429
|
-
};
|
|
430
|
-
const saved = await live.session.checkpoint(agentAssembled.messages);
|
|
431
|
-
if (saved.isErr()) {
|
|
432
|
-
live.close();
|
|
433
|
-
return Result.Err(saved.Err());
|
|
434
|
-
}
|
|
106
|
+
agentAssembled = agent.agentAssembled;
|
|
107
|
+
agentSession = agent.agentSession;
|
|
108
|
+
agentEvidence = agent.agentEvidence;
|
|
109
|
+
agentFetchUrlContext = agent.agentFetchUrlContext;
|
|
435
110
|
}
|
|
436
111
|
else {
|
|
437
|
-
const
|
|
438
|
-
chatId: req.chatId,
|
|
439
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
440
|
-
model: modelId,
|
|
441
|
-
newUserMessages: orig.prompt.messages.filter(isChatMessage),
|
|
442
|
-
selected: orig.selected,
|
|
443
|
-
slots: resolveSlotConfig(orig.slots, {
|
|
444
|
-
SLOTS_ORIGINAL: vctx.sthis.env.get("SLOTS_ORIGINAL"),
|
|
445
|
-
SLOTS_SELECTED: vctx.sthis.env.get("SLOTS_SELECTED"),
|
|
446
|
-
SLOTS_LAST_EDIT: vctx.sthis.env.get("SLOTS_LAST_EDIT"),
|
|
447
|
-
SLOTS_PREVIOUS: vctx.sthis.env.get("SLOTS_PREVIOUS"),
|
|
448
|
-
SLOTS_COMPACTION: vctx.sthis.env.get("SLOTS_COMPACTION"),
|
|
449
|
-
}),
|
|
450
|
-
focusPath: orig.focusPath,
|
|
451
|
-
attachScreenshot: orig.dryRun !== true,
|
|
452
|
-
degradeAttachments: orig.dryRun === true,
|
|
453
|
-
...(directBuildRequested && Array.isArray(orig.agentSkills) && orig.agentSkills.length > 0
|
|
454
|
-
? { forceSkills: orig.agentSkills }
|
|
455
|
-
: {}),
|
|
456
|
-
});
|
|
457
|
-
if (rAssembled.isErr())
|
|
458
|
-
return Result.Err(rAssembled);
|
|
459
|
-
preAssembled = rAssembled.Ok();
|
|
460
|
-
if (orig.dryRun === true) {
|
|
461
|
-
const dryRunPromptId = `dry-run-${vctx.sthis.nextId(12).str}`;
|
|
462
|
-
await ctx.send.send(ctx, wrapMsgBase(ctx.validated, {
|
|
463
|
-
payload: {
|
|
464
|
-
type: "vibes.diy.res-prompt-chat-section",
|
|
465
|
-
chatId: req.chatId,
|
|
466
|
-
ownerHandle: resChat.ownerHandle,
|
|
467
|
-
appSlug: resChat.appSlug,
|
|
468
|
-
promptId: dryRunPromptId,
|
|
469
|
-
outerTid: req.outerTid,
|
|
470
|
-
mode: req.mode,
|
|
471
|
-
},
|
|
472
|
-
tid: ctx.validated.tid,
|
|
473
|
-
src: "promptChatSection",
|
|
474
|
-
}));
|
|
475
|
-
const now = () => new Date();
|
|
476
|
-
let seq = 0;
|
|
477
|
-
await appendBlockEvent({
|
|
478
|
-
ctx,
|
|
479
|
-
vctx,
|
|
480
|
-
req,
|
|
481
|
-
promptId: dryRunPromptId,
|
|
482
|
-
blockSeq: seq,
|
|
483
|
-
emitMode: "emit-only",
|
|
484
|
-
evt: { type: "prompt.block-begin", streamId: dryRunPromptId, chatId: req.chatId, seq, timestamp: now() },
|
|
485
|
-
});
|
|
486
|
-
seq++;
|
|
487
|
-
await appendBlockEvent({
|
|
488
|
-
ctx,
|
|
489
|
-
vctx,
|
|
490
|
-
req,
|
|
491
|
-
promptId: dryRunPromptId,
|
|
492
|
-
blockSeq: seq,
|
|
493
|
-
emitMode: "emit-only",
|
|
494
|
-
evt: {
|
|
495
|
-
type: "prompt.dry-run-payload",
|
|
496
|
-
streamId: dryRunPromptId,
|
|
497
|
-
chatId: req.chatId,
|
|
498
|
-
seq,
|
|
499
|
-
timestamp: now(),
|
|
500
|
-
request: { ...orig.prompt, model: preAssembled.model, messages: preAssembled.messages },
|
|
501
|
-
},
|
|
502
|
-
});
|
|
503
|
-
seq++;
|
|
504
|
-
await appendBlockEvent({
|
|
505
|
-
ctx,
|
|
506
|
-
vctx,
|
|
507
|
-
req,
|
|
508
|
-
promptId: dryRunPromptId,
|
|
509
|
-
blockSeq: seq,
|
|
510
|
-
emitMode: "emit-only",
|
|
511
|
-
evt: { type: "prompt.block-end", streamId: dryRunPromptId, chatId: req.chatId, seq, timestamp: now() },
|
|
512
|
-
});
|
|
513
|
-
return Result.Ok(EventoResult.Continue);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
let resolvedImgModel;
|
|
518
|
-
if (isReqPromptImageChatSection(orig)) {
|
|
519
|
-
const override = orig.prompt.model;
|
|
520
|
-
if (override) {
|
|
521
|
-
resolvedImgModel = override;
|
|
522
|
-
}
|
|
523
|
-
else {
|
|
524
|
-
const rDefaults = await getModelDefaults(vctx, { appSlug: resChat.appSlug, ownerHandle: resChat.ownerHandle });
|
|
525
|
-
if (rDefaults.isOk()) {
|
|
526
|
-
const defaults = rDefaults.Ok();
|
|
527
|
-
const hasInputImage = !!orig.inputImageBase64;
|
|
528
|
-
const editDefault = hasInputImage ? defaults["img-edit"] : undefined;
|
|
529
|
-
resolvedImgModel = (editDefault ?? defaults.img).model.id;
|
|
530
|
-
orig.prompt.model = resolvedImgModel;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
if (resolvedImgModel?.startsWith("prodia/") && !vctx.prodiaToken) {
|
|
535
|
-
resolvedImgModel = "google/gemini-2.5-flash-image";
|
|
536
|
-
if (isReqPromptImageChatSection(orig)) {
|
|
537
|
-
orig.prompt.model = resolvedImgModel;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
const useProdia = !!(isReqPromptImageChatSection(orig) && vctx.prodiaToken && resolvedImgModel?.startsWith("prodia/"));
|
|
541
|
-
const terminal = { promptBlockEndEmitted: false, latency: turnLatency };
|
|
542
|
-
let prompSectionAction;
|
|
543
|
-
if (isReqPromptImageChatSection(orig) && useProdia) {
|
|
544
|
-
prompSectionAction = async (scope, blockSeq) => {
|
|
545
|
-
const reqWithAuth = { ...orig, _auth: req._auth };
|
|
546
|
-
return handleProdiaImageRequest({
|
|
547
|
-
scope,
|
|
548
|
-
ctx,
|
|
549
|
-
vctx,
|
|
550
|
-
req: reqWithAuth,
|
|
551
|
-
promptId,
|
|
552
|
-
blockSeq,
|
|
553
|
-
resolvedModel: resolvedImgModel,
|
|
554
|
-
resChat,
|
|
555
|
-
});
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
else if (agentAssembled !== undefined && isReqPromptLLMChatSection(orig)) {
|
|
559
|
-
const agentPayload = agentAssembled;
|
|
560
|
-
const liveSession = agentSession;
|
|
561
|
-
if (liveSession === undefined)
|
|
562
|
-
return Result.Err("Agent turn has no session");
|
|
563
|
-
prompSectionAction = async (scope, blockSeq) => {
|
|
564
|
-
const rActor = await resolveAgentActor(vctx, {
|
|
565
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
566
|
-
scope: agentFirstTurnMint
|
|
567
|
-
? { ownerHandle: resChat.ownerHandle }
|
|
568
|
-
: { ownerHandle: resChat.ownerHandle, appSlug: resChat.appSlug },
|
|
569
|
-
});
|
|
570
|
-
if (rActor.isErr())
|
|
571
|
-
return Result.Err(rActor.Err());
|
|
572
|
-
let liveAppSlug = resChat.appSlug;
|
|
573
|
-
let firstTurnAppClaimed = agentFirstTurnMint === false;
|
|
574
|
-
const rVfs = await loadWorkVfs(vctx, {
|
|
575
|
-
chatId: req.chatId,
|
|
576
|
-
ownerHandle: resChat.ownerHandle,
|
|
577
|
-
appSlug: resChat.appSlug,
|
|
578
|
-
editBaseFsId: undefined,
|
|
579
|
-
});
|
|
580
|
-
if (rVfs.isErr())
|
|
581
|
-
return Result.Err(rVfs.Err());
|
|
582
|
-
const vfs = new Map(rVfs.Ok());
|
|
583
|
-
function extendDeadlineForAwaitedBuild(awaiting) {
|
|
584
|
-
void extendOpenTurnDeadline(vctx.sql, {
|
|
585
|
-
chatId: req.chatId,
|
|
586
|
-
promptId,
|
|
587
|
-
deadlineAtMs: Date.now() + OPEN_TURN_AWAIT_BUILD_EXTENSION_MS,
|
|
588
|
-
}).then((r) => {
|
|
589
|
-
if (r.isErr()) {
|
|
590
|
-
vctx.logger
|
|
591
|
-
.Warn()
|
|
592
|
-
.Err(r)
|
|
593
|
-
.Any("event", { chatId: req.chatId, promptId, awaiting })
|
|
594
|
-
.Msg("agent-await-deadline-extend-failed");
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
const firstTurnFileBlocks = orig.prompt.messages
|
|
599
|
-
.filter(isUserChatMessage)
|
|
600
|
-
.flatMap((m) => m.content.filter((c) => c.type === "vibes_file"));
|
|
601
|
-
const dispatcher = createAgentBuildDispatcher({
|
|
602
|
-
vctx,
|
|
603
|
-
host: ctx,
|
|
604
|
-
auth: req.auth,
|
|
605
|
-
outerTid: req.outerTid,
|
|
606
|
-
handle: (dispatchCtx) => promptChatSection.handle(dispatchCtx),
|
|
607
|
-
wakeBudget: 0,
|
|
608
|
-
onPendingBuild: (t) => {
|
|
609
|
-
extendDeadlineForAwaitedBuild(t.promptId);
|
|
610
|
-
return liveSession.watch(t.promptId);
|
|
611
|
-
},
|
|
612
|
-
...(agentFirstTurnMint
|
|
613
|
-
? {
|
|
614
|
-
firstTurn: {
|
|
615
|
-
chatId: req.chatId,
|
|
616
|
-
...(submittedAt === undefined ? {} : { submittedAt }),
|
|
617
|
-
...(firstTurnFileBlocks.length === 0 ? {} : { fileBlocks: firstTurnFileBlocks }),
|
|
618
|
-
...(orig.varietyPin === undefined
|
|
619
|
-
? {}
|
|
620
|
-
: { varietyPin: orig.varietyPin }),
|
|
621
|
-
...(typeof orig.stylePin === "string"
|
|
622
|
-
? { stylePin: orig.stylePin }
|
|
623
|
-
: {}),
|
|
624
|
-
},
|
|
625
|
-
}
|
|
626
|
-
: {}),
|
|
627
|
-
...(Object.keys(dispatchCarry).length === 0 ? {} : { carry: dispatchCarry }),
|
|
628
|
-
});
|
|
629
|
-
const belt = createAgentBelt(vctx, {
|
|
630
|
-
actor: rActor.Ok(),
|
|
631
|
-
chatId: req.chatId,
|
|
632
|
-
vfs,
|
|
633
|
-
...(agentFirstTurnMint
|
|
634
|
-
? {
|
|
635
|
-
firstTurn: {
|
|
636
|
-
chatId: req.chatId,
|
|
637
|
-
claim: () => claimFirstTurnMint(vctx, req.chatId),
|
|
638
|
-
release: async () => {
|
|
639
|
-
await claimMintJob(vctx, req.chatId, ["pending"], "agent");
|
|
640
|
-
},
|
|
641
|
-
},
|
|
642
|
-
}
|
|
643
|
-
: {}),
|
|
644
|
-
...(agentFetchUrlContext === undefined ? {} : { fetchUrl: agentFetchUrlContext }),
|
|
645
|
-
dispatcher,
|
|
646
|
-
queueEdit: (input) => liveSession.queue(input),
|
|
647
|
-
fileSession: liveSession,
|
|
648
|
-
...(instructionVariant === undefined ? {} : { instructionVariant }),
|
|
649
|
-
onStyleApplied: async (applied) => {
|
|
650
|
-
await appendBlockEvent({
|
|
651
|
-
ctx,
|
|
652
|
-
vctx,
|
|
653
|
-
req,
|
|
654
|
-
promptId,
|
|
655
|
-
blockSeq,
|
|
656
|
-
evt: {
|
|
657
|
-
type: "prompt.restyle",
|
|
658
|
-
streamId: promptId,
|
|
659
|
-
chatId: req.chatId,
|
|
660
|
-
seq: blockSeq,
|
|
661
|
-
timestamp: new Date(),
|
|
662
|
-
style: applied.style,
|
|
663
|
-
description: applied.description,
|
|
664
|
-
},
|
|
665
|
-
emitMode: "emit-only",
|
|
666
|
-
});
|
|
667
|
-
},
|
|
668
|
-
onDispatch: (dispatched) => {
|
|
669
|
-
liveAppSlug = dispatched.appSlug;
|
|
670
|
-
liveSession.claimAppAddress(dispatched.appSlug);
|
|
671
|
-
firstTurnAppClaimed = true;
|
|
672
|
-
vctx.logger
|
|
673
|
-
.Info()
|
|
674
|
-
.Any("event", { chatId: dispatched.chatId, appSlug: dispatched.appSlug, promptId })
|
|
675
|
-
.Msg("agent-turn-dispatched-build");
|
|
676
|
-
},
|
|
677
|
-
});
|
|
678
|
-
turnToolsOffered = belt.definitions.map((d) => d.function.name);
|
|
679
|
-
await liveSession.bind((input) => runEditVibeTool(vctx, {
|
|
680
|
-
actor: rActor.Ok(),
|
|
681
|
-
chatId: req.chatId,
|
|
682
|
-
input,
|
|
683
|
-
dispatcher,
|
|
684
|
-
toolsOffered: belt.definitions.map((d) => d.function.name),
|
|
685
|
-
}), async (commit) => {
|
|
686
|
-
if (firstTurnAppClaimed === false)
|
|
687
|
-
return Result.Ok({
|
|
688
|
-
ok: false,
|
|
689
|
-
reason: "no-app-yet",
|
|
690
|
-
message: "Call create_vibe first; there is no app to edit until it has been created.",
|
|
691
|
-
});
|
|
692
|
-
const currentActor = await resolveAgentActor(vctx, {
|
|
693
|
-
userId: rActor.Ok().userId,
|
|
694
|
-
requestedHandle: rActor.Ok().ownerHandle,
|
|
695
|
-
scope: rActor.Ok().scope,
|
|
696
|
-
});
|
|
697
|
-
if (currentActor.isErr())
|
|
698
|
-
return Result.Err(currentActor.Err());
|
|
699
|
-
const scoped = await resolveChatApp(vctx, currentActor.Ok(), req.chatId);
|
|
700
|
-
if (scoped.isErr())
|
|
701
|
-
return Result.Err(scoped.Err());
|
|
702
|
-
const commitId = vctx.sthis.nextId(12).str;
|
|
703
|
-
const lock = acquireTurnBuildLock({
|
|
704
|
-
vctx,
|
|
705
|
-
chatId: req.chatId,
|
|
706
|
-
promptId: commitId,
|
|
707
|
-
movesFilesystem: true,
|
|
708
|
-
wakesOnTerminal: false,
|
|
709
|
-
});
|
|
710
|
-
if (lock.acquired === false)
|
|
711
|
-
return Result.Err("A build is running; the staged commit could not acquire the write lane.");
|
|
712
|
-
const committed = { promptBlockEndEmitted: false };
|
|
713
|
-
const saved = await exception2Result(() => handleFSPrompt({
|
|
714
|
-
scope,
|
|
715
|
-
vctx,
|
|
716
|
-
ctx,
|
|
717
|
-
promptId: commitId,
|
|
718
|
-
blockSeq: 0,
|
|
719
|
-
terminal: committed,
|
|
720
|
-
beginDirect: true,
|
|
721
|
-
resChat: { ...resChat, mode: "fs-update" },
|
|
722
|
-
req: {
|
|
723
|
-
type: "vibes.diy.req-prompt-chat-section",
|
|
724
|
-
mode: "fs-update",
|
|
725
|
-
auth: req.auth,
|
|
726
|
-
_auth: req._auth,
|
|
727
|
-
chatId: req.chatId,
|
|
728
|
-
outerTid: req.outerTid,
|
|
729
|
-
agentFileCommit: commit,
|
|
730
|
-
fsUpdate: {
|
|
731
|
-
update: commit.changes.map((file) => ({
|
|
732
|
-
type: "code-block",
|
|
733
|
-
filename: file.path,
|
|
734
|
-
content: file.contents,
|
|
735
|
-
lang: langForFilename(file.path),
|
|
736
|
-
})),
|
|
737
|
-
remove: [],
|
|
738
|
-
},
|
|
739
|
-
},
|
|
740
|
-
})).finally(() => {
|
|
741
|
-
committed.releasePersistGate?.();
|
|
742
|
-
releaseTurnBuildLock(vctx, req.chatId, commitId);
|
|
743
|
-
});
|
|
744
|
-
if (saved.isErr()) {
|
|
745
|
-
const last = await maxPersistedBlockSeq(vctx.sql, { chatId: req.chatId, promptId: commitId });
|
|
746
|
-
if (last.isErr())
|
|
747
|
-
return Result.Err(last.Err());
|
|
748
|
-
const seq = (last.Ok() ?? -1) + 1;
|
|
749
|
-
await appendBlockEvent({
|
|
750
|
-
ctx,
|
|
751
|
-
vctx,
|
|
752
|
-
req,
|
|
753
|
-
promptId: commitId,
|
|
754
|
-
blockSeq: seq,
|
|
755
|
-
evt: {
|
|
756
|
-
type: "prompt.error",
|
|
757
|
-
streamId: commitId,
|
|
758
|
-
chatId: req.chatId,
|
|
759
|
-
seq,
|
|
760
|
-
timestamp: new Date(),
|
|
761
|
-
error: saved.Err().message,
|
|
762
|
-
},
|
|
763
|
-
});
|
|
764
|
-
return Result.Err(saved.Err());
|
|
765
|
-
}
|
|
766
|
-
if (committed.fsRef === undefined)
|
|
767
|
-
return Result.Err("The commit did not persist a version.");
|
|
768
|
-
const committedPaths = commit.changes.map((file) => file.path);
|
|
769
|
-
return Result.Ok({
|
|
770
|
-
ok: true,
|
|
771
|
-
saved: true,
|
|
772
|
-
fsRef: committed.fsRef,
|
|
773
|
-
paths: committedPaths,
|
|
774
|
-
entryTouched: classifyTurnReach(committedPaths).entryTouched,
|
|
775
|
-
});
|
|
776
|
-
});
|
|
777
|
-
const res = await handlerLlmRequest({
|
|
112
|
+
const rCodegen = await assembleCodegenTurn({
|
|
778
113
|
ctx,
|
|
779
|
-
blockSeq,
|
|
780
|
-
scope,
|
|
781
|
-
vctx,
|
|
782
|
-
req: req,
|
|
783
|
-
resChat,
|
|
784
|
-
promptId,
|
|
785
|
-
preAssembled: { ...agentPayload, isInitialTurn: false },
|
|
786
|
-
modelUsage: "agent",
|
|
787
|
-
serverTools: belt.definitions,
|
|
788
|
-
});
|
|
789
|
-
const evidence = agentEvidence ??
|
|
790
|
-
observeEvidenceLine(createAgentEvidenceWriter({
|
|
791
|
-
chatId: req.chatId,
|
|
792
|
-
promptId,
|
|
793
|
-
sessionId: liveSession.promptId,
|
|
794
|
-
append: (evt, blockSeq) => appendBlockEvent({ ctx, vctx, req, promptId, blockSeq, evt }),
|
|
795
|
-
}), turnLatency);
|
|
796
|
-
let providerStream;
|
|
797
|
-
const rSse = createProviderSseStream(res.res, promptId);
|
|
798
|
-
if (rSse.isErr()) {
|
|
799
|
-
vctx.logger.Warn().Err(rSse).Str("chatId", req.chatId).Msg("agent-turn-provider-stream-unavailable");
|
|
800
|
-
}
|
|
801
|
-
else {
|
|
802
|
-
providerStream = createAgentTurnStream({
|
|
803
|
-
vctx,
|
|
804
|
-
belt,
|
|
805
|
-
actor: rActor.Ok(),
|
|
806
|
-
chatId: req.chatId,
|
|
807
|
-
vfs,
|
|
808
|
-
dispatcher,
|
|
809
|
-
request: res.llmReq,
|
|
810
|
-
stream: rSse.Ok(),
|
|
811
|
-
abort: res.abort,
|
|
812
|
-
onToolEvidence: ({ kind, call, text, round, epoch }) => evidence({ kind, callId: call.id, name: call.name, text, round, epoch }),
|
|
813
|
-
session: {
|
|
814
|
-
checkpoint: async (messages) => {
|
|
815
|
-
const saved = await liveSession.session.checkpoint(messages);
|
|
816
|
-
if (saved.isErr())
|
|
817
|
-
return saved;
|
|
818
|
-
const extended = await extendOpenTurnDeadline(vctx.sql, {
|
|
819
|
-
chatId: req.chatId,
|
|
820
|
-
promptId,
|
|
821
|
-
deadlineAtMs: Date.now() + agentTotalBudgetMs(vctx) + OPEN_TURN_AWAIT_BUILD_EXTENSION_MS,
|
|
822
|
-
});
|
|
823
|
-
if (extended.isErr())
|
|
824
|
-
return Result.Err(extended.Err());
|
|
825
|
-
return Result.Ok();
|
|
826
|
-
},
|
|
827
|
-
next: () => nextAgentSessionMessages(liveSession.session, evidence),
|
|
828
|
-
head: () => liveSession.session.head(),
|
|
829
|
-
dispatchBudgetMs: agentTotalBudgetMs(vctx),
|
|
830
|
-
},
|
|
831
|
-
dispatch: async ({ request, budget }) => {
|
|
832
|
-
const messages = agentFirstTurnMint && firstTurnAppClaimed
|
|
833
|
-
? claimAgentAppContext(request.messages, { ownerHandle: resChat.ownerHandle, appSlug: liveAppSlug })
|
|
834
|
-
: request.messages;
|
|
835
|
-
{
|
|
836
|
-
const latest = await loadWorkVfs(vctx, {
|
|
837
|
-
chatId: req.chatId,
|
|
838
|
-
ownerHandle: resChat.ownerHandle,
|
|
839
|
-
appSlug: liveAppSlug,
|
|
840
|
-
editBaseFsId: undefined,
|
|
841
|
-
});
|
|
842
|
-
if (latest.isErr())
|
|
843
|
-
return Result.Err(latest.Err());
|
|
844
|
-
vfs.clear();
|
|
845
|
-
for (const [path, content] of latest.Ok())
|
|
846
|
-
vfs.set(path, content);
|
|
847
|
-
}
|
|
848
|
-
const dispatch = await dispatchLlmRequestWithFallback({
|
|
849
|
-
vctx,
|
|
850
|
-
mode: req.mode,
|
|
851
|
-
llmReq: { ...res.llmReq, messages },
|
|
852
|
-
chatId: req.chatId,
|
|
853
|
-
promptId,
|
|
854
|
-
phase: "tool-resume",
|
|
855
|
-
budget,
|
|
856
|
-
});
|
|
857
|
-
if (dispatch.ok === false)
|
|
858
|
-
return Result.Err(dispatch.error);
|
|
859
|
-
const rRound = createProviderSseStream(dispatch.res, promptId);
|
|
860
|
-
if (rRound.isErr())
|
|
861
|
-
return Result.Err(rRound);
|
|
862
|
-
return Result.Ok({
|
|
863
|
-
request: { ...res.llmReq, messages },
|
|
864
|
-
stream: rRound.Ok(),
|
|
865
|
-
abort: dispatch.abort,
|
|
866
|
-
});
|
|
867
|
-
},
|
|
868
|
-
onError: (error) => {
|
|
869
|
-
vctx.logger.Warn().Any("event", { chatId: req.chatId, promptId, error }).Msg("agent-turn-loop-failed");
|
|
870
|
-
},
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
const finalBlockSeq = await handleLlmResponse({
|
|
874
|
-
scope,
|
|
875
114
|
vctx,
|
|
876
|
-
req
|
|
877
|
-
|
|
878
|
-
res: res.res,
|
|
879
|
-
resChat,
|
|
880
|
-
promptId,
|
|
881
|
-
blockSeq: res.blockSeq,
|
|
882
|
-
llmReq: res.llmReq,
|
|
883
|
-
abort: res.abort,
|
|
884
|
-
...(providerStream === undefined ? {} : { providerStream }),
|
|
885
|
-
stripServerTools: withoutServerTools,
|
|
886
|
-
proseOnly: true,
|
|
887
|
-
terminal,
|
|
888
|
-
researchRequested: false,
|
|
889
|
-
platformInitiated: agentWakeTurn,
|
|
890
|
-
step: agentWakeTurn ? "wake" : "agent",
|
|
891
|
-
});
|
|
892
|
-
return Result.Ok(finalBlockSeq);
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
else if (isReqPromptLLMChatSection(orig)) {
|
|
896
|
-
const buildStep = promptStepFor({
|
|
897
|
-
agentTurn: false,
|
|
898
|
-
agentWake: false,
|
|
899
|
-
agentDispatched: agentDispatchedBuild,
|
|
900
|
-
agentStep: orig.agentStep,
|
|
901
|
-
agentSkills: orig.agentSkills,
|
|
902
|
-
});
|
|
903
|
-
prompSectionAction = async (scope, blockSeq) => {
|
|
904
|
-
const res = await handlerLlmRequest({
|
|
905
|
-
ctx,
|
|
906
|
-
blockSeq,
|
|
907
|
-
scope,
|
|
908
|
-
vctx,
|
|
909
|
-
req: req,
|
|
910
|
-
resChat,
|
|
911
|
-
promptId,
|
|
912
|
-
preAssembled,
|
|
913
|
-
...(agentDispatchedBuild ? { initiator: "platform" } : {}),
|
|
914
|
-
...(agentDispatchedBuild ? { agentDispatched: true } : {}),
|
|
915
|
-
});
|
|
916
|
-
if (res.urlResearchJob !== undefined) {
|
|
917
|
-
scheduleUrlResearch((message) => exception2Result(() => Result.Ok(vctx.postQueue(message))), res.urlResearchJob, {
|
|
918
|
-
waitUntil: vctx.waitUntil,
|
|
919
|
-
onError: (error) => {
|
|
920
|
-
vctx.logger
|
|
921
|
-
.Warn()
|
|
922
|
-
.Any("event", { chatId: req.chatId, promptId, error: String(error) })
|
|
923
|
-
.Msg("url-research-enqueue-failed");
|
|
924
|
-
},
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
const finalBlockSeq = await handleLlmResponse({
|
|
928
|
-
scope,
|
|
929
|
-
vctx,
|
|
930
|
-
req: req,
|
|
931
|
-
ctx,
|
|
932
|
-
res: res.res,
|
|
933
|
-
resChat,
|
|
934
|
-
promptId,
|
|
935
|
-
blockSeq: res.blockSeq,
|
|
936
|
-
llmReq: res.llmReq,
|
|
937
|
-
abort: res.abort,
|
|
938
|
-
terminal,
|
|
939
|
-
researchRequested: res.urlResearchJob !== undefined,
|
|
940
|
-
frontendDraft: preAssembled?.frontendDraft === true && req.mode === "codegen",
|
|
941
|
-
codegenTheme: preAssembled?.codegenTheme,
|
|
942
|
-
codegenVariety: preAssembled?.codegenVariety,
|
|
943
|
-
editBaseFsId: preAssembled?.editBaseFsId,
|
|
944
|
-
agentDispatched: agentDispatchedBuild,
|
|
945
|
-
...(buildStep === undefined ? {} : { step: buildStep }),
|
|
946
|
-
...(res.urlResearchJob === undefined ? {} : { researchModel: res.urlResearchJob.model }),
|
|
947
|
-
});
|
|
948
|
-
return Result.Ok(finalBlockSeq);
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
if (isReqPromptFSChatSection(orig)) {
|
|
952
|
-
prompSectionAction = async (scope, blockSeq) => {
|
|
953
|
-
const r = await handleFSPrompt({
|
|
954
|
-
scope,
|
|
955
|
-
vctx,
|
|
956
|
-
req: req,
|
|
957
|
-
ctx,
|
|
115
|
+
req,
|
|
116
|
+
orig,
|
|
958
117
|
resChat,
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
terminal,
|
|
118
|
+
modelId: route.modelId,
|
|
119
|
+
directBuildRequested: envelope.directBuildRequested,
|
|
962
120
|
});
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
121
|
+
if (rCodegen.isErr())
|
|
122
|
+
return Result.Err(rCodegen);
|
|
123
|
+
const codegen = rCodegen.Ok();
|
|
124
|
+
if (codegen.kind === "dry-run-done")
|
|
125
|
+
return Result.Ok(EventoResult.Continue);
|
|
126
|
+
preAssembled = codegen.preAssembled;
|
|
127
|
+
}
|
|
968
128
|
}
|
|
129
|
+
const { resolvedImgModel, useProdia } = await resolveImageModel(vctx, orig, resChat);
|
|
130
|
+
const terminal = { promptBlockEndEmitted: false, latency: turnLatency };
|
|
131
|
+
const reenter = (reentry) => promptChatSection.handle(reentry);
|
|
132
|
+
const rSectionAction = selectPromptSectionAction({
|
|
133
|
+
ctx,
|
|
134
|
+
vctx,
|
|
135
|
+
req,
|
|
136
|
+
orig,
|
|
137
|
+
resChat,
|
|
138
|
+
resolvedImgModel,
|
|
139
|
+
useProdia,
|
|
140
|
+
preAssembled,
|
|
141
|
+
agentAssembled,
|
|
142
|
+
agentSession,
|
|
143
|
+
agentEvidence,
|
|
144
|
+
agentFetchUrlContext,
|
|
145
|
+
agentFirstTurnMint,
|
|
146
|
+
envelope,
|
|
147
|
+
dispatchCarry,
|
|
148
|
+
instructionVariant,
|
|
149
|
+
subagentModel,
|
|
150
|
+
subagentCall,
|
|
151
|
+
turnLatency,
|
|
152
|
+
terminal,
|
|
153
|
+
facts,
|
|
154
|
+
reenter,
|
|
155
|
+
});
|
|
156
|
+
if (rSectionAction.isErr())
|
|
157
|
+
return Result.Err(rSectionAction);
|
|
158
|
+
const prompSectionAction = rSectionAction.Ok();
|
|
969
159
|
const rBump = await bumpAppRecency(vctx, { ownerHandle: resChat.ownerHandle, appSlug: resChat.appSlug });
|
|
970
160
|
if (rBump.isErr()) {
|
|
971
161
|
vctx.logger.Warn().Err(rBump).Msg("bumpAppRecency failed");
|
|
@@ -1006,64 +196,8 @@ const accountPromptChatSection = {
|
|
|
1006
196
|
await scopey(async (scope) => {
|
|
1007
197
|
const seq = { val: 0 };
|
|
1008
198
|
const notifiesBuild = isBuildNotifyMode(req.mode);
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
scope.onCatch(async (e) => {
|
|
1012
|
-
turnErrored = true;
|
|
1013
|
-
const failureMessage = e.message;
|
|
1014
|
-
if (failureMessage !== "")
|
|
1015
|
-
turnErrorReason = failureMessage;
|
|
1016
|
-
const rMaxSeq = await maxPersistedBlockSeq(vctx.sql, { chatId: req.chatId, promptId });
|
|
1017
|
-
const maxSeq = rMaxSeq.isOk() ? rMaxSeq.Ok() : undefined;
|
|
1018
|
-
if (maxSeq !== undefined) {
|
|
1019
|
-
seq.val = Math.max(seq.val, maxSeq + 1);
|
|
1020
|
-
}
|
|
1021
|
-
const errorSeq = seq.val;
|
|
1022
|
-
seq.val++;
|
|
1023
|
-
const rError = await appendBlockEvent({
|
|
1024
|
-
ctx,
|
|
1025
|
-
vctx,
|
|
1026
|
-
req,
|
|
1027
|
-
promptId,
|
|
1028
|
-
blockSeq: errorSeq,
|
|
1029
|
-
evt: {
|
|
1030
|
-
type: "prompt.error",
|
|
1031
|
-
streamId: promptId,
|
|
1032
|
-
chatId: req.chatId,
|
|
1033
|
-
seq: errorSeq,
|
|
1034
|
-
timestamp: new Date(),
|
|
1035
|
-
error: e.message,
|
|
1036
|
-
},
|
|
1037
|
-
});
|
|
1038
|
-
if (rError.isErr()) {
|
|
1039
|
-
vctx.logger
|
|
1040
|
-
.Error()
|
|
1041
|
-
.Err(rError)
|
|
1042
|
-
.Any("event", { chatId: req.chatId, promptId, blockSeq: errorSeq })
|
|
1043
|
-
.Msg("prompt-error-persist-failed");
|
|
1044
|
-
}
|
|
1045
|
-
if (vctx.notifyUser && notifiesBuild) {
|
|
1046
|
-
const userId = req._auth.verifiedAuth.claims.userId;
|
|
1047
|
-
const connId = clientWsSend(ctx).connId;
|
|
1048
|
-
const prefs = await loadNotificationPrefs(vctx, userId);
|
|
1049
|
-
if (shouldNotify(prefs, {
|
|
1050
|
-
notificationType: "build-failed",
|
|
1051
|
-
ownerHandle: resChat.ownerHandle,
|
|
1052
|
-
appSlug: resChat.appSlug,
|
|
1053
|
-
})) {
|
|
1054
|
-
void vctx
|
|
1055
|
-
.notifyUser(userId, {
|
|
1056
|
-
type: "vibes.diy.evt-user-notification",
|
|
1057
|
-
notificationType: "build-failed",
|
|
1058
|
-
ownerHandle: resChat.ownerHandle,
|
|
1059
|
-
appSlug: resChat.appSlug,
|
|
1060
|
-
promptId,
|
|
1061
|
-
}, connId)
|
|
1062
|
-
.catch((_e) => {
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
}, 0);
|
|
199
|
+
const terminalArgs = { ctx, vctx, req, resChat, promptId, seq, facts, notifiesBuild };
|
|
200
|
+
scope.onCatch(async (e) => recordTurnError(terminalArgs, e), 0);
|
|
1067
201
|
await scope
|
|
1068
202
|
.evalResult(async () => {
|
|
1069
203
|
const res = await appendBlockEvent({
|
|
@@ -1081,7 +215,7 @@ const accountPromptChatSection = {
|
|
|
1081
215
|
},
|
|
1082
216
|
});
|
|
1083
217
|
seq.val++;
|
|
1084
|
-
const rAction = await prompSectionAction(scope, seq.val);
|
|
218
|
+
const rAction = await prompSectionAction({ scope, blockSeq: seq.val, promptId });
|
|
1085
219
|
if (rAction.isErr())
|
|
1086
220
|
return rAction;
|
|
1087
221
|
seq.val = rAction.Ok();
|
|
@@ -1089,218 +223,36 @@ const accountPromptChatSection = {
|
|
|
1089
223
|
})
|
|
1090
224
|
.finally(async () => {
|
|
1091
225
|
const turnBegan = seq.val > 0;
|
|
1092
|
-
let settledArgs;
|
|
1093
|
-
let lookLintPlan;
|
|
1094
226
|
try {
|
|
1095
|
-
await finalizePromptTurn();
|
|
227
|
+
await finalizePromptTurn({ ...terminalArgs, terminal });
|
|
1096
228
|
}
|
|
1097
229
|
finally {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
};
|
|
1121
|
-
if (lookLintPlanned(lookLintPlan) === false)
|
|
1122
|
-
captureCodegenTurnSettled(vctx, settledArgs);
|
|
1123
|
-
postMakerFact(vctx, {
|
|
1124
|
-
eventId: `turn:${promptId}`,
|
|
1125
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
1126
|
-
at: new Date().toISOString(),
|
|
1127
|
-
kind: "codegen-turn",
|
|
1128
|
-
}, "codegen-turn-settled");
|
|
1129
|
-
const ownWords = agentDispatchedBuild === false && agentWakeTurn === false && isReqPromptLLMChatSection(orig)
|
|
1130
|
-
? currentUserMessageText(orig.prompt.messages.filter(isChatMessage))
|
|
1131
|
-
: undefined;
|
|
1132
|
-
postCapiBuildEvent(vctx, {
|
|
1133
|
-
outcome: settledArgs.outcome,
|
|
1134
|
-
firstBuild: settledArgs.firstBuild,
|
|
1135
|
-
promptId,
|
|
1136
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
1137
|
-
promptText: ownWords,
|
|
1138
|
-
});
|
|
1139
|
-
}
|
|
1140
|
-
peekInFlightTurns(req.chatId)?.delete(promptId);
|
|
1141
|
-
await agentSession?.settle();
|
|
1142
|
-
releaseTurnBuildLock(vctx, req.chatId, promptId);
|
|
1143
|
-
terminal.releasePersistGate?.();
|
|
1144
|
-
if (settledArgs !== undefined && lookLintPlan !== undefined) {
|
|
1145
|
-
const args = settledArgs;
|
|
1146
|
-
dispatchLookLint(vctx, {
|
|
1147
|
-
...lookLintPlan,
|
|
1148
|
-
files: async () => (terminal.fsRef === undefined ? {} : loadTurnFilesByFsId(vctx, terminal.fsRef.fsId)),
|
|
1149
|
-
onResult: (lookLint) => {
|
|
1150
|
-
captureCodegenTurnSettled(vctx, lookLint === undefined ? args : { ...args, lookLint });
|
|
1151
|
-
},
|
|
1152
|
-
});
|
|
1153
|
-
}
|
|
1154
|
-
const accessTouched = (terminal.touchedPaths ?? []).some((path) => /\/?(access\.js|seed\.json)$/.test(path)) &&
|
|
1155
|
-
terminal.fsRef !== undefined;
|
|
1156
|
-
const accessFsRef = terminal.fsRef;
|
|
1157
|
-
const rAccessReport = await exception2Result(async () => {
|
|
1158
|
-
if (!accessTouched || accessFsRef === undefined)
|
|
1159
|
-
return undefined;
|
|
1160
|
-
const report = await releaseAccessVerdicts(vctx, {
|
|
1161
|
-
ownerHandle: resChat.ownerHandle,
|
|
1162
|
-
appSlug: resChat.appSlug,
|
|
1163
|
-
files: () => loadTurnFilesByFsId(vctx, accessFsRef.fsId),
|
|
1164
|
-
});
|
|
1165
|
-
if (report !== undefined) {
|
|
1166
|
-
captureAccessVerdicts(vctx, {
|
|
1167
|
-
lane: "build",
|
|
1168
|
-
userId: req._auth.verifiedAuth.claims.userId,
|
|
1169
|
-
ownerHandle: resChat.ownerHandle,
|
|
1170
|
-
appSlug: resChat.appSlug,
|
|
1171
|
-
report,
|
|
1172
|
-
accessChanged: (terminal.touchedPaths ?? []).some((path) => /\/?access\.js$/.test(path)),
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
return report;
|
|
1176
|
-
});
|
|
1177
|
-
if (rAccessReport.isErr()) {
|
|
1178
|
-
vctx.logger.Warn().Err(rAccessReport.Err()).Str("promptId", promptId).Msg("access-verdicts-terminal-failed");
|
|
1179
|
-
}
|
|
1180
|
-
const accessReport = rAccessReport.isErr() ? undefined : rAccessReport.Ok();
|
|
1181
|
-
const landingOutcome = {
|
|
1182
|
-
outcome: turnErrored
|
|
1183
|
-
? "error"
|
|
1184
|
-
: terminal.settled?.applied === true
|
|
1185
|
-
? "applied"
|
|
1186
|
-
: "no-code",
|
|
1187
|
-
...(terminal.touchedPaths === undefined ? {} : { touchedPaths: terminal.touchedPaths }),
|
|
1188
|
-
...(terminal.settled === undefined || turnErrored ? {} : { settled: terminal.settled }),
|
|
1189
|
-
...(terminal.fsRef === undefined ? {} : { fsId: terminal.fsRef.fsId }),
|
|
1190
|
-
...(accessReport === undefined ? {} : { accessLine: renderAccessVerdictLine(accessReport) }),
|
|
1191
|
-
...(turnErrorReason === undefined ? {} : { errorReason: turnErrorReason }),
|
|
1192
|
-
};
|
|
1193
|
-
const { consumed } = settleTurnTerminal(vctx.connections, req.chatId, promptId, landingOutcome);
|
|
1194
|
-
const wake = decideAgentWake({
|
|
1195
|
-
agentDispatched: agentDispatchedBuild,
|
|
1196
|
-
movedFilesystem: movesFilesystem,
|
|
1197
|
-
budget: 1,
|
|
230
|
+
await settlePromptTurn({
|
|
231
|
+
ctx,
|
|
232
|
+
vctx,
|
|
233
|
+
req,
|
|
234
|
+
orig,
|
|
235
|
+
resChat,
|
|
236
|
+
promptId,
|
|
237
|
+
terminal,
|
|
238
|
+
facts,
|
|
239
|
+
turnBegan,
|
|
240
|
+
preAssembled,
|
|
241
|
+
agentAssembled,
|
|
242
|
+
agentSession,
|
|
243
|
+
envelope,
|
|
244
|
+
turnStartedAt,
|
|
245
|
+
turnLatency,
|
|
246
|
+
movesFilesystem,
|
|
247
|
+
builderModel,
|
|
248
|
+
subagentModel,
|
|
249
|
+
instructionVariant,
|
|
250
|
+
wakeAgentModel,
|
|
251
|
+
reenter,
|
|
1198
252
|
});
|
|
1199
|
-
if (consumed === true) {
|
|
1200
|
-
vctx.logger
|
|
1201
|
-
.Info()
|
|
1202
|
-
.Any("event", { chatId: req.chatId, promptId, outcome: landingOutcome.outcome })
|
|
1203
|
-
.Msg("agent-build-landing-consumed");
|
|
1204
|
-
}
|
|
1205
|
-
else if (wake.wake === true) {
|
|
1206
|
-
vctx.logger.Info().Any("event", { chatId: req.chatId, promptId, budget: wake.budget }).Msg("agent-wake-firing");
|
|
1207
|
-
fireAgentWakeTurn({
|
|
1208
|
-
vctx,
|
|
1209
|
-
host: ctx,
|
|
1210
|
-
auth: req.auth,
|
|
1211
|
-
outerTid: req.outerTid,
|
|
1212
|
-
chatId: req.chatId,
|
|
1213
|
-
budget: wake.budget,
|
|
1214
|
-
note: renderAgentWakeNote(landingOutcome),
|
|
1215
|
-
...(builderModel === undefined ? {} : { builderModel }),
|
|
1216
|
-
...(instructionVariant === undefined ? {} : { instructionVariant }),
|
|
1217
|
-
...(wakeAgentModel === undefined ? {} : { agentModel: wakeAgentModel }),
|
|
1218
|
-
handle: (wakeCtx) => promptChatSection.handle(promptDispatchContext(ctx, wakeCtx.validated)),
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1221
|
-
else {
|
|
1222
|
-
vctx.logger
|
|
1223
|
-
.Info()
|
|
1224
|
-
.Any("event", {
|
|
1225
|
-
chatId: req.chatId,
|
|
1226
|
-
promptId,
|
|
1227
|
-
skip: wake.skip,
|
|
1228
|
-
agentDispatched: agentDispatchedBuild,
|
|
1229
|
-
movedFilesystem: movesFilesystem,
|
|
1230
|
-
budget: agentWakeBudget,
|
|
1231
|
-
})
|
|
1232
|
-
.Msg("agent-wake-skipped");
|
|
1233
|
-
}
|
|
1234
253
|
}
|
|
1235
254
|
})
|
|
1236
255
|
.do();
|
|
1237
|
-
async function finalizePromptTurn() {
|
|
1238
|
-
if (seq.val === 0)
|
|
1239
|
-
return;
|
|
1240
|
-
const rEnd = await appendBlockEvent({
|
|
1241
|
-
ctx,
|
|
1242
|
-
vctx,
|
|
1243
|
-
req,
|
|
1244
|
-
promptId,
|
|
1245
|
-
blockSeq: seq.val,
|
|
1246
|
-
evt: {
|
|
1247
|
-
type: "prompt.block-end",
|
|
1248
|
-
streamId: promptId,
|
|
1249
|
-
chatId: req.chatId,
|
|
1250
|
-
seq: seq.val,
|
|
1251
|
-
timestamp: new Date(),
|
|
1252
|
-
},
|
|
1253
|
-
emitMode: terminal.promptBlockEndEmitted ? "store-only" : "store",
|
|
1254
|
-
});
|
|
1255
|
-
if (rEnd.isErr()) {
|
|
1256
|
-
vctx.logger
|
|
1257
|
-
.Error()
|
|
1258
|
-
.Err(rEnd)
|
|
1259
|
-
.Any("event", { chatId: req.chatId, promptId, blockSeq: seq.val })
|
|
1260
|
-
.Msg("prompt-block-end-persist-failed");
|
|
1261
|
-
}
|
|
1262
|
-
if (shouldCloseTurnRecord({ canonicalMode: canonicalModelUsage(req.mode), terminalPersisted: rEnd.isOk() })) {
|
|
1263
|
-
const rClose = await closeTurn(vctx.sql, { chatId: req.chatId, promptId });
|
|
1264
|
-
if (rClose.isErr()) {
|
|
1265
|
-
vctx.logger.Warn().Err(rClose).Any("event", { chatId: req.chatId, promptId }).Msg("close-turn-record-failed");
|
|
1266
|
-
}
|
|
1267
|
-
else if (rClose.Ok() === false) {
|
|
1268
|
-
vctx.logger.Warn().Any("event", { chatId: req.chatId, promptId, turnErrored }).Msg("turn-closed-after-sweep");
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
if (vctx.notifyUser && notifiesBuild && turnErrored === false) {
|
|
1272
|
-
const userId = req._auth.verifiedAuth.claims.userId;
|
|
1273
|
-
const connId = clientWsSend(ctx).connId;
|
|
1274
|
-
const prefs = await loadNotificationPrefs(vctx, userId);
|
|
1275
|
-
if (shouldNotify(prefs, {
|
|
1276
|
-
notificationType: "build-complete",
|
|
1277
|
-
ownerHandle: resChat.ownerHandle,
|
|
1278
|
-
appSlug: resChat.appSlug,
|
|
1279
|
-
})) {
|
|
1280
|
-
const persisted = terminal.fsRef;
|
|
1281
|
-
const version = persisted === undefined
|
|
1282
|
-
? undefined
|
|
1283
|
-
: await resolveBuildOrdinal(vctx, {
|
|
1284
|
-
ownerHandle: persisted.ownerHandle,
|
|
1285
|
-
appSlug: persisted.appSlug,
|
|
1286
|
-
fsId: persisted.fsId,
|
|
1287
|
-
});
|
|
1288
|
-
const fsId = persisted?.fsId;
|
|
1289
|
-
void vctx
|
|
1290
|
-
.notifyUser(userId, {
|
|
1291
|
-
type: "vibes.diy.evt-user-notification",
|
|
1292
|
-
notificationType: "build-complete",
|
|
1293
|
-
ownerHandle: resChat.ownerHandle,
|
|
1294
|
-
appSlug: resChat.appSlug,
|
|
1295
|
-
promptId,
|
|
1296
|
-
...(fsId === undefined ? {} : { fsId }),
|
|
1297
|
-
...(version === undefined ? {} : { version }),
|
|
1298
|
-
}, connId)
|
|
1299
|
-
.catch((_e) => {
|
|
1300
|
-
});
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
256
|
});
|
|
1305
257
|
return Result.Ok(EventoResult.Continue);
|
|
1306
258
|
}),
|