@vibes.diy/api-svc 14.0.9 → 14.0.11
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/create-handler.js +2 -0
- package/create-handler.js.map +1 -1
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/index.js.map +1 -1
- package/intern/agent-assembly.d.ts +1 -0
- package/intern/agent-assembly.js +22 -13
- package/intern/agent-assembly.js.map +1 -1
- package/intern/agent-belt.d.ts +2 -1
- package/intern/agent-belt.js +15 -1
- package/intern/agent-belt.js.map +1 -1
- package/intern/agent-build-tools.d.ts +6 -0
- package/intern/agent-build-tools.js +20 -1
- package/intern/agent-build-tools.js.map +1 -1
- package/intern/agent-dispatcher.d.ts +13 -0
- package/intern/agent-dispatcher.js +98 -2
- package/intern/agent-dispatcher.js.map +1 -1
- package/intern/agent-first-turn-eligible.d.ts +8 -0
- package/intern/agent-first-turn-eligible.js +12 -0
- package/intern/agent-first-turn-eligible.js.map +1 -0
- package/intern/agent-instruction.d.ts +1 -1
- package/intern/agent-instruction.js +23 -1
- package/intern/agent-instruction.js.map +1 -1
- package/intern/agent-lane-flag.d.ts +7 -0
- package/intern/agent-lane-flag.js +3 -0
- package/intern/agent-lane-flag.js.map +1 -1
- package/intern/agent-router.d.ts +1 -0
- package/intern/agent-router.js +1 -1
- package/intern/agent-router.js.map +1 -1
- package/intern/codegen-build-lock.d.ts +2 -0
- package/intern/codegen-build-lock.js +2 -0
- package/intern/codegen-build-lock.js.map +1 -1
- package/intern/ensure-chat-id.d.ts +3 -0
- package/intern/ensure-chat-id.js +37 -3
- package/intern/ensure-chat-id.js.map +1 -1
- package/intern/mint-fire-core.d.ts +10 -0
- package/intern/mint-fire-core.js +16 -2
- package/intern/mint-fire-core.js.map +1 -1
- package/intern/mint-job-store.d.ts +12 -1
- package/intern/mint-job-store.js +40 -5
- package/intern/mint-job-store.js.map +1 -1
- package/intern/open-turn-store.d.ts +60 -0
- package/intern/open-turn-store.js +134 -0
- package/intern/open-turn-store.js.map +1 -0
- package/intern/open-turn-sweep.d.ts +50 -0
- package/intern/open-turn-sweep.js +128 -0
- package/intern/open-turn-sweep.js.map +1 -0
- package/intern/persisted-block-seq.d.ts +19 -0
- package/intern/persisted-block-seq.js +28 -0
- package/intern/persisted-block-seq.js.map +1 -0
- package/package.json +11 -11
- package/public/llm-dispatch.js +16 -1
- package/public/llm-dispatch.js.map +1 -1
- package/public/open-chat.js +67 -2
- package/public/open-chat.js.map +1 -1
- package/public/prompt-chat-section.js +45 -11
- package/public/prompt-chat-section.js.map +1 -1
- package/public/shared-mint.d.ts +3 -0
- package/public/shared-mint.js +26 -3
- package/public/shared-mint.js.map +1 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { exception2Result, Result } from "@adviser/cement";
|
|
2
|
+
import { asCodegenTurnVariant } from "@vibes.diy/api-types";
|
|
3
|
+
import { and, asc, eq, lt, ne, or } from "drizzle-orm/sql/expressions";
|
|
4
|
+
import { OPEN_TURN_DEADLINE_MS } from "./codegen-build-lock.js";
|
|
5
|
+
const OPEN_TURN_STATUSES = ["open", "closed", "swept"];
|
|
6
|
+
const OPEN_TURN_KINDS = ["codegen", "first-build"];
|
|
7
|
+
export const OPEN_TURN_RETENTION_MS = 7 * 86_400_000;
|
|
8
|
+
export const OPEN_TURN_CLAIM_LIMIT = 200;
|
|
9
|
+
function toRow(raw) {
|
|
10
|
+
if (raw === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
const variant = asCodegenTurnVariant(raw.variant);
|
|
13
|
+
return {
|
|
14
|
+
chatId: raw.chatId,
|
|
15
|
+
promptId: raw.promptId,
|
|
16
|
+
userId: raw.userId,
|
|
17
|
+
ownerHandle: raw.ownerHandle,
|
|
18
|
+
appSlug: raw.appSlug,
|
|
19
|
+
kind: OPEN_TURN_KINDS.find((k) => k === raw.kind) ?? "codegen",
|
|
20
|
+
...(variant === undefined ? {} : { variant }),
|
|
21
|
+
status: OPEN_TURN_STATUSES.find((s) => s === raw.status) ?? "open",
|
|
22
|
+
startedAt: raw.startedAt,
|
|
23
|
+
deadlineAt: raw.deadlineAt,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export async function openTurn(sql, input, startedAtMs) {
|
|
27
|
+
const startedAt = new Date(startedAtMs ?? Date.now());
|
|
28
|
+
const nowIso = startedAt.toISOString();
|
|
29
|
+
const r = await exception2Result(() => sql.db
|
|
30
|
+
.insert(sql.tables.openTurns)
|
|
31
|
+
.values({
|
|
32
|
+
chatId: input.chatId,
|
|
33
|
+
promptId: input.promptId,
|
|
34
|
+
userId: input.userId,
|
|
35
|
+
ownerHandle: input.ownerHandle,
|
|
36
|
+
appSlug: input.appSlug,
|
|
37
|
+
kind: input.kind,
|
|
38
|
+
variant: input.variant ?? null,
|
|
39
|
+
status: "open",
|
|
40
|
+
startedAt: nowIso,
|
|
41
|
+
deadlineAt: new Date(startedAt.getTime() + OPEN_TURN_DEADLINE_MS).toISOString(),
|
|
42
|
+
closedAt: null,
|
|
43
|
+
created: nowIso,
|
|
44
|
+
updated: nowIso,
|
|
45
|
+
})
|
|
46
|
+
.onConflictDoNothing());
|
|
47
|
+
if (r.isErr())
|
|
48
|
+
return Result.Err(r);
|
|
49
|
+
return Result.Ok(undefined);
|
|
50
|
+
}
|
|
51
|
+
export function shouldCloseTurnRecord(args) {
|
|
52
|
+
return args.canonicalMode === "codegen" && args.terminalPersisted;
|
|
53
|
+
}
|
|
54
|
+
export async function closeTurn(sql, args, closedAtMs) {
|
|
55
|
+
const nowIso = new Date(closedAtMs ?? Date.now()).toISOString();
|
|
56
|
+
const r = await exception2Result(() => sql.db
|
|
57
|
+
.update(sql.tables.openTurns)
|
|
58
|
+
.set({ status: "closed", closedAt: nowIso, updated: nowIso })
|
|
59
|
+
.where(and(eq(sql.tables.openTurns.chatId, args.chatId), eq(sql.tables.openTurns.promptId, args.promptId), eq(sql.tables.openTurns.status, "open")))
|
|
60
|
+
.returning({ promptId: sql.tables.openTurns.promptId }));
|
|
61
|
+
if (r.isErr())
|
|
62
|
+
return Result.Err(r);
|
|
63
|
+
return Result.Ok(r.Ok().length > 0);
|
|
64
|
+
}
|
|
65
|
+
export async function reopenTurn(sql, args) {
|
|
66
|
+
return setTurnStatus(sql, args, { from: "swept", to: "open", clearClosedAt: true });
|
|
67
|
+
}
|
|
68
|
+
export async function closeSweptTurn(sql, args, closedAtMs) {
|
|
69
|
+
return setTurnStatus(sql, args, { from: "swept", to: "closed", closedAtMs });
|
|
70
|
+
}
|
|
71
|
+
async function setTurnStatus(sql, args, opts) {
|
|
72
|
+
const nowIso = new Date(opts.closedAtMs ?? Date.now()).toISOString();
|
|
73
|
+
const r = await exception2Result(() => sql.db
|
|
74
|
+
.update(sql.tables.openTurns)
|
|
75
|
+
.set({
|
|
76
|
+
status: opts.to,
|
|
77
|
+
updated: nowIso,
|
|
78
|
+
...(opts.clearClosedAt === true ? { closedAt: null } : { closedAt: nowIso }),
|
|
79
|
+
})
|
|
80
|
+
.where(and(eq(sql.tables.openTurns.chatId, args.chatId), eq(sql.tables.openTurns.promptId, args.promptId), eq(sql.tables.openTurns.status, opts.from)))
|
|
81
|
+
.returning({ promptId: sql.tables.openTurns.promptId }));
|
|
82
|
+
if (r.isErr())
|
|
83
|
+
return Result.Err(r);
|
|
84
|
+
return Result.Ok(r.Ok().length > 0);
|
|
85
|
+
}
|
|
86
|
+
export async function getOpenTurn(sql, args) {
|
|
87
|
+
const r = await exception2Result(() => sql.db
|
|
88
|
+
.select()
|
|
89
|
+
.from(sql.tables.openTurns)
|
|
90
|
+
.where(and(eq(sql.tables.openTurns.chatId, args.chatId), eq(sql.tables.openTurns.promptId, args.promptId)))
|
|
91
|
+
.limit(1));
|
|
92
|
+
if (r.isErr())
|
|
93
|
+
return Result.Err(r);
|
|
94
|
+
return Result.Ok(toRow(r.Ok()[0]));
|
|
95
|
+
}
|
|
96
|
+
export async function claimLostTurns(sql, args) {
|
|
97
|
+
const nowIso = new Date(args.nowMs).toISOString();
|
|
98
|
+
const limit = args.limit ?? OPEN_TURN_CLAIM_LIMIT;
|
|
99
|
+
function overdue(extra) {
|
|
100
|
+
return and(eq(sql.tables.openTurns.status, "open"), lt(sql.tables.openTurns.deadlineAt, nowIso), extra);
|
|
101
|
+
}
|
|
102
|
+
const rCandidates = await exception2Result(() => sql.db
|
|
103
|
+
.select({ chatId: sql.tables.openTurns.chatId, promptId: sql.tables.openTurns.promptId })
|
|
104
|
+
.from(sql.tables.openTurns)
|
|
105
|
+
.where(args.chatId === undefined ? overdue() : overdue(eq(sql.tables.openTurns.chatId, args.chatId)))
|
|
106
|
+
.orderBy(asc(sql.tables.openTurns.deadlineAt))
|
|
107
|
+
.limit(limit));
|
|
108
|
+
if (rCandidates.isErr())
|
|
109
|
+
return Result.Err(rCandidates);
|
|
110
|
+
const candidates = rCandidates.Ok();
|
|
111
|
+
if (candidates.length === 0)
|
|
112
|
+
return Result.Ok([]);
|
|
113
|
+
const keyed = or(...candidates.map((c) => and(eq(sql.tables.openTurns.chatId, c.chatId), eq(sql.tables.openTurns.promptId, c.promptId))));
|
|
114
|
+
const r = await exception2Result(() => sql.db
|
|
115
|
+
.update(sql.tables.openTurns)
|
|
116
|
+
.set({ status: "swept", closedAt: nowIso, updated: nowIso })
|
|
117
|
+
.where(overdue(keyed))
|
|
118
|
+
.returning());
|
|
119
|
+
if (r.isErr())
|
|
120
|
+
return Result.Err(r);
|
|
121
|
+
const rows = r.Ok().map((raw) => toRow(raw));
|
|
122
|
+
return Result.Ok(rows.filter((row) => row !== undefined));
|
|
123
|
+
}
|
|
124
|
+
export async function pruneClosedTurns(sql, nowMs) {
|
|
125
|
+
const cutoff = new Date(nowMs - OPEN_TURN_RETENTION_MS).toISOString();
|
|
126
|
+
const r = await exception2Result(() => sql.db
|
|
127
|
+
.delete(sql.tables.openTurns)
|
|
128
|
+
.where(and(ne(sql.tables.openTurns.status, "open"), lt(sql.tables.openTurns.updated, cutoff)))
|
|
129
|
+
.returning({ promptId: sql.tables.openTurns.promptId }));
|
|
130
|
+
if (r.isErr())
|
|
131
|
+
return Result.Err(r);
|
|
132
|
+
return Result.Ok(r.Ok().length);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=open-turn-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-turn-store.js","sourceRoot":"","sources":["../../jsr/intern/open-turn-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Result } from "@adviser/cement";
|
|
2
|
+
import { type PromptAndBlockMsgs } from "@vibes.diy/api-types";
|
|
3
|
+
import { type OpenTurnSql } from "./open-turn-store.js";
|
|
4
|
+
import { type PersistedBlockRow } from "./persisted-block-seq.js";
|
|
5
|
+
export declare const TURN_LOST_ERROR = "turn-lost: the server restarted mid-build";
|
|
6
|
+
export declare const TURN_LOST_CODE = "turn-lost";
|
|
7
|
+
export interface SweepLostTurnsArgs {
|
|
8
|
+
readonly nowMs: number;
|
|
9
|
+
readonly chatId?: string;
|
|
10
|
+
readonly limit?: number;
|
|
11
|
+
readonly deps?: SweepDeps;
|
|
12
|
+
}
|
|
13
|
+
export interface SweepTurnKey {
|
|
14
|
+
readonly chatId: string;
|
|
15
|
+
readonly promptId: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SweepDeps {
|
|
18
|
+
readonly readLastBlock: (key: SweepTurnKey) => Promise<Result<PersistedBlockRow | undefined>>;
|
|
19
|
+
readonly writeTerminal: (args: {
|
|
20
|
+
readonly key: SweepTurnKey;
|
|
21
|
+
readonly rows: readonly {
|
|
22
|
+
readonly blockSeq: number;
|
|
23
|
+
readonly blocks: readonly PromptAndBlockMsgs[];
|
|
24
|
+
}[];
|
|
25
|
+
readonly createdIso: string;
|
|
26
|
+
}) => Promise<Result<void>>;
|
|
27
|
+
readonly reopen: (key: SweepTurnKey) => Promise<Result<boolean>>;
|
|
28
|
+
readonly closeAlreadyEnded: (args: {
|
|
29
|
+
readonly key: SweepTurnKey;
|
|
30
|
+
readonly nowMs: number;
|
|
31
|
+
}) => Promise<Result<boolean>>;
|
|
32
|
+
readonly settleFirstBuild: (args: {
|
|
33
|
+
readonly chatId: string;
|
|
34
|
+
}) => Promise<Result<boolean>>;
|
|
35
|
+
}
|
|
36
|
+
export declare function defaultSweepDeps(sql: OpenTurnSql): SweepDeps;
|
|
37
|
+
export type SweepFailureStep = "read" | "write" | "reopen" | "close" | "settle-first-build";
|
|
38
|
+
export interface SweepFailure {
|
|
39
|
+
readonly chatId: string;
|
|
40
|
+
readonly promptId: string;
|
|
41
|
+
readonly step: SweepFailureStep;
|
|
42
|
+
readonly reason: Error;
|
|
43
|
+
}
|
|
44
|
+
export interface SweepLostTurnsResult {
|
|
45
|
+
readonly swept: number;
|
|
46
|
+
readonly collisions: number;
|
|
47
|
+
readonly alreadyEnded: number;
|
|
48
|
+
readonly failures: readonly SweepFailure[];
|
|
49
|
+
}
|
|
50
|
+
export declare function sweepLostTurns(sql: OpenTurnSql, args: SweepLostTurnsArgs): Promise<Result<SweepLostTurnsResult>>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { exception2Result, Result } from "@adviser/cement";
|
|
2
|
+
import { claimLostTurns, closeSweptTurn, reopenTurn } from "./open-turn-store.js";
|
|
3
|
+
import { blocksCarryTurnTerminal, lastPersistedBlock } from "./persisted-block-seq.js";
|
|
4
|
+
import { markMintJobSql } from "./mint-job-store.js";
|
|
5
|
+
export const TURN_LOST_ERROR = "turn-lost: the server restarted mid-build";
|
|
6
|
+
export const TURN_LOST_CODE = "turn-lost";
|
|
7
|
+
export function defaultSweepDeps(sql) {
|
|
8
|
+
return {
|
|
9
|
+
readLastBlock: (key) => lastPersistedBlock(sql, key),
|
|
10
|
+
writeTerminal: async (args) => {
|
|
11
|
+
const r = await exception2Result(() => sql.db.insert(sql.tables.chatSections).values(args.rows.map((row) => ({
|
|
12
|
+
chatId: args.key.chatId,
|
|
13
|
+
promptId: args.key.promptId,
|
|
14
|
+
blockSeq: row.blockSeq,
|
|
15
|
+
blocks: row.blocks,
|
|
16
|
+
created: args.createdIso,
|
|
17
|
+
}))));
|
|
18
|
+
if (r.isErr())
|
|
19
|
+
return Result.Err(r);
|
|
20
|
+
return Result.Ok(undefined);
|
|
21
|
+
},
|
|
22
|
+
reopen: (key) => reopenTurn(sql, key),
|
|
23
|
+
closeAlreadyEnded: (args) => closeSweptTurn(sql, args.key, args.nowMs),
|
|
24
|
+
settleFirstBuild: (args) => markMintJobSql(sql, args.chatId, {
|
|
25
|
+
status: "failed",
|
|
26
|
+
lastError: TURN_LOST_ERROR,
|
|
27
|
+
onlyFrom: ["pending", "parked", "retrying"],
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function isUniqueViolation(err) {
|
|
32
|
+
for (let cur = err, depth = 0; cur !== undefined && cur !== null && depth < 5; depth++) {
|
|
33
|
+
const code = cur.code;
|
|
34
|
+
if (code === "23505" || code === "SQLITE_CONSTRAINT_PRIMARYKEY" || code === "SQLITE_CONSTRAINT_UNIQUE")
|
|
35
|
+
return true;
|
|
36
|
+
const text = `${cur.message ?? String(cur)}`.toLowerCase();
|
|
37
|
+
if (text.includes("unique constraint") || text.includes("duplicate key"))
|
|
38
|
+
return true;
|
|
39
|
+
cur = cur.cause;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
export async function sweepLostTurns(sql, args) {
|
|
44
|
+
const deps = args.deps ?? defaultSweepDeps(sql);
|
|
45
|
+
const rClaim = await claimLostTurns(sql, {
|
|
46
|
+
nowMs: args.nowMs,
|
|
47
|
+
...(args.chatId === undefined ? {} : { chatId: args.chatId }),
|
|
48
|
+
...(args.limit === undefined ? {} : { limit: args.limit }),
|
|
49
|
+
});
|
|
50
|
+
if (rClaim.isErr())
|
|
51
|
+
return Result.Err(rClaim);
|
|
52
|
+
let swept = 0;
|
|
53
|
+
let collisions = 0;
|
|
54
|
+
let alreadyEnded = 0;
|
|
55
|
+
const failures = [];
|
|
56
|
+
async function handBack(key, step, reason) {
|
|
57
|
+
failures.push({ ...key, step, reason });
|
|
58
|
+
const rReopen = await deps.reopen(key);
|
|
59
|
+
if (rReopen.isErr()) {
|
|
60
|
+
failures.push({ ...key, step: "reopen", reason: rReopen.Err() });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const row of rClaim.Ok()) {
|
|
64
|
+
const now = new Date(args.nowMs);
|
|
65
|
+
const key = { chatId: row.chatId, promptId: row.promptId };
|
|
66
|
+
const rLast = await deps.readLastBlock(key);
|
|
67
|
+
if (rLast.isErr()) {
|
|
68
|
+
await handBack(key, "read", rLast.Err());
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const last = rLast.Ok();
|
|
72
|
+
if (last !== undefined && blocksCarryTurnTerminal(last.blocks)) {
|
|
73
|
+
const rClose = await deps.closeAlreadyEnded({ key, nowMs: args.nowMs });
|
|
74
|
+
if (rClose.isErr()) {
|
|
75
|
+
failures.push({ ...key, step: "close", reason: rClose.Err() });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
alreadyEnded += 1;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const base = last?.blockSeq ?? -1;
|
|
82
|
+
const errorSeq = base + 1;
|
|
83
|
+
const endSeq = base + 2;
|
|
84
|
+
const errorEvt = {
|
|
85
|
+
type: "prompt.error",
|
|
86
|
+
streamId: row.promptId,
|
|
87
|
+
chatId: row.chatId,
|
|
88
|
+
seq: errorSeq,
|
|
89
|
+
timestamp: now,
|
|
90
|
+
error: TURN_LOST_ERROR,
|
|
91
|
+
code: TURN_LOST_CODE,
|
|
92
|
+
...(row.variant === undefined ? {} : { variant: row.variant }),
|
|
93
|
+
};
|
|
94
|
+
const endEvt = {
|
|
95
|
+
type: "prompt.block-end",
|
|
96
|
+
streamId: row.promptId,
|
|
97
|
+
chatId: row.chatId,
|
|
98
|
+
seq: endSeq,
|
|
99
|
+
timestamp: now,
|
|
100
|
+
};
|
|
101
|
+
const rWrite = await deps.writeTerminal({
|
|
102
|
+
key,
|
|
103
|
+
rows: [
|
|
104
|
+
{ blockSeq: errorSeq, blocks: [errorEvt] },
|
|
105
|
+
{ blockSeq: endSeq, blocks: [endEvt] },
|
|
106
|
+
],
|
|
107
|
+
createdIso: now.toISOString(),
|
|
108
|
+
});
|
|
109
|
+
if (rWrite.isErr()) {
|
|
110
|
+
if (isUniqueViolation(rWrite.Err())) {
|
|
111
|
+
collisions += 1;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
await handBack(key, "write", rWrite.Err());
|
|
115
|
+
}
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
swept += 1;
|
|
119
|
+
if (row.kind === "first-build") {
|
|
120
|
+
const rSettle = await deps.settleFirstBuild({ chatId: row.chatId });
|
|
121
|
+
if (rSettle.isErr()) {
|
|
122
|
+
failures.push({ ...key, step: "settle-first-build", reason: rSettle.Err() });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return Result.Ok({ swept, collisions, alreadyEnded, failures });
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=open-turn-sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-turn-sweep.js","sourceRoot":"","sources":["../../jsr/intern/open-turn-sweep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Result } from "@adviser/cement";
|
|
2
|
+
import type { VibesApiTables, VibesSqlite } from "@vibes.diy/api-sql";
|
|
3
|
+
export interface PersistedBlockSql {
|
|
4
|
+
readonly db: VibesSqlite;
|
|
5
|
+
readonly tables: VibesApiTables;
|
|
6
|
+
}
|
|
7
|
+
export interface PersistedBlockRow {
|
|
8
|
+
readonly blockSeq: number;
|
|
9
|
+
readonly blocks: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function lastPersistedBlock(sql: PersistedBlockSql, args: {
|
|
12
|
+
chatId: string;
|
|
13
|
+
promptId: string;
|
|
14
|
+
}): Promise<Result<PersistedBlockRow | undefined>>;
|
|
15
|
+
export declare function maxPersistedBlockSeq(sql: PersistedBlockSql, args: {
|
|
16
|
+
chatId: string;
|
|
17
|
+
promptId: string;
|
|
18
|
+
}): Promise<Result<number | undefined>>;
|
|
19
|
+
export declare function blocksCarryTurnTerminal(blocks: unknown): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { exception2Result, Result } from "@adviser/cement";
|
|
2
|
+
import { RESEARCH_BLOCK_SEQ } from "@vibes.diy/api-types";
|
|
3
|
+
import { and, desc, eq, ne } from "drizzle-orm/sql/expressions";
|
|
4
|
+
export async function lastPersistedBlock(sql, args) {
|
|
5
|
+
const r = await exception2Result(() => sql.db
|
|
6
|
+
.select({ blockSeq: sql.tables.chatSections.blockSeq, blocks: sql.tables.chatSections.blocks })
|
|
7
|
+
.from(sql.tables.chatSections)
|
|
8
|
+
.where(and(eq(sql.tables.chatSections.chatId, args.chatId), eq(sql.tables.chatSections.promptId, args.promptId), ne(sql.tables.chatSections.blockSeq, RESEARCH_BLOCK_SEQ)))
|
|
9
|
+
.orderBy(desc(sql.tables.chatSections.blockSeq))
|
|
10
|
+
.limit(1));
|
|
11
|
+
if (r.isErr())
|
|
12
|
+
return Result.Err(r);
|
|
13
|
+
const row = r.Ok()[0];
|
|
14
|
+
return Result.Ok(row === undefined ? undefined : { blockSeq: row.blockSeq, blocks: row.blocks });
|
|
15
|
+
}
|
|
16
|
+
export async function maxPersistedBlockSeq(sql, args) {
|
|
17
|
+
const r = await lastPersistedBlock(sql, args);
|
|
18
|
+
if (r.isErr())
|
|
19
|
+
return Result.Err(r);
|
|
20
|
+
const row = r.Ok();
|
|
21
|
+
return Result.Ok(row === undefined ? undefined : row.blockSeq);
|
|
22
|
+
}
|
|
23
|
+
export function blocksCarryTurnTerminal(blocks) {
|
|
24
|
+
if (!Array.isArray(blocks))
|
|
25
|
+
return false;
|
|
26
|
+
return blocks.some((b) => typeof b === "object" && b !== null && b.type === "prompt.block-end");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=persisted-block-seq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persisted-block-seq.js","sourceRoot":"","sources":["../../jsr/intern/persisted-block-seq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAgChE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAsB,EACtB,IAA0C;IAE1C,MAAM,CAAC,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CACpC,GAAG,CAAC,EAAE;SACH,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;SAC9F,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC;SAC7B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAC/C,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,EACnD,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CACzD,CACF;SACA,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;SAC/C,KAAK,CAAC,CAAC,CAAC,CACZ,CAAC;IACF,IAAI,CAAC,CAAC,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AACnG,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAsB,EACtB,IAA0C;IAE1C,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;IACnB,OAAO,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACjE,CAAC;AAOD,MAAM,UAAU,uBAAuB,CAAC,MAAe;IACrD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAAwB,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;AAC1H,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/api-svc",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.11",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -30,18 +30,18 @@
|
|
|
30
30
|
"@libsql/client": "~0.17.4",
|
|
31
31
|
"@neondatabase/serverless": "~1.1.0",
|
|
32
32
|
"@noble/hashes": "~2.3.0",
|
|
33
|
-
"@vibes.diy/api-pkg": "14.0.
|
|
34
|
-
"@vibes.diy/api-sql": "14.0.
|
|
35
|
-
"@vibes.diy/api-types": "14.0.
|
|
36
|
-
"@vibes.diy/call-ai-v2": "14.0.
|
|
37
|
-
"@vibes.diy/identity": "14.0.
|
|
38
|
-
"@vibes.diy/prompts": "14.0.
|
|
39
|
-
"@vibes.diy/vibe-db-explorer": "14.0.
|
|
40
|
-
"@vibes.diy/vibe-runtime": "14.0.
|
|
41
|
-
"@vibes.diy/vibe-types": "14.0.
|
|
33
|
+
"@vibes.diy/api-pkg": "14.0.11",
|
|
34
|
+
"@vibes.diy/api-sql": "14.0.11",
|
|
35
|
+
"@vibes.diy/api-types": "14.0.11",
|
|
36
|
+
"@vibes.diy/call-ai-v2": "14.0.11",
|
|
37
|
+
"@vibes.diy/identity": "14.0.11",
|
|
38
|
+
"@vibes.diy/prompts": "14.0.11",
|
|
39
|
+
"@vibes.diy/vibe-db-explorer": "14.0.11",
|
|
40
|
+
"@vibes.diy/vibe-runtime": "14.0.11",
|
|
41
|
+
"@vibes.diy/vibe-types": "14.0.11",
|
|
42
42
|
"acorn": "~8.17.0",
|
|
43
43
|
"arktype": "~2.2.3",
|
|
44
|
-
"call-ai": "14.0.
|
|
44
|
+
"call-ai": "14.0.11",
|
|
45
45
|
"charwise": "~3.0.1",
|
|
46
46
|
"cookie": "~2.0.1",
|
|
47
47
|
"csv-parse": "~7.0.2",
|
package/public/llm-dispatch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Result, Option, exception2Result, chunkyAsync } from "@adviser/cement";
|
|
2
2
|
import { convertImageEvtToFileRef } from "./convert-image-evt.js";
|
|
3
|
-
import { isDraftOwnerHandle, isPromptFSStyle, buildUrlResearchJob, } from "@vibes.diy/api-types";
|
|
3
|
+
import { canonicalModelUsage, isDraftOwnerHandle, isPromptFSStyle, buildUrlResearchJob, } from "@vibes.diy/api-types";
|
|
4
4
|
import { type } from "arktype";
|
|
5
5
|
import { eq } from "drizzle-orm/sql/expressions";
|
|
6
6
|
import { publishApp } from "./publish-app.js";
|
|
@@ -20,6 +20,7 @@ import { activateUrlCandidates } from "../intern/url-activation.js";
|
|
|
20
20
|
import { reconcileResearchPointer } from "../intern/persist-url-research.js";
|
|
21
21
|
import { claimDraftState } from "../intern/draft-chat-store.js";
|
|
22
22
|
import { settleMintJobIfLive } from "../intern/mint-job-store.js";
|
|
23
|
+
import { openTurn } from "../intern/open-turn-store.js";
|
|
23
24
|
import { fanOutSectionToChat } from "../intern/section-fan-out.js";
|
|
24
25
|
import { delayForAttempt, extractEdgeError, extractProviderErrorFields, formatLlmAttemptFailures, isInvalidModelError, parseRetryAfterMs, pickDiagnosticHeaders, readFailureBody, waitMs, } from "./provider-errors.js";
|
|
25
26
|
const TRANSIENT_LLM_STATUSES = new Set([429, 502, 503, 504]);
|
|
@@ -823,6 +824,20 @@ export async function handlerLlmRequest({ scope, ctx, vctx, blockSeq, req, resCh
|
|
|
823
824
|
return r;
|
|
824
825
|
})
|
|
825
826
|
.do();
|
|
827
|
+
if (canonicalModelUsage(req.mode) === "codegen") {
|
|
828
|
+
const rOpen = await openTurn(vctx.sql, {
|
|
829
|
+
chatId: req.chatId,
|
|
830
|
+
promptId,
|
|
831
|
+
userId: req._auth.verifiedAuth.claims.userId,
|
|
832
|
+
ownerHandle: resChat.ownerHandle,
|
|
833
|
+
appSlug: resChat.appSlug,
|
|
834
|
+
kind: isInitialTurn ? "first-build" : "codegen",
|
|
835
|
+
...("variant" in req && req.variant !== undefined ? { variant: req.variant } : {}),
|
|
836
|
+
});
|
|
837
|
+
if (rOpen.isErr()) {
|
|
838
|
+
vctx.logger.Warn().Err(rOpen).Any("event", { chatId: req.chatId, promptId }).Msg("open-turn-record-failed");
|
|
839
|
+
}
|
|
840
|
+
}
|
|
826
841
|
if (req.mode === "codegen" && preAssembled !== undefined) {
|
|
827
842
|
const systemText = systemMessageText(preAssembled.messages);
|
|
828
843
|
if (systemText !== "") {
|