@vibes.diy/api-svc 14.3.88 → 14.3.90
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/get-model-defaults.d.ts +1 -0
- package/intern/get-model-defaults.js +2 -1
- package/intern/get-model-defaults.js.map +1 -1
- package/intern/instant-build.d.ts +154 -0
- package/intern/instant-build.js +443 -0
- package/intern/instant-build.js.map +1 -0
- package/intern/prompt-assembly.d.ts +20 -0
- package/intern/prompt-assembly.js +10 -1
- package/intern/prompt-assembly.js.map +1 -1
- package/package.json +13 -13
- package/public/codegen-turn-route.d.ts +9 -0
- package/public/codegen-turn-route.js +47 -2
- package/public/codegen-turn-route.js.map +1 -1
- package/public/handle-prompt-context.d.ts +3 -1
- package/public/handle-prompt-context.js +9 -1
- package/public/handle-prompt-context.js.map +1 -1
- package/public/handler-llm-request.d.ts +6 -1
- package/public/handler-llm-request.js +11 -9
- package/public/handler-llm-request.js.map +1 -1
- package/public/prompt-chat-section.js +1 -0
- package/public/prompt-chat-section.js.map +1 -1
- package/public/prompt-section-actions.js +24 -0
- package/public/prompt-section-actions.js.map +1 -1
- package/public/prompt-turn-types.d.ts +2 -0
- package/public/stream-assembly.d.ts +5 -2
- package/public/stream-assembly.js +5 -2
- package/public/stream-assembly.js.map +1 -1
|
@@ -65,7 +65,7 @@ export async function getModelDefaults(ctx, { appSlug, ownerHandle }) {
|
|
|
65
65
|
]);
|
|
66
66
|
if (rDefaults.isErr())
|
|
67
67
|
return Result.Err(rDefaults);
|
|
68
|
-
const result = { ...rDefaults.Ok() };
|
|
68
|
+
const result = { ...rDefaults.Ok(), instantBuild: false };
|
|
69
69
|
if (rAccount.isErr())
|
|
70
70
|
return Result.Err(rAccount);
|
|
71
71
|
const userRow = rAccount.Ok();
|
|
@@ -90,6 +90,7 @@ export async function getModelDefaults(ctx, { appSlug, ownerHandle }) {
|
|
|
90
90
|
result.runtime = runtime;
|
|
91
91
|
if (modelDefaults.img?.model)
|
|
92
92
|
result.img = modelDefaults.img;
|
|
93
|
+
result.instantBuild = modelDefaults.instantBuild === true;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
if (rApp !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-model-defaults.js","sourceRoot":"","sources":["../../jsr/intern/get-model-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAEL,2BAA2B,EAC3B,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAE1B,eAAe,EACf,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAE5E,KAAK,UAAU,uBAAuB,CAAC,GAAmB;IACxD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;IAKnC,MAAM,cAAc,GAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,EAA8B,CAAC;IAChD,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,yCAAyC,KAAK,EAAE,CAAC,CAAC;QAChF,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAqB,CAAC;IACxD,CAAC;IAKD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACzE,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAqB,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC;aACxC,IAAI,EAAE;aACN,GAAG,CAAC,4EAA4E,CAAC,CAAC;QACrF,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;IACvC,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACxE,IAAI,OAAO,EAAE,CAAC;QACZ,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAqB,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;
|
|
1
|
+
{"version":3,"file":"get-model-defaults.js","sourceRoot":"","sources":["../../jsr/intern/get-model-defaults.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Result } from "@adviser/cement";
|
|
2
|
+
import { type LLMMessage, type SseUsage } from "@vibes.diy/call-ai-v2";
|
|
3
|
+
import type { VibesApiSQLCtx } from "../types.js";
|
|
4
|
+
import { type SynthLook } from "./import-synth.js";
|
|
5
|
+
export type InstantCandidateName = "mercury" | "haiku";
|
|
6
|
+
export declare const INSTANT_MERCURY_MODEL = "inception/mercury-2.5";
|
|
7
|
+
export declare const INSTANT_HAIKU_MODEL = "anthropic/claude-haiku-5.5";
|
|
8
|
+
export declare const INSTANT_MAX_OUTPUT_TOKENS = 32000;
|
|
9
|
+
export declare const INSTANT_MERCURY_CALL_MS = 40000;
|
|
10
|
+
export declare const INSTANT_HAIKU_CALL_MS = 90000;
|
|
11
|
+
export declare const INSTANT_STAGE_BUDGET_MS = 150000;
|
|
12
|
+
export declare const INSTANT_MAX_ATTEMPTS = 5;
|
|
13
|
+
export interface InstantModelChoice {
|
|
14
|
+
readonly name: InstantCandidateName;
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly reasoning: {
|
|
17
|
+
readonly effort: "none";
|
|
18
|
+
} | {
|
|
19
|
+
readonly enabled: false;
|
|
20
|
+
};
|
|
21
|
+
readonly reasoningEffort?: string;
|
|
22
|
+
readonly callMs: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function instantModelChoice(name: InstantCandidateName): InstantModelChoice;
|
|
25
|
+
export declare const INSTANT_PARAGRAPH: string;
|
|
26
|
+
export declare function composeInstantBrief(sentence: string): string;
|
|
27
|
+
export declare function composeInstantEditAsk(args: {
|
|
28
|
+
readonly instruction: string;
|
|
29
|
+
readonly vfs: ReadonlyMap<string, string>;
|
|
30
|
+
}): string;
|
|
31
|
+
export declare function appendInstantContext(systemPrompt: string, ownerHandle: string): string;
|
|
32
|
+
export declare function loadInstantSystemPrompt(vctx: VibesApiSQLCtx, args: {
|
|
33
|
+
readonly chatId: string;
|
|
34
|
+
readonly ownerHandle: string;
|
|
35
|
+
readonly userId?: string;
|
|
36
|
+
}): Promise<Result<string>>;
|
|
37
|
+
export interface ParsedCandidate {
|
|
38
|
+
readonly vfs: ReadonlyMap<string, string>;
|
|
39
|
+
readonly changed: readonly string[];
|
|
40
|
+
readonly applyErrors: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
export declare function parseCandidateText(text: string, base: ReadonlyMap<string, string>): Promise<Result<ParsedCandidate>>;
|
|
43
|
+
export interface InstantGateResult {
|
|
44
|
+
readonly vfs: ReadonlyMap<string, string>;
|
|
45
|
+
readonly opens: boolean;
|
|
46
|
+
readonly findings: readonly string[];
|
|
47
|
+
readonly notes: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
export declare function autofixAndCheck(args: {
|
|
50
|
+
readonly vfs: ReadonlyMap<string, string>;
|
|
51
|
+
readonly changed: readonly string[];
|
|
52
|
+
readonly look: SynthLook;
|
|
53
|
+
}): InstantGateResult;
|
|
54
|
+
export interface InstantModelRequest {
|
|
55
|
+
readonly model: InstantModelChoice;
|
|
56
|
+
readonly messages: readonly LLMMessage[];
|
|
57
|
+
readonly signal: AbortSignal;
|
|
58
|
+
}
|
|
59
|
+
export type InstantRoundUsage = SseUsage & {
|
|
60
|
+
readonly cost?: number;
|
|
61
|
+
};
|
|
62
|
+
export interface InstantModelReply {
|
|
63
|
+
readonly text: string;
|
|
64
|
+
readonly servedModel?: string;
|
|
65
|
+
readonly usage?: InstantRoundUsage;
|
|
66
|
+
}
|
|
67
|
+
export type InstantModelCall = (req: InstantModelRequest) => Promise<Result<InstantModelReply>>;
|
|
68
|
+
export declare function instantModelCallFor(vctx: Pick<VibesApiSQLCtx, "llmRequest" | "params">): InstantModelCall;
|
|
69
|
+
export interface InstantCandidateSpec {
|
|
70
|
+
readonly model: InstantModelChoice;
|
|
71
|
+
readonly messages: readonly LLMMessage[];
|
|
72
|
+
}
|
|
73
|
+
export type InstantGate = "pass" | "fail" | "cancelled";
|
|
74
|
+
export interface InstantCandidateOutcome {
|
|
75
|
+
readonly name: InstantCandidateName;
|
|
76
|
+
readonly model: string;
|
|
77
|
+
readonly gate: InstantGate;
|
|
78
|
+
readonly attempts: number;
|
|
79
|
+
readonly ms: number;
|
|
80
|
+
readonly usage: readonly InstantRoundUsage[];
|
|
81
|
+
readonly abortedInFlight: boolean;
|
|
82
|
+
readonly vfs?: ReadonlyMap<string, string>;
|
|
83
|
+
readonly changed?: readonly string[];
|
|
84
|
+
readonly findings: readonly string[];
|
|
85
|
+
readonly error?: string;
|
|
86
|
+
}
|
|
87
|
+
export declare function runInstantCandidate(args: {
|
|
88
|
+
readonly call: InstantModelCall;
|
|
89
|
+
readonly spec: InstantCandidateSpec;
|
|
90
|
+
readonly base: ReadonlyMap<string, string>;
|
|
91
|
+
readonly look: SynthLook;
|
|
92
|
+
readonly cancel: AbortSignal;
|
|
93
|
+
readonly startedAt: number;
|
|
94
|
+
readonly deadlineAt: number;
|
|
95
|
+
readonly now?: () => number;
|
|
96
|
+
readonly maxAttempts?: number;
|
|
97
|
+
}): Promise<InstantCandidateOutcome>;
|
|
98
|
+
export interface InstantRaceResult {
|
|
99
|
+
readonly winner?: InstantCandidateOutcome;
|
|
100
|
+
readonly outcomes: readonly InstantCandidateOutcome[];
|
|
101
|
+
readonly ms: number;
|
|
102
|
+
}
|
|
103
|
+
export declare function raceInstantCandidates(args: {
|
|
104
|
+
readonly run: (o: {
|
|
105
|
+
readonly spec: InstantCandidateSpec;
|
|
106
|
+
readonly cancel: AbortSignal;
|
|
107
|
+
readonly startedAt: number;
|
|
108
|
+
readonly deadlineAt: number;
|
|
109
|
+
}) => Promise<InstantCandidateOutcome>;
|
|
110
|
+
readonly specs: readonly InstantCandidateSpec[];
|
|
111
|
+
readonly budgetMs: number;
|
|
112
|
+
readonly turn?: AbortSignal;
|
|
113
|
+
readonly now?: () => number;
|
|
114
|
+
}): Promise<InstantRaceResult>;
|
|
115
|
+
export interface InstantReceipt {
|
|
116
|
+
readonly candidates: readonly {
|
|
117
|
+
readonly model: string;
|
|
118
|
+
readonly ms: number;
|
|
119
|
+
readonly gate: InstantGate;
|
|
120
|
+
readonly attempts: number;
|
|
121
|
+
readonly abortedInFlight?: true;
|
|
122
|
+
}[];
|
|
123
|
+
readonly winner?: string;
|
|
124
|
+
}
|
|
125
|
+
export declare function instantReceipt(race: InstantRaceResult): InstantReceipt;
|
|
126
|
+
export declare function instantTurnText(race: InstantRaceResult): string;
|
|
127
|
+
export declare function instantResponse(args: {
|
|
128
|
+
readonly race: InstantRaceResult;
|
|
129
|
+
readonly promptId: string;
|
|
130
|
+
}): Response;
|
|
131
|
+
export interface InstantAssembly {
|
|
132
|
+
readonly mercurySystem?: string;
|
|
133
|
+
readonly instruction: string;
|
|
134
|
+
readonly look: SynthLook;
|
|
135
|
+
readonly base: ReadonlyMap<string, string>;
|
|
136
|
+
}
|
|
137
|
+
export interface InstantBuildOutcome {
|
|
138
|
+
readonly response: Response;
|
|
139
|
+
readonly receipt: InstantReceipt;
|
|
140
|
+
readonly model: string;
|
|
141
|
+
}
|
|
142
|
+
export declare function mercuryMessages(args: {
|
|
143
|
+
readonly system: string;
|
|
144
|
+
readonly instruction: string;
|
|
145
|
+
readonly base: ReadonlyMap<string, string>;
|
|
146
|
+
}): LLMMessage[];
|
|
147
|
+
export declare function runInstantBuild(args: {
|
|
148
|
+
readonly assembly: InstantAssembly;
|
|
149
|
+
readonly haikuMessages: readonly LLMMessage[];
|
|
150
|
+
readonly call: InstantModelCall;
|
|
151
|
+
readonly promptId: string;
|
|
152
|
+
readonly turn: AbortSignal;
|
|
153
|
+
readonly budgetMs?: number;
|
|
154
|
+
}): Promise<InstantBuildOutcome>;
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { Result, exception2Result } from "@adviser/cement";
|
|
2
|
+
import { type } from "arktype";
|
|
3
|
+
import { makeBaseSystemPrompt } from "@vibes.diy/prompts";
|
|
4
|
+
import { createBlockStream, isCodeEnd, } from "@vibes.diy/call-ai-v2";
|
|
5
|
+
import { lazyType } from "@vibes.diy/api-types/lazy-type";
|
|
6
|
+
import { createBlockAccumulator, createStreamingResolver, resolveCodeBlocks } from "./prompt-streaming.js";
|
|
7
|
+
import { synthesizeImports } from "./import-synth.js";
|
|
8
|
+
import { checkOpens, OPENS_ADVISORY_CLASSES } from "./opens-check.js";
|
|
9
|
+
import { saveRepairFindings } from "./save-repair.js";
|
|
10
|
+
import { composeRepairAsk, renderRepairFiles } from "./save-repair-io.js";
|
|
11
|
+
import { createPromptAssetFetch, promptsPkgBaseUrl } from "./prompt-asset-fetch.js";
|
|
12
|
+
import { loadActiveSettings, lookOptionForTurn } from "./prompt-assembly.js";
|
|
13
|
+
export const INSTANT_MERCURY_MODEL = "inception/mercury-2.5";
|
|
14
|
+
export const INSTANT_HAIKU_MODEL = "anthropic/claude-haiku-5.5";
|
|
15
|
+
export const INSTANT_MAX_OUTPUT_TOKENS = 32_000;
|
|
16
|
+
export const INSTANT_MERCURY_CALL_MS = 40_000;
|
|
17
|
+
export const INSTANT_HAIKU_CALL_MS = 90_000;
|
|
18
|
+
export const INSTANT_STAGE_BUDGET_MS = 150_000;
|
|
19
|
+
export const INSTANT_MAX_ATTEMPTS = 5;
|
|
20
|
+
export function instantModelChoice(name) {
|
|
21
|
+
switch (name) {
|
|
22
|
+
case "mercury":
|
|
23
|
+
return {
|
|
24
|
+
name,
|
|
25
|
+
id: INSTANT_MERCURY_MODEL,
|
|
26
|
+
reasoning: { effort: "none" },
|
|
27
|
+
reasoningEffort: "none",
|
|
28
|
+
callMs: INSTANT_MERCURY_CALL_MS,
|
|
29
|
+
};
|
|
30
|
+
case "haiku":
|
|
31
|
+
return { name, id: INSTANT_HAIKU_MODEL, reasoning: { enabled: false }, callMs: INSTANT_HAIKU_CALL_MS };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const INSTANT_PARAGRAPH = "Build the interaction this sentence names, fully working, with realistic launch content. " +
|
|
35
|
+
"Records are documents with a type; every list is a live query; every save is a document write. " +
|
|
36
|
+
"Known values are direct controls. " +
|
|
37
|
+
"Sharing, invitations, roles, scheduled jobs, emails and outside services come in a later pass.";
|
|
38
|
+
export function composeInstantBrief(sentence) {
|
|
39
|
+
const trimmed = sentence.trim().replace(/[.\s]+$/, "");
|
|
40
|
+
return `${trimmed}. ${INSTANT_PARAGRAPH}`;
|
|
41
|
+
}
|
|
42
|
+
export function composeInstantEditAsk(args) {
|
|
43
|
+
return (renderRepairFiles({ vfs: args.vfs, intro: "This is the app as it stands." }) +
|
|
44
|
+
"\nChange it as this instruction says:\n\n" +
|
|
45
|
+
args.instruction.trim() +
|
|
46
|
+
"\n\nWrite every file you change in full, in the same shape (each under its `### `path`` heading, complete, once). " +
|
|
47
|
+
"Leave out the files you do not change. Keep everything that already works.");
|
|
48
|
+
}
|
|
49
|
+
export function appendInstantContext(systemPrompt, ownerHandle) {
|
|
50
|
+
const previewMaker = `<preview-maker>${JSON.stringify({ handle: ownerHandle })}</preview-maker>\n` +
|
|
51
|
+
"This is the maker opening the first preview. Match seed.json parent IDs to this maker's opening query; resolve each visitor's identity dynamically in app code.";
|
|
52
|
+
return [systemPrompt.replace(/\n+$/, ""), previewMaker].join("\n\n");
|
|
53
|
+
}
|
|
54
|
+
export async function loadInstantSystemPrompt(vctx, args) {
|
|
55
|
+
const active = await exception2Result(() => loadActiveSettings(vctx, args.chatId));
|
|
56
|
+
if (active.isErr())
|
|
57
|
+
return Result.Err(active.Err());
|
|
58
|
+
const { skills, theme, title, enrichedPrompt, layoutArchetype, flourishes, textureNote } = active.Ok();
|
|
59
|
+
const base = await exception2Result(() => makeBaseSystemPrompt(INSTANT_MERCURY_MODEL, {
|
|
60
|
+
...(skills === undefined ? {} : { skills }),
|
|
61
|
+
theme,
|
|
62
|
+
...lookOptionForTurn(vctx, { includeTheme: true, theme, ...(args.userId === undefined ? {} : { userId: args.userId }) }),
|
|
63
|
+
title,
|
|
64
|
+
enrichedPrompt,
|
|
65
|
+
layoutArchetype,
|
|
66
|
+
flourishes,
|
|
67
|
+
textureNote,
|
|
68
|
+
demoData: false,
|
|
69
|
+
suppressDefaultStylePrompt: false,
|
|
70
|
+
variant: "initial-instant",
|
|
71
|
+
pkgBaseUrl: promptsPkgBaseUrl(vctx.params.pkgRepos.workspace),
|
|
72
|
+
fetch: createPromptAssetFetch({ fetchAsset: vctx.fetchAsset }),
|
|
73
|
+
}));
|
|
74
|
+
if (base.isErr())
|
|
75
|
+
return Result.Err(base.Err());
|
|
76
|
+
return Result.Ok(appendInstantContext(base.Ok().systemPrompt, args.ownerHandle));
|
|
77
|
+
}
|
|
78
|
+
function toLines(text) {
|
|
79
|
+
const lines = text.split("\n");
|
|
80
|
+
if (lines.length > 0 && lines[lines.length - 1] === "")
|
|
81
|
+
lines.pop();
|
|
82
|
+
return lines;
|
|
83
|
+
}
|
|
84
|
+
async function textToBlocks(text) {
|
|
85
|
+
const streamId = "instant-parse";
|
|
86
|
+
const inner = `${streamId}:lines`;
|
|
87
|
+
const now = new Date();
|
|
88
|
+
const lines = toLines(text);
|
|
89
|
+
let id = 0;
|
|
90
|
+
const input = new ReadableStream({
|
|
91
|
+
start(controller) {
|
|
92
|
+
controller.enqueue({ type: "line.begin", streamId: inner, timestamp: now });
|
|
93
|
+
lines.forEach((content, index) => controller.enqueue({ type: "line.line", streamId: inner, content, lineNr: index + 1, timestamp: now }));
|
|
94
|
+
controller.enqueue({ type: "line.end", streamId: inner, totalLines: lines.length, timestamp: now });
|
|
95
|
+
controller.close();
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
const out = input.pipeThrough(createBlockStream(streamId, inner, () => `i${++id}`));
|
|
99
|
+
const collected = [];
|
|
100
|
+
const read = await exception2Result(async () => {
|
|
101
|
+
const reader = out.getReader();
|
|
102
|
+
for (;;) {
|
|
103
|
+
const next = await reader.read();
|
|
104
|
+
if (next.done === true)
|
|
105
|
+
break;
|
|
106
|
+
collected.push(next.value);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
if (read.isErr())
|
|
110
|
+
return Result.Err(read.Err());
|
|
111
|
+
return Result.Ok(collected);
|
|
112
|
+
}
|
|
113
|
+
export async function parseCandidateText(text, base) {
|
|
114
|
+
const blocks = await textToBlocks(text);
|
|
115
|
+
if (blocks.isErr())
|
|
116
|
+
return Result.Err(blocks.Err());
|
|
117
|
+
const accumulator = createBlockAccumulator();
|
|
118
|
+
const code = [];
|
|
119
|
+
for (const msg of blocks.Ok()) {
|
|
120
|
+
const closed = accumulator.ingest(msg);
|
|
121
|
+
if (closed !== undefined)
|
|
122
|
+
code.push({ begin: closed.begin, lines: [...closed.lines], end: closed.end });
|
|
123
|
+
}
|
|
124
|
+
const resolved = resolveCodeBlocks(code, base);
|
|
125
|
+
if (resolved.changedPaths.length === 0)
|
|
126
|
+
return Result.Err("the reply wrote no file");
|
|
127
|
+
const vfs = new Map();
|
|
128
|
+
for (const file of resolved.files) {
|
|
129
|
+
if (file.type === "code-block")
|
|
130
|
+
vfs.set(file.filename, file.content);
|
|
131
|
+
}
|
|
132
|
+
const observer = createStreamingResolver({ chatId: "instant", promptId: "instant", seed: base, onApplyError: ignoreApplyError });
|
|
133
|
+
const applyErrors = [];
|
|
134
|
+
for (const block of code) {
|
|
135
|
+
if (block.end === undefined || isCodeEnd(block.end) === false)
|
|
136
|
+
continue;
|
|
137
|
+
const applied = observer.observeBlock({ begin: block.begin, lines: block.lines, end: block.end });
|
|
138
|
+
for (const error of applied.errors) {
|
|
139
|
+
const near = error.searchPrefix === undefined ? "" : ` near "${error.searchPrefix}"`;
|
|
140
|
+
applyErrors.push(`${applied.path.replace(/^\/+/, "")}: a SEARCH/REPLACE edit did not apply (${error.reason})${near}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return Result.Ok({ vfs, changed: resolved.changedPaths, applyErrors });
|
|
144
|
+
}
|
|
145
|
+
function ignoreApplyError() {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
export function autofixAndCheck(args) {
|
|
149
|
+
const fixed = synthesizeImports({ vfs: args.vfs, paths: args.changed.filter((path) => args.vfs.has(path)), look: args.look });
|
|
150
|
+
const files = [...fixed.vfs].map(([filename, content]) => ({ type: "code-block", filename, lang: "jsx", content }));
|
|
151
|
+
const parse = saveRepairFindings(files, new Set(args.changed)).map((finding) => `${finding.path.replace(/^\/+/, "")}: ${finding.message}`);
|
|
152
|
+
const opens = checkOpens(fixed.vfs)
|
|
153
|
+
.findings.filter((finding) => OPENS_ADVISORY_CLASSES.has(finding.class) === false)
|
|
154
|
+
.map((finding) => `${finding.file.replace(/^\/+/, "")}:${finding.line}: ${finding.message}`);
|
|
155
|
+
const findings = [...parse, ...opens];
|
|
156
|
+
return { vfs: fixed.vfs, opens: findings.length === 0, findings, notes: fixed.notes };
|
|
157
|
+
}
|
|
158
|
+
const completionBody = lazyType(() => type({
|
|
159
|
+
"model?": "string",
|
|
160
|
+
choices: type({ message: { content: "string | null" }, "finish_reason?": "string | null" }).array(),
|
|
161
|
+
"usage?": {
|
|
162
|
+
"prompt_tokens?": "number >= 0",
|
|
163
|
+
"completion_tokens?": "number >= 0",
|
|
164
|
+
"total_tokens?": "number >= 0",
|
|
165
|
+
"cost?": "number >= 0",
|
|
166
|
+
},
|
|
167
|
+
}));
|
|
168
|
+
export function instantModelCallFor(vctx) {
|
|
169
|
+
return async function callInstantModel(req) {
|
|
170
|
+
const body = {
|
|
171
|
+
model: req.model.id,
|
|
172
|
+
stream: false,
|
|
173
|
+
max_tokens: INSTANT_MAX_OUTPUT_TOKENS,
|
|
174
|
+
reasoning: { ...req.model.reasoning },
|
|
175
|
+
messages: [...req.messages],
|
|
176
|
+
};
|
|
177
|
+
const rRes = await exception2Result(() => vctx.llmRequest({ ...body, headers: vctx.params.llm.headers }, { signal: req.signal }));
|
|
178
|
+
if (rRes.isErr())
|
|
179
|
+
return Result.Err(rRes.Err());
|
|
180
|
+
const res = rRes.Ok();
|
|
181
|
+
if (res.ok === false) {
|
|
182
|
+
await exception2Result(() => res.body?.cancel());
|
|
183
|
+
return Result.Err(`instant ${req.model.name}: status ${res.status}`);
|
|
184
|
+
}
|
|
185
|
+
const rJson = await exception2Result(() => res.json());
|
|
186
|
+
if (rJson.isErr())
|
|
187
|
+
return Result.Err(rJson.Err());
|
|
188
|
+
const parsed = completionBody(rJson.Ok());
|
|
189
|
+
if (parsed instanceof type.errors)
|
|
190
|
+
return Result.Err(`instant ${req.model.name}: reply: ${parsed.summary}`);
|
|
191
|
+
const content = parsed.choices[0]?.message.content;
|
|
192
|
+
if (content === undefined || content === null || content.trim().length === 0) {
|
|
193
|
+
return Result.Err(`instant ${req.model.name}: empty reply (finish ${parsed.choices[0]?.finish_reason ?? "unknown"})`);
|
|
194
|
+
}
|
|
195
|
+
const u = parsed.usage;
|
|
196
|
+
const servedModel = parsed.model ?? req.model.id;
|
|
197
|
+
return Result.Ok({
|
|
198
|
+
text: content,
|
|
199
|
+
servedModel,
|
|
200
|
+
...(u === undefined
|
|
201
|
+
? {}
|
|
202
|
+
: {
|
|
203
|
+
usage: {
|
|
204
|
+
prompt_tokens: u.prompt_tokens ?? 0,
|
|
205
|
+
completion_tokens: u.completion_tokens ?? 0,
|
|
206
|
+
total_tokens: u.total_tokens ?? (u.prompt_tokens ?? 0) + (u.completion_tokens ?? 0),
|
|
207
|
+
model: servedModel,
|
|
208
|
+
...(req.model.reasoningEffort === undefined ? {} : { reasoningEffort: req.model.reasoningEffort }),
|
|
209
|
+
...(u.cost === undefined ? {} : { cost: u.cost }),
|
|
210
|
+
},
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
async function callWithin(call, req, cancel) {
|
|
216
|
+
const abort = new AbortController();
|
|
217
|
+
const timer = setTimeout(function expire() {
|
|
218
|
+
abort.abort();
|
|
219
|
+
}, Math.max(1, req.timeoutMs));
|
|
220
|
+
function cancelled() {
|
|
221
|
+
abort.abort();
|
|
222
|
+
}
|
|
223
|
+
cancel.addEventListener("abort", cancelled, { once: true });
|
|
224
|
+
if (cancel.aborted)
|
|
225
|
+
abort.abort();
|
|
226
|
+
const reply = await Promise.resolve()
|
|
227
|
+
.then(function invoke() {
|
|
228
|
+
return call({ model: req.model, messages: req.messages, signal: abort.signal });
|
|
229
|
+
})
|
|
230
|
+
.then(function settle(r) {
|
|
231
|
+
return r;
|
|
232
|
+
}, function failed(e) {
|
|
233
|
+
return Result.Err(e instanceof Error ? e : new Error(String(e)));
|
|
234
|
+
})
|
|
235
|
+
.finally(function disarm() {
|
|
236
|
+
clearTimeout(timer);
|
|
237
|
+
cancel.removeEventListener("abort", cancelled);
|
|
238
|
+
});
|
|
239
|
+
if (cancel.aborted)
|
|
240
|
+
return { kind: "cancelled" };
|
|
241
|
+
if (abort.signal.aborted)
|
|
242
|
+
return { kind: "deadline" };
|
|
243
|
+
return { kind: "reply", reply };
|
|
244
|
+
}
|
|
245
|
+
function pauseUnlessCancelled(ms, cancel) {
|
|
246
|
+
return new Promise((resolve) => {
|
|
247
|
+
const timer = setTimeout(done, ms);
|
|
248
|
+
function done() {
|
|
249
|
+
clearTimeout(timer);
|
|
250
|
+
cancel.removeEventListener("abort", done);
|
|
251
|
+
resolve();
|
|
252
|
+
}
|
|
253
|
+
cancel.addEventListener("abort", done, { once: true });
|
|
254
|
+
if (cancel.aborted)
|
|
255
|
+
done();
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
export async function runInstantCandidate(args) {
|
|
259
|
+
const now = args.now ?? Date.now;
|
|
260
|
+
const maxAttempts = args.maxAttempts ?? INSTANT_MAX_ATTEMPTS;
|
|
261
|
+
const { model } = args.spec;
|
|
262
|
+
const usage = [];
|
|
263
|
+
const messages = [...args.spec.messages];
|
|
264
|
+
let attempts = 0;
|
|
265
|
+
let providerErrors = 0;
|
|
266
|
+
let firstFindings = [];
|
|
267
|
+
let lastError = "no attempt";
|
|
268
|
+
let current = args.base;
|
|
269
|
+
let changed = new Set();
|
|
270
|
+
function end(gate, extra) {
|
|
271
|
+
return {
|
|
272
|
+
name: model.name,
|
|
273
|
+
model: model.id,
|
|
274
|
+
gate,
|
|
275
|
+
attempts,
|
|
276
|
+
ms: now() - args.startedAt,
|
|
277
|
+
usage,
|
|
278
|
+
abortedInFlight: false,
|
|
279
|
+
findings: firstFindings,
|
|
280
|
+
...extra,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
for (;;) {
|
|
284
|
+
if (args.cancel.aborted)
|
|
285
|
+
return end("cancelled", {});
|
|
286
|
+
const left = args.deadlineAt - now();
|
|
287
|
+
if (left <= 0)
|
|
288
|
+
return end("fail", { error: `stage budget spent after ${attempts} call(s): ${lastError}` });
|
|
289
|
+
if (attempts >= maxAttempts)
|
|
290
|
+
return end("fail", { error: `${attempts} calls without a passing answer: ${lastError}` });
|
|
291
|
+
attempts++;
|
|
292
|
+
const answer = await callWithin(args.call, { model, messages, timeoutMs: Math.min(model.callMs, left) }, args.cancel);
|
|
293
|
+
if (answer.kind === "cancelled")
|
|
294
|
+
return end("cancelled", { abortedInFlight: true });
|
|
295
|
+
if (answer.kind === "deadline") {
|
|
296
|
+
lastError = `call ${attempts} passed its deadline`;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (answer.reply.isErr()) {
|
|
300
|
+
lastError = answer.reply.Err().message;
|
|
301
|
+
providerErrors++;
|
|
302
|
+
await pauseUnlessCancelled(Math.min(8_000, 1_000 * 2 ** (providerErrors - 1)), args.cancel);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
providerErrors = 0;
|
|
306
|
+
const reply = answer.reply.Ok();
|
|
307
|
+
if (reply.usage !== undefined)
|
|
308
|
+
usage.push(reply.usage);
|
|
309
|
+
const parsed = await parseCandidateText(reply.text, current);
|
|
310
|
+
if (parsed.isErr()) {
|
|
311
|
+
lastError = parsed.Err().message;
|
|
312
|
+
messages.push({ role: "assistant", content: [{ type: "text", text: reply.text }] });
|
|
313
|
+
messages.push({ role: "user", content: [{ type: "text", text: composeRepairAsk([`the reply: ${lastError}`]) }] });
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
changed = new Set([...changed, ...parsed.Ok().changed]);
|
|
317
|
+
const checked = autofixAndCheck({ vfs: parsed.Ok().vfs, changed: [...changed], look: args.look });
|
|
318
|
+
const gated = parsed.Ok().applyErrors.length === 0
|
|
319
|
+
? checked
|
|
320
|
+
: { ...checked, opens: false, findings: [...parsed.Ok().applyErrors, ...checked.findings] };
|
|
321
|
+
if (gated.opens) {
|
|
322
|
+
return end("pass", { vfs: gated.vfs, changed: [...changed] });
|
|
323
|
+
}
|
|
324
|
+
if (firstFindings.length === 0)
|
|
325
|
+
firstFindings = gated.findings.slice(0, 6);
|
|
326
|
+
lastError = gated.findings.slice(0, 3).join("; ");
|
|
327
|
+
current = gated.vfs;
|
|
328
|
+
messages.push({ role: "assistant", content: [{ type: "text", text: reply.text }] });
|
|
329
|
+
messages.push({ role: "user", content: [{ type: "text", text: composeRepairAsk(gated.findings) }] });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
export async function raceInstantCandidates(args) {
|
|
333
|
+
const now = args.now ?? Date.now;
|
|
334
|
+
const startedAt = now();
|
|
335
|
+
const deadlineAt = startedAt + args.budgetMs;
|
|
336
|
+
const cancel = new AbortController();
|
|
337
|
+
function turnAborted() {
|
|
338
|
+
cancel.abort();
|
|
339
|
+
}
|
|
340
|
+
args.turn?.addEventListener("abort", turnAborted, { once: true });
|
|
341
|
+
if (args.turn?.aborted === true)
|
|
342
|
+
cancel.abort();
|
|
343
|
+
let winner;
|
|
344
|
+
let winnerMs;
|
|
345
|
+
const runs = args.specs.map((spec) => args.run({ spec, cancel: cancel.signal, startedAt, deadlineAt }).then((outcome) => {
|
|
346
|
+
if (outcome.gate === "pass" && winner === undefined) {
|
|
347
|
+
winner = outcome;
|
|
348
|
+
winnerMs = now() - startedAt;
|
|
349
|
+
cancel.abort();
|
|
350
|
+
}
|
|
351
|
+
return outcome;
|
|
352
|
+
}));
|
|
353
|
+
const outcomes = await Promise.all(runs);
|
|
354
|
+
args.turn?.removeEventListener("abort", turnAborted);
|
|
355
|
+
const settled = outcomes.map((outcome) => outcome.gate === "pass" && outcome !== winner ? { ...outcome, gate: "cancelled" } : outcome);
|
|
356
|
+
return { ...(winner === undefined ? {} : { winner }), outcomes: settled, ms: winnerMs ?? now() - startedAt };
|
|
357
|
+
}
|
|
358
|
+
export function instantReceipt(race) {
|
|
359
|
+
return {
|
|
360
|
+
candidates: race.outcomes.map((outcome) => ({
|
|
361
|
+
model: outcome.model,
|
|
362
|
+
ms: outcome.ms,
|
|
363
|
+
gate: outcome.gate,
|
|
364
|
+
attempts: outcome.attempts,
|
|
365
|
+
...(outcome.abortedInFlight ? { abortedInFlight: true } : {}),
|
|
366
|
+
})),
|
|
367
|
+
...(race.winner === undefined ? {} : { winner: race.winner.model }),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
export function instantTurnText(race) {
|
|
371
|
+
const winner = race.winner;
|
|
372
|
+
if (winner === undefined || winner.vfs === undefined || winner.changed === undefined) {
|
|
373
|
+
const why = race.outcomes
|
|
374
|
+
.map((outcome) => `${outcome.name}: ${outcome.error ?? outcome.findings.slice(0, 2).join("; ")}`)
|
|
375
|
+
.join("\n");
|
|
376
|
+
return `The instant build wrote no files that open, so nothing was saved.\n\n${why}\n`;
|
|
377
|
+
}
|
|
378
|
+
const vfs = winner.vfs;
|
|
379
|
+
const files = new Map(winner.changed.flatMap((path) => {
|
|
380
|
+
const content = vfs.get(path);
|
|
381
|
+
return content === undefined ? [] : [[path, content]];
|
|
382
|
+
}));
|
|
383
|
+
return renderRepairFiles({ vfs: files, intro: "Here is the app." });
|
|
384
|
+
}
|
|
385
|
+
export function instantResponse(args) {
|
|
386
|
+
const model = args.race.winner?.model ?? INSTANT_HAIKU_MODEL;
|
|
387
|
+
function chunk(delta, finish, usage) {
|
|
388
|
+
return `data: ${JSON.stringify({
|
|
389
|
+
id: `instant-${args.promptId}`,
|
|
390
|
+
provider: "instant",
|
|
391
|
+
model,
|
|
392
|
+
object: "chat.completion.chunk",
|
|
393
|
+
created: Math.floor(Date.now() / 1000),
|
|
394
|
+
choices: [{ index: 0, delta, finish_reason: finish, native_finish_reason: finish }],
|
|
395
|
+
...(usage === undefined ? {} : { usage }),
|
|
396
|
+
})}\n\n`;
|
|
397
|
+
}
|
|
398
|
+
const rounds = args.race.outcomes.flatMap((outcome) => outcome.usage);
|
|
399
|
+
const body = [
|
|
400
|
+
chunk({ role: "assistant", content: instantTurnText(args.race) }, null),
|
|
401
|
+
...rounds.map((round) => chunk({}, null, round)),
|
|
402
|
+
chunk({}, "stop"),
|
|
403
|
+
"data: [DONE]\n\n",
|
|
404
|
+
].join("");
|
|
405
|
+
return new Response(body, { status: 200, headers: { "Content-Type": "text/event-stream" } });
|
|
406
|
+
}
|
|
407
|
+
function sourceFiles(vfs) {
|
|
408
|
+
return new Map([...vfs].filter(([path]) => path.startsWith("/~~") === false));
|
|
409
|
+
}
|
|
410
|
+
export function mercuryMessages(args) {
|
|
411
|
+
const files = sourceFiles(args.base);
|
|
412
|
+
const ask = files.size === 0 ? composeInstantBrief(args.instruction) : composeInstantEditAsk({ instruction: args.instruction, vfs: files });
|
|
413
|
+
return [
|
|
414
|
+
{ role: "system", content: [{ type: "text", text: args.system }] },
|
|
415
|
+
{ role: "user", content: [{ type: "text", text: ask }] },
|
|
416
|
+
];
|
|
417
|
+
}
|
|
418
|
+
export async function runInstantBuild(args) {
|
|
419
|
+
const { assembly } = args;
|
|
420
|
+
const specs = [
|
|
421
|
+
...(assembly.mercurySystem === undefined
|
|
422
|
+
? []
|
|
423
|
+
: [
|
|
424
|
+
{
|
|
425
|
+
model: instantModelChoice("mercury"),
|
|
426
|
+
messages: mercuryMessages({ system: assembly.mercurySystem, instruction: assembly.instruction, base: assembly.base }),
|
|
427
|
+
},
|
|
428
|
+
]),
|
|
429
|
+
{ model: instantModelChoice("haiku"), messages: args.haikuMessages },
|
|
430
|
+
];
|
|
431
|
+
const race = await raceInstantCandidates({
|
|
432
|
+
specs,
|
|
433
|
+
budgetMs: args.budgetMs ?? INSTANT_STAGE_BUDGET_MS,
|
|
434
|
+
turn: args.turn,
|
|
435
|
+
run: ({ spec, cancel, startedAt, deadlineAt }) => runInstantCandidate({ call: args.call, spec, base: assembly.base, look: assembly.look, cancel, startedAt, deadlineAt }),
|
|
436
|
+
});
|
|
437
|
+
return {
|
|
438
|
+
response: instantResponse({ race, promptId: args.promptId }),
|
|
439
|
+
receipt: instantReceipt(race),
|
|
440
|
+
model: race.winner?.model ?? INSTANT_HAIKU_MODEL,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
//# sourceMappingURL=instant-build.js.map
|