@vibes.diy/api-svc 14.3.83 → 14.3.84

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.
Files changed (57) hide show
  1. package/analytics.d.ts +1 -0
  2. package/analytics.js +1 -0
  3. package/analytics.js.map +1 -1
  4. package/index.d.ts +1 -0
  5. package/index.js +1 -0
  6. package/index.js.map +1 -1
  7. package/intern/agent-assembly.d.ts +5 -0
  8. package/intern/agent-assembly.js +14 -2
  9. package/intern/agent-assembly.js.map +1 -1
  10. package/intern/agent-belt.d.ts +5 -1
  11. package/intern/agent-belt.js +27 -8
  12. package/intern/agent-belt.js.map +1 -1
  13. package/intern/agent-build-tools.d.ts +3 -0
  14. package/intern/agent-build-tools.js.map +1 -1
  15. package/intern/agent-request-frame.d.ts +2 -0
  16. package/intern/agent-request-frame.js +2 -2
  17. package/intern/agent-request-frame.js.map +1 -1
  18. package/intern/agent-session-instruction.d.ts +4 -0
  19. package/intern/agent-session-instruction.js +4 -0
  20. package/intern/agent-session-instruction.js.map +1 -1
  21. package/intern/first-brief.d.ts +58 -0
  22. package/intern/first-brief.js +168 -0
  23. package/intern/first-brief.js.map +1 -0
  24. package/intern/first-build-classifier.d.ts +88 -0
  25. package/intern/first-build-classifier.js +241 -0
  26. package/intern/first-build-classifier.js.map +1 -0
  27. package/intern/instruction-variant.d.ts +29 -1
  28. package/intern/instruction-variant.js +107 -1
  29. package/intern/instruction-variant.js.map +1 -1
  30. package/intern/llm-tool-loop.d.ts +1 -0
  31. package/intern/llm-tool-loop.js +13 -0
  32. package/intern/llm-tool-loop.js.map +1 -1
  33. package/intern/prompt-step.d.ts +1 -1
  34. package/intern/prompt-step.js.map +1 -1
  35. package/intern/server-first-build.d.ts +25 -0
  36. package/intern/server-first-build.js +46 -0
  37. package/intern/server-first-build.js.map +1 -0
  38. package/intern/swr-wrapper-html-cache.js +1 -0
  39. package/intern/swr-wrapper-html-cache.js.map +1 -1
  40. package/intern/turn-latency.d.ts +3 -0
  41. package/intern/turn-latency.js +11 -0
  42. package/intern/turn-latency.js.map +1 -1
  43. package/package.json +13 -13
  44. package/public/agent-turn-action.d.ts +3 -2
  45. package/public/agent-turn-action.js +147 -32
  46. package/public/agent-turn-action.js.map +1 -1
  47. package/public/agent-turn-assembly.d.ts +3 -1
  48. package/public/agent-turn-assembly.js +18 -3
  49. package/public/agent-turn-assembly.js.map +1 -1
  50. package/public/prompt-chat-section.js +3 -0
  51. package/public/prompt-chat-section.js.map +1 -1
  52. package/public/prompt-section-actions.d.ts +2 -1
  53. package/public/prompt-section-actions.js +1 -0
  54. package/public/prompt-section-actions.js.map +1 -1
  55. package/public/prompt-turn-settled.js +3 -1
  56. package/public/prompt-turn-settled.js.map +1 -1
  57. package/public/prompt-turn-types.d.ts +2 -0
@@ -0,0 +1,58 @@
1
+ import { type Result } from "@adviser/cement";
2
+ import { type LLMMessage, type SseStreamMsg, type ToolDefinition } from "@vibes.diy/call-ai-v2";
3
+ import type { AgentEvidence } from "@vibes.diy/api-types";
4
+ import type { VibesApiSQLCtx } from "../types.js";
5
+ export type FirstBriefSkip = "no-create-call" | "create-refused";
6
+ export declare function firstBriefTurnEligible(t: {
7
+ readonly wakeTurn: boolean;
8
+ readonly topLevel: boolean;
9
+ readonly personWords: string;
10
+ readonly linkedUrls: number;
11
+ }): boolean;
12
+ export declare function firstBriefTools(definitions: readonly ToolDefinition[]): ToolDefinition[];
13
+ export declare function withFirstBriefLine(messages: readonly LLMMessage[], words: readonly string[]): LLMMessage[];
14
+ export declare function withSeededAddressWordsLine(messages: readonly LLMMessage[], words: readonly string[]): LLMMessage[];
15
+ export declare function withoutFirstBriefLine(messages: readonly LLMMessage[]): LLMMessage[];
16
+ export declare const FIRST_BRIEF_CONTINUE_NOTE = "[platform] Your reply above has reached the person, and every tool is yours again for the rest of this turn. Carry on from it as you would in any turn: finish with offer_options when options fit, and keep what you already said as said.";
17
+ export declare function withFirstBriefContinueNote(messages: readonly LLMMessage[]): LLMMessage[];
18
+ export interface FirstBriefUsage {
19
+ readonly prompt_tokens: number;
20
+ readonly completion_tokens: number;
21
+ readonly total_tokens: number;
22
+ readonly cost?: number;
23
+ }
24
+ export interface FirstBriefRound {
25
+ readonly servedModel?: string;
26
+ readonly called: boolean;
27
+ readonly elapsedMs: number;
28
+ readonly usage: readonly FirstBriefUsage[];
29
+ }
30
+ export declare function observeFirstBriefRound(stream: ReadableStream<SseStreamMsg>, o: {
31
+ readonly startedAt: number;
32
+ readonly now: () => number;
33
+ readonly onEnd: (round: FirstBriefRound) => Promise<void>;
34
+ }): ReadableStream<SseStreamMsg>;
35
+ export declare function recordFirstBriefRow(vctx: VibesApiSQLCtx, o: {
36
+ readonly chatId: string;
37
+ readonly userId: string;
38
+ readonly model: string;
39
+ readonly round: FirstBriefRound;
40
+ }): Promise<void>;
41
+ export type FirstBriefOutcome = {
42
+ readonly dispatched: true;
43
+ readonly appSlug: string;
44
+ readonly addressRetried?: true;
45
+ } | {
46
+ readonly dispatched: false;
47
+ readonly reason: FirstBriefSkip;
48
+ readonly refusal?: string;
49
+ readonly addressRetried?: true;
50
+ };
51
+ export declare function recordFirstBriefOutcome(vctx: VibesApiSQLCtx, o: {
52
+ readonly chatId: string;
53
+ readonly model: string;
54
+ readonly round: FirstBriefRound | undefined;
55
+ readonly outcome: FirstBriefOutcome;
56
+ readonly evidence: (e: AgentEvidence) => Promise<Result<void>>;
57
+ }): Promise<void>;
58
+ export declare function firstBriefOutcomeFromReceipt(text: string): FirstBriefOutcome;
@@ -0,0 +1,168 @@
1
+ import { exception2Result } from "@adviser/cement";
2
+ import { type } from "arktype";
3
+ import { isSseEnd, isSseLine, } from "@vibes.diy/call-ai-v2";
4
+ import { FIRST_BRIEF_ROUND_TAG, firstBriefRoundInstruction, SEEDED_ADDRESS_WORDS_TAG, seededAddressWordsInstruction, } from "./instruction-variant.js";
5
+ import { SERVER_FIRST_BUILD_EVIDENCE_NAME } from "./server-first-build.js";
6
+ const CREATE_VIBE = "create_vibe";
7
+ export function firstBriefTurnEligible(t) {
8
+ return t.wakeTurn === false && t.topLevel === false && t.personWords.length > 0 && t.linkedUrls === 0;
9
+ }
10
+ export function firstBriefTools(definitions) {
11
+ return definitions.filter((d) => d.function.name === CREATE_VIBE);
12
+ }
13
+ const ROUND_ONE_LINE_TAGS = [FIRST_BRIEF_ROUND_TAG, SEEDED_ADDRESS_WORDS_TAG];
14
+ function isRoundOneLine(part) {
15
+ return (typeof part === "object" &&
16
+ part !== null &&
17
+ part.type === "text" &&
18
+ typeof part.text === "string" &&
19
+ ROUND_ONE_LINE_TAGS.some((tag) => part.text.startsWith(tag)));
20
+ }
21
+ function withRoundOneLine(messages, text) {
22
+ let at = -1;
23
+ messages.forEach((m, i) => {
24
+ if (m.role === "system")
25
+ at = i;
26
+ });
27
+ if (at < 0)
28
+ return [...messages];
29
+ return messages.map((m, i) => {
30
+ if (i !== at || m.role !== "system" || Array.isArray(m.content) === false)
31
+ return m;
32
+ return { ...m, content: [...m.content, { type: "text", text }] };
33
+ });
34
+ }
35
+ export function withFirstBriefLine(messages, words) {
36
+ return withRoundOneLine(messages, firstBriefRoundInstruction(words));
37
+ }
38
+ export function withSeededAddressWordsLine(messages, words) {
39
+ return withRoundOneLine(messages, seededAddressWordsInstruction(words));
40
+ }
41
+ export function withoutFirstBriefLine(messages) {
42
+ return messages.map((m) => {
43
+ if (m.role !== "system" || Array.isArray(m.content) === false || m.content.some(isRoundOneLine) === false)
44
+ return m;
45
+ return { ...m, content: m.content.filter((part) => isRoundOneLine(part) === false) };
46
+ });
47
+ }
48
+ export const FIRST_BRIEF_CONTINUE_NOTE = "[platform] Your reply above has reached the person, and every tool is yours again for the rest of this turn. Carry on from it as you would in any turn: finish with offer_options when options fit, and keep what you already said as said.";
49
+ export function withFirstBriefContinueNote(messages) {
50
+ return [...messages, { role: "user", content: [{ type: "text", text: FIRST_BRIEF_CONTINUE_NOTE }] }];
51
+ }
52
+ const usageShape = type({ prompt_tokens: "number", completion_tokens: "number", total_tokens: "number", "cost?": "number" });
53
+ function readUsage(raw) {
54
+ const u = usageShape(raw);
55
+ if (u instanceof type.errors)
56
+ return undefined;
57
+ return {
58
+ prompt_tokens: u.prompt_tokens,
59
+ completion_tokens: u.completion_tokens,
60
+ total_tokens: u.total_tokens,
61
+ ...(u.cost === undefined ? {} : { cost: u.cost }),
62
+ };
63
+ }
64
+ export function observeFirstBriefRound(stream, o) {
65
+ let servedModel;
66
+ let ended = false;
67
+ const names = new Map();
68
+ return stream.pipeThrough(new TransformStream({
69
+ async transform(msg, controller) {
70
+ if (isSseLine(msg)) {
71
+ if (msg.chunk.model.length > 0)
72
+ servedModel = msg.chunk.model;
73
+ for (const choice of msg.chunk.choices) {
74
+ for (const delta of choice.delta.tool_calls ?? []) {
75
+ const name = delta.function?.name;
76
+ if (name !== undefined)
77
+ names.set(delta.index, (names.get(delta.index) ?? "") + name);
78
+ }
79
+ }
80
+ }
81
+ else if (isSseEnd(msg) && ended === false) {
82
+ ended = true;
83
+ await o.onEnd({
84
+ ...(servedModel === undefined ? {} : { servedModel }),
85
+ called: [...names.values()].includes(CREATE_VIBE),
86
+ elapsedMs: o.now() - o.startedAt,
87
+ usage: msg.usages.flatMap((u) => {
88
+ const read = readUsage(u);
89
+ return read === undefined ? [] : [read];
90
+ }),
91
+ });
92
+ }
93
+ controller.enqueue(msg);
94
+ },
95
+ }));
96
+ }
97
+ export async function recordFirstBriefRow(vctx, o) {
98
+ const zero = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
99
+ const rInsert = await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.promptContexts).values({
100
+ userId: o.userId,
101
+ chatId: o.chatId,
102
+ promptId: vctx.sthis.nextId(12).str,
103
+ nethash: vctx.netHash(),
104
+ promptTokens: 0,
105
+ completionTokens: 0,
106
+ totalTokens: 0,
107
+ ref: {
108
+ type: "prompt.usage.sql",
109
+ usage: { given: [], calculated: zero },
110
+ model: o.model,
111
+ step: "first-brief",
112
+ firstBrief: {
113
+ ...(o.round.servedModel === undefined ? {} : { servedModel: o.round.servedModel }),
114
+ called: o.round.called,
115
+ elapsedMs: o.round.elapsedMs,
116
+ usage: o.round.usage.map((u) => ({ ...u })),
117
+ },
118
+ },
119
+ created: new Date().toISOString(),
120
+ }));
121
+ if (rInsert.isErr()) {
122
+ vctx.logger.Warn().Err(rInsert).Str("chatId", o.chatId).Msg("first-brief-row-failed");
123
+ }
124
+ }
125
+ export async function recordFirstBriefOutcome(vctx, o) {
126
+ const brief = {
127
+ model: o.model,
128
+ ...(o.round?.servedModel === undefined ? {} : { servedModel: o.round.servedModel }),
129
+ ...(o.round === undefined ? {} : { called: o.round.called, elapsedMs: o.round.elapsedMs }),
130
+ };
131
+ const written = await o.evidence({
132
+ kind: "receipt",
133
+ name: SERVER_FIRST_BUILD_EVIDENCE_NAME,
134
+ text: JSON.stringify({ ...o.outcome, brief }),
135
+ });
136
+ if (written.isErr())
137
+ vctx.logger.Warn().Err(written).Str("chatId", o.chatId).Msg("first-brief-evidence-failed");
138
+ if (o.outcome.dispatched) {
139
+ vctx.logger
140
+ .Info()
141
+ .Any("event", {
142
+ chatId: o.chatId,
143
+ appSlug: o.outcome.appSlug,
144
+ ...(o.outcome.addressRetried === true ? { addressRetried: true } : {}),
145
+ briefMs: o.round?.elapsedMs,
146
+ servedModel: o.round?.servedModel,
147
+ })
148
+ .Msg("first-brief-dispatched");
149
+ }
150
+ else {
151
+ vctx.logger
152
+ .Warn()
153
+ .Any("event", { chatId: o.chatId, reason: o.outcome.reason, servedModel: o.round?.servedModel })
154
+ .Msg(o.outcome.reason === "no-create-call" ? "first-brief-no-create" : "first-brief-create-refused");
155
+ }
156
+ }
157
+ const createReceipt = type({ "ok?": "boolean", "appSlug?": "string", "reason?": "string" });
158
+ export function firstBriefOutcomeFromReceipt(text) {
159
+ const rJson = exception2Result(() => JSON.parse(text));
160
+ const body = rJson.isOk() ? createReceipt(rJson.Ok()) : undefined;
161
+ if (body === undefined || body instanceof type.errors)
162
+ return { dispatched: false, reason: "create-refused" };
163
+ if (body.ok === false || body.appSlug === undefined) {
164
+ return { dispatched: false, reason: "create-refused", ...(body.reason === undefined ? {} : { refusal: body.reason }) };
165
+ }
166
+ return { dispatched: true, appSlug: body.appSlug };
167
+ }
168
+ //# sourceMappingURL=first-brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-brief.js","sourceRoot":"","sources":["../../jsr/intern/first-brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { Result } from "@adviser/cement";
2
+ import { AppNature, type CreateVibeToolInput } from "@vibes.diy/api-types";
3
+ import type { VibesApiSQLCtx } from "../types.js";
4
+ export declare const FIRST_BUILD_CLASSIFIER_MODEL = "google/gemini-3.5-flash-lite";
5
+ export declare const FIRST_BUILD_CLASSIFIER_REASONING: {
6
+ readonly effort: "minimal";
7
+ };
8
+ export declare const FIRST_BUILD_CLASSIFIER_TIMEOUT_MS = 3000;
9
+ export declare const SERVER_FIRST_BUILD_ACCESS_SKILL = "access";
10
+ export declare function firstBuildSkillMenu(opts: {
11
+ readonly poufBlocks: boolean;
12
+ }): Promise<string>;
13
+ export declare function firstBuildClassifierMessage(personWords: string, skillMenu: string): string;
14
+ export declare const firstBuildClassifierSchema: {
15
+ readonly name: "first_build";
16
+ readonly required: readonly ["build", "skills", "pairs", "iconDescription", "nature", "noAccessControl"];
17
+ readonly properties: {
18
+ readonly build: {
19
+ readonly type: "boolean";
20
+ };
21
+ readonly skills: {
22
+ readonly type: "array";
23
+ readonly items: {
24
+ readonly type: "string";
25
+ };
26
+ };
27
+ readonly pairs: {
28
+ readonly type: "array";
29
+ readonly items: {
30
+ readonly type: "object";
31
+ readonly properties: {
32
+ readonly title: {
33
+ readonly type: "string";
34
+ };
35
+ readonly slug: {
36
+ readonly type: "string";
37
+ };
38
+ };
39
+ };
40
+ };
41
+ readonly iconDescription: {
42
+ readonly type: "string";
43
+ };
44
+ readonly nature: {
45
+ readonly type: "string";
46
+ readonly enum: readonly ["sensitive", "collaborative", "open"];
47
+ };
48
+ readonly noAccessControl: {
49
+ readonly type: "boolean";
50
+ };
51
+ };
52
+ };
53
+ export interface FirstBuildUsage {
54
+ readonly prompt_tokens: number;
55
+ readonly completion_tokens: number;
56
+ readonly total_tokens: number;
57
+ readonly cost?: number;
58
+ }
59
+ export interface FirstBuildVerdict {
60
+ readonly build: boolean;
61
+ readonly skills: readonly string[];
62
+ readonly pairs: readonly {
63
+ readonly title: string;
64
+ readonly slug: string;
65
+ }[];
66
+ readonly iconDescription?: string;
67
+ readonly nature?: AppNature;
68
+ readonly noAccessControl: boolean;
69
+ readonly model: string;
70
+ readonly usage?: FirstBuildUsage;
71
+ readonly elapsedMs: number;
72
+ }
73
+ export declare function parseFirstBuildVerdict(raw: unknown, meta: {
74
+ readonly model: string;
75
+ readonly usage?: FirstBuildUsage;
76
+ readonly elapsedMs: number;
77
+ }): Result<FirstBuildVerdict>;
78
+ export declare function serverFirstBuildBrief(personWords: string, o: {
79
+ readonly noAccessControl: boolean;
80
+ }): string;
81
+ export declare function createVibeInputFromVerdict(personWords: string, verdict: FirstBuildVerdict): CreateVibeToolInput;
82
+ export interface ClassifyFirstBuildArgs {
83
+ readonly chatId: string;
84
+ readonly userId: string;
85
+ readonly personWords: string;
86
+ readonly timeoutMs?: number;
87
+ }
88
+ export declare function classifyFirstBuild(vctx: VibesApiSQLCtx, args: ClassifyFirstBuildArgs): Promise<Result<FirstBuildVerdict>>;
@@ -0,0 +1,241 @@
1
+ import { Result, exception2Result } from "@adviser/cement";
2
+ import { callAI } from "call-ai";
3
+ import { type } from "arktype";
4
+ import { AppNature } from "@vibes.diy/api-types";
5
+ import { getLlmCatalog } from "@vibes.diy/prompts";
6
+ import { isPoufBlockSkill, poufLookFor } from "./pouf-look-flag.js";
7
+ import { GROUP_READY_SHAPE, INVITE_SCREEN_WHEN, KNOWN_VALUES_DIRECT_CONTROLS, SEED_DEMO_RULE, } from "./agent-session-instruction.js";
8
+ export const FIRST_BUILD_CLASSIFIER_MODEL = "google/gemini-3.5-flash-lite";
9
+ export const FIRST_BUILD_CLASSIFIER_REASONING = { effort: "minimal" };
10
+ export const FIRST_BUILD_CLASSIFIER_TIMEOUT_MS = 3_000;
11
+ const ALWAYS_PRESENT_SKILLS = new Set(["fireproof", "image-gen", "use-vibe", "use-viewer"]);
12
+ export const SERVER_FIRST_BUILD_ACCESS_SKILL = "access";
13
+ const SKILL_LINE_MAX_CHARS = 110;
14
+ function shortDescription(description) {
15
+ const flat = description.replace(/\s+/g, " ").trim();
16
+ if (flat.length <= SKILL_LINE_MAX_CHARS)
17
+ return flat;
18
+ const cut = flat.slice(0, SKILL_LINE_MAX_CHARS);
19
+ const space = cut.lastIndexOf(" ");
20
+ return `${space > 40 ? cut.slice(0, space) : cut}…`;
21
+ }
22
+ export async function firstBuildSkillMenu(opts) {
23
+ const catalog = await getLlmCatalog();
24
+ return catalog
25
+ .filter((c) => ALWAYS_PRESENT_SKILLS.has(c.name) === false && c.name !== SERVER_FIRST_BUILD_ACCESS_SKILL)
26
+ .filter((c) => opts.poufBlocks || isPoufBlockSkill(c.name) === false)
27
+ .map((c) => `- ${c.name}: ${shortDescription(c.description)}`)
28
+ .join("\n");
29
+ }
30
+ export function firstBuildClassifierMessage(personWords, skillMenu) {
31
+ return [
32
+ "Read one message a person sent to an app builder and fill the schema.",
33
+ "build: true when the message describes an app, tool, game, page, tracker or anything else to make — however short. " +
34
+ "build: false for a greeting, a question about the builder itself, or a message that names nothing to make.",
35
+ "skills: the names from the list below that the app needs, exactly as written; an empty list when none fit. " +
36
+ '"backend" for schedules, email, fetching, notifications and server work; ' +
37
+ '"callai" for record intake by sentence, a chat reply, a suggestion or any text the page asks the model for itself. ' +
38
+ "Access rules ride every build already.",
39
+ "noAccessControl: true only when the message itself asks for no access control, a single-user app or no sharing; false otherwise.",
40
+ "pairs: three title/slug pairs ranked by fit — a Title Case title of one to four words, and a kebab-case slug made from it.",
41
+ "iconDescription: one short line naming what the app's icon shows, such as 'a fox on a record player'.",
42
+ 'nature: "sensitive" for private record-keeping (a diary, health, money), "open" for a light toy anyone can play with, "collaborative" for everything else.',
43
+ "",
44
+ "Skills:",
45
+ skillMenu,
46
+ "",
47
+ "Message:",
48
+ personWords,
49
+ ].join("\n");
50
+ }
51
+ export const firstBuildClassifierSchema = {
52
+ name: "first_build",
53
+ required: ["build", "skills", "pairs", "iconDescription", "nature", "noAccessControl"],
54
+ properties: {
55
+ build: { type: "boolean" },
56
+ skills: { type: "array", items: { type: "string" } },
57
+ pairs: {
58
+ type: "array",
59
+ items: { type: "object", properties: { title: { type: "string" }, slug: { type: "string" } } },
60
+ },
61
+ iconDescription: { type: "string" },
62
+ nature: { type: "string", enum: ["sensitive", "collaborative", "open"] },
63
+ noAccessControl: { type: "boolean" },
64
+ },
65
+ };
66
+ const firstBuildParsed = type({
67
+ build: "boolean",
68
+ "skills?": "string[]",
69
+ "pairs?": type({ "title?": "string", "slug?": "string" }).array(),
70
+ "iconDescription?": "string",
71
+ "nature?": "string",
72
+ "noAccessControl?": "boolean",
73
+ });
74
+ export function parseFirstBuildVerdict(raw, meta) {
75
+ const parsed = firstBuildParsed(raw);
76
+ if (parsed instanceof type.errors)
77
+ return Result.Err(`first-build classifier: schema validation failed: ${parsed.summary}`);
78
+ const pairs = (parsed.pairs ?? []).flatMap((p) => {
79
+ const title = (p.title ?? "").trim();
80
+ const slug = (p.slug ?? "").trim();
81
+ return title.length > 0 && slug.length > 0 ? [{ title, slug }] : [];
82
+ });
83
+ const icon = (parsed.iconDescription ?? "").trim();
84
+ const nature = AppNature(parsed.nature);
85
+ return Result.Ok({
86
+ build: parsed.build,
87
+ skills: (parsed.skills ?? []).map((s) => s.trim()).filter((s) => s.length > 0),
88
+ pairs,
89
+ ...(icon.length === 0 ? {} : { iconDescription: icon }),
90
+ ...(nature instanceof type.errors ? {} : { nature }),
91
+ noAccessControl: parsed.noAccessControl === true,
92
+ model: meta.model,
93
+ ...(meta.usage === undefined ? {} : { usage: meta.usage }),
94
+ elapsedMs: meta.elapsedMs,
95
+ });
96
+ }
97
+ export function serverFirstBuildBrief(personWords, o) {
98
+ return [
99
+ ...(o.noAccessControl
100
+ ? []
101
+ : [
102
+ `This first build is group-ready: ${GROUP_READY_SHAPE}`,
103
+ `${INVITE_SCREEN_WHEN}; every other first build leaves it as an option for later.`,
104
+ ]),
105
+ `Sample content: ${SEED_DEMO_RULE}`,
106
+ KNOWN_VALUES_DIRECT_CONTROLS,
107
+ `The person asked: "${personWords}". Plan the app from their words.`,
108
+ ].join("\n");
109
+ }
110
+ function serverFirstBuildSkills(verdict) {
111
+ const picked = verdict.skills.filter((s) => s !== SERVER_FIRST_BUILD_ACCESS_SKILL);
112
+ if (verdict.noAccessControl)
113
+ return picked;
114
+ return verdict.skills.includes(SERVER_FIRST_BUILD_ACCESS_SKILL)
115
+ ? [...verdict.skills]
116
+ : [...picked, SERVER_FIRST_BUILD_ACCESS_SKILL];
117
+ }
118
+ export function createVibeInputFromVerdict(personWords, verdict) {
119
+ return {
120
+ prompt: personWords,
121
+ enrichedPrompt: serverFirstBuildBrief(personWords, { noAccessControl: verdict.noAccessControl }),
122
+ skills: serverFirstBuildSkills(verdict),
123
+ pairs: verdict.pairs.map((p) => ({ ...p })),
124
+ ...(verdict.iconDescription === undefined ? {} : { iconDescription: verdict.iconDescription }),
125
+ ...(verdict.nature === undefined ? {} : { nature: verdict.nature }),
126
+ };
127
+ }
128
+ function numberField(o, key) {
129
+ const v = o[key];
130
+ return typeof v === "number" && Number.isFinite(v) ? v : undefined;
131
+ }
132
+ function readEcho(json, echo) {
133
+ if (typeof json !== "object" || json === null)
134
+ return;
135
+ const body = json;
136
+ if (typeof body.model === "string")
137
+ echo.model = body.model;
138
+ const usage = body.usage;
139
+ if (typeof usage !== "object" || usage === null)
140
+ return;
141
+ const u = usage;
142
+ const prompt = numberField(u, "prompt_tokens");
143
+ const completion = numberField(u, "completion_tokens");
144
+ if (prompt === undefined || completion === undefined)
145
+ return;
146
+ const cost = numberField(u, "cost");
147
+ echo.usage = {
148
+ prompt_tokens: prompt,
149
+ completion_tokens: completion,
150
+ total_tokens: numberField(u, "total_tokens") ?? prompt + completion,
151
+ ...(cost === undefined ? {} : { cost }),
152
+ };
153
+ }
154
+ function classifierFetch(inner, signal, echo) {
155
+ return async (input, init) => {
156
+ const body = typeof init?.body === "string" ? init.body : undefined;
157
+ const rBody = body === undefined ? undefined : exception2Result(() => JSON.parse(body));
158
+ const patchedBody = rBody !== undefined && rBody.isOk()
159
+ ? JSON.stringify({ ...rBody.Ok(), reasoning: { ...FIRST_BUILD_CLASSIFIER_REASONING }, usage: { include: true } })
160
+ : body;
161
+ const res = await inner(input, { ...init, ...(patchedBody === undefined ? {} : { body: patchedBody }), signal });
162
+ const rJson = await exception2Result(() => res.clone().json());
163
+ if (rJson.isOk())
164
+ readEcho(rJson.Ok(), echo);
165
+ return res;
166
+ };
167
+ }
168
+ export async function classifyFirstBuild(vctx, args) {
169
+ return exception2Result(() => classify(vctx, args));
170
+ }
171
+ async function classify(vctx, args) {
172
+ if (args.personWords.trim().length === 0)
173
+ return Result.Err("first-build classifier: no words to classify");
174
+ if (vctx.billing.enforceEnabled) {
175
+ const rCheck = await vctx.billing.checkCredits({ userId: args.userId });
176
+ if (rCheck.isOk() && rCheck.Ok().allowed === false)
177
+ return Result.Err("first-build classifier: no credits remaining");
178
+ }
179
+ const message = firstBuildClassifierMessage(args.personWords, await firstBuildSkillMenu({ poufBlocks: poufLookFor(vctx, args.userId) }));
180
+ const timeoutMs = args.timeoutMs ?? FIRST_BUILD_CLASSIFIER_TIMEOUT_MS;
181
+ const controller = new AbortController();
182
+ const echo = {};
183
+ const startedAt = Date.now();
184
+ let timer;
185
+ const timeout = new Promise((_, reject) => {
186
+ timer = setTimeout(() => {
187
+ controller.abort();
188
+ reject(new Error(`first-build classifier timed out after ${timeoutMs}ms`));
189
+ }, timeoutMs);
190
+ });
191
+ const rCall = await exception2Result(() => Promise.race([
192
+ callAI(message, {
193
+ model: FIRST_BUILD_CLASSIFIER_MODEL,
194
+ endpoint: vctx.params.llm.url,
195
+ apiKey: vctx.params.llm.apiKey,
196
+ mock: { fetch: classifierFetch(vctx.inferenceFetch, controller.signal, echo) },
197
+ skipRetry: true,
198
+ schema: { ...firstBuildClassifierSchema, required: [...firstBuildClassifierSchema.required] },
199
+ }),
200
+ timeout,
201
+ ])).finally(() => clearTimeout(timer));
202
+ const elapsedMs = Date.now() - startedAt;
203
+ if (rCall.isErr())
204
+ return Result.Err(rCall);
205
+ const served = echo.model ?? FIRST_BUILD_CLASSIFIER_MODEL;
206
+ await recordFirstClassifyRow(vctx, { chatId: args.chatId, userId: args.userId, model: served, usage: echo.usage });
207
+ const raw = rCall.Ok();
208
+ if (typeof raw !== "string")
209
+ return Result.Err("first-build classifier: callAI returned non-string");
210
+ const rParsed = exception2Result(() => JSON.parse(raw));
211
+ if (rParsed.isErr())
212
+ return Result.Err(`first-build classifier: JSON parse failed: ${rParsed.Err().message}`);
213
+ return parseFirstBuildVerdict(rParsed.Ok(), {
214
+ model: served,
215
+ ...(echo.usage === undefined ? {} : { usage: echo.usage }),
216
+ elapsedMs,
217
+ });
218
+ }
219
+ async function recordFirstClassifyRow(vctx, o) {
220
+ const zero = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
221
+ const rInsert = await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.promptContexts).values({
222
+ userId: o.userId,
223
+ chatId: o.chatId,
224
+ promptId: vctx.sthis.nextId(12).str,
225
+ nethash: vctx.netHash(),
226
+ promptTokens: 0,
227
+ completionTokens: 0,
228
+ totalTokens: 0,
229
+ ref: {
230
+ type: "prompt.usage.sql",
231
+ usage: { given: o.usage === undefined ? [] : [{ ...o.usage, model: o.model }], calculated: zero },
232
+ model: o.model,
233
+ step: "first-classify",
234
+ },
235
+ created: new Date().toISOString(),
236
+ }));
237
+ if (rInsert.isErr()) {
238
+ vctx.logger.Warn().Err(rInsert).Str("chatId", o.chatId).Msg("first-build-classify-row-failed");
239
+ }
240
+ }
241
+ //# sourceMappingURL=first-build-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-build-classifier.js","sourceRoot":"","sources":["../../jsr/intern/first-build-classifier.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,37 @@
1
1
  import { Result } from "@adviser/cement";
2
2
  import type { VibesApiSQLCtx } from "../types.js";
3
- export declare const INSTRUCTION_VARIANTS: readonly ["direct-write"];
3
+ export declare const INSTRUCTION_VARIANTS: readonly ["direct-write", "pre-staged-reply", "fast-first-turn", "server-first-build", "fast-server-first-build", "fast-first-turn-full-brief", "opus-server-first-build", "seeded-address-words", "no-first-brief"];
4
4
  export type InstructionVariant = (typeof INSTRUCTION_VARIANTS)[number];
5
+ export declare function variantForTurn(variant: InstructionVariant | undefined, turn: {
6
+ readonly firstTurn: boolean;
7
+ }): InstructionVariant | undefined;
5
8
  export declare function admitInstructionVariant(requested: unknown, ownerHandle: string | undefined): Result<InstructionVariant | undefined>;
6
9
  export declare const DIRECT_WRITE_VARIANT_INSTRUCTION = "<direct-write-session>\nIn this conversation you write the app's code yourself. You are its builder as well as the person's\nguide, so every file the app has is one you wrote and committed, and each change reaches the app as\nyour own commit.\n\nA new app starts with create_vibe carrying codegen: false, together with the fields you always fill:\nprompt, pairs, iconDescription, skills and nature. It answers `created`: the app has its\naddress, name, icon and look, and its files are yours to write. Then write App.jsx with write_file \u2014\nthe complete, working app with every feature wired, following the builder brief below \u2014 and, in the\nsame pass, access.js with the app's record rules and backend.js when it needs server work. Run\nvalidate, fix what it reports and validate again until it comes back clean, then commit_version. Its\n[commit result] is the moment the app is saved, and the reply that says the app is ready follows it.\n\nThe record rules are part of your first pass: the group shape the base instruction describes is an\naccess.js you write beside App.jsx, with the can gates in App.jsx itself, and the invite screen there\ntoo when the ask names other people, sharing or a group. The\nfirst touch of access.js or backend.js hands you the guide index for that file; read the section\nyou need at its offset.\n\nA later change takes the same shape: read the files it touches, edit_file or write_file, validate\nuntil clean, commit_version, then answer from the [commit result]. A reshape, a new screen and a\none-word fix all travel this way. set_app_style still owns the app's look setting.\n\nThe <builder-brief> below is exactly what the platform's builder is taught about writing an app\nhere: the React rules, the house look and its tokens, and the Fireproof, callAI, ImgGen, useVibe\nand useViewer APIs. It is your reference for App.jsx. Where it describes emitting fenced code\nblocks, a title and a feature list, your equivalent is the write_file call; where it closes a\nturn with an improvement question, your own reply rules apply. Any other capability in the\ncatalog reads as /skills/<name>.md with read_file (for example /skills/three-js.md).\n</direct-write-session>";
10
+ export declare const PRE_STAGED_REPLY_VARIANT_INSTRUCTION = "<pre-staged-reply>\nOn this first build your reply comes in two parts, one on each side of the build.\n\nWhen create_vibe answers `building`, describe the app the person is about to open, in present\ntense and in the person's own terms, with a little room to explain: what the app is and who it is\nfor; its screens and the main things the person does on each; and its access rules in plain\nwords \u2014 who can see it, who can add or change things, and what someone opening a shared link\ngets. It describes the app itself; the build's arrival is the result's to announce. Then stop\nspeaking: the build owns the next step, and the options belong to the second part.\n\nWhen the [build result] arrives, the description is already on the person's screen, so the\nsecond part starts from what is new. When the result differs from the description \u2014 a field that\ncame out missing, an access rule that came out another way \u2014 say so in one sentence; when it\nmatches, go straight to the options. Then offer two or three concrete next features for this app\nas options, offered with offer_options as the turn's last call so they arrive as chips the person\ncan tap rather than as prose: each one something this app could do next that the person did not\nmention. The description stands as written: the second part carries no restatement of it and no line\nconfirming the app matches it.\n\nThe base rule holds across both parts: saved, done, ready, in and live belong to the second\npart, written after the result arrives.\n</pre-staged-reply>";
11
+ export declare const FAST_FIRST_TURN_AGENT_MODEL = "~anthropic/claude-sonnet-latest";
12
+ export declare const FAST_FIRST_TURN_REASONING: {
13
+ readonly effort: "none";
14
+ };
15
+ export interface FastFirstTurnLevers {
16
+ readonly model: string;
17
+ readonly reasoning: {
18
+ readonly effort: "none";
19
+ };
20
+ }
21
+ export declare function serverFirstBuildArmed(variant: InstructionVariant | undefined, firstTurn: boolean): boolean;
22
+ export declare function firstBriefArmed(variant: InstructionVariant | undefined, firstTurn: boolean, defaultOn: boolean): boolean;
23
+ export declare const AGENT_FIRST_BRIEF_ENV = "AGENT_FIRST_BRIEF";
24
+ export declare function agentFirstBriefEnabled(flag: string | undefined): boolean;
25
+ export declare const FIRST_BRIEF_ROUND_TAG = "<first-brief-round>";
26
+ export declare const FIRST_BRIEF_WORD_COUNT = 5;
27
+ export declare function addressWordsSentence(words: readonly string[]): string;
28
+ export declare function firstBriefRoundInstruction(words: readonly string[]): string;
29
+ export declare function seededAddressWordsArmed(variant: InstructionVariant | undefined, firstTurn: boolean): boolean;
30
+ export declare const SEEDED_ADDRESS_WORDS_TAG = "<seeded-address-words>";
31
+ export declare function seededAddressWordsInstruction(words: readonly string[]): string;
32
+ export declare function fastFirstTurnLevers(variant: InstructionVariant | undefined, firstTurn: boolean): FastFirstTurnLevers | undefined;
33
+ export declare const FAST_FIRST_TURN_VARIANT_INSTRUCTION = "<fast-first-turn>\nThis first turn moves quickly. The person's own sentence travels to the builder in full as\ncreate_vibe's prompt, so the brief you add stays short: enrichedPrompt is two or three sentences\nnaming the screens and the actions on them, and the builder reads the person's own words for the\nrest. The skills list carries the capability choices \u2014 name each capability the ask needs there.\nCall create_vibe as your first action, then tell the person in a sentence or two what is on its way.\n</fast-first-turn>";
34
+ export declare const FAST_FIRST_TURN_ENRICHED_PROMPT_DESCRIPTION: string;
7
35
  export declare function renderDirectWriteVariant(builderBrief: string): string;
8
36
  export declare function loadDirectWriteBuilderBrief(vctx: VibesApiSQLCtx, model: string, userId: string | undefined): Promise<Result<string>>;
9
37
  export declare function agentSystemContent(variantText?: string, extraText?: string): {