@vibes.diy/api-svc 14.3.103 → 14.3.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/intern/agent-session.d.ts +24 -24
- package/package.json +15 -14
- package/public/agent-turn-action.d.ts +1 -24
- package/public/agent-turn-action.js +6 -24
- package/public/agent-turn-action.js.map +1 -1
- package/public/handle-prompt-context.d.ts +1 -3
- package/public/handle-prompt-context.js +18 -23
- package/public/handle-prompt-context.js.map +1 -1
- package/public/stream-assembly.d.ts +2 -5
- package/public/stream-assembly.js +2 -4
- package/public/stream-assembly.js.map +1 -1
- package/usage-report/failed-turn-alert-util.d.ts +98 -0
- package/usage-report/failed-turn-alert-util.js +288 -0
- package/usage-report/failed-turn-alert-util.js.map +1 -0
- package/usage-report/failed-turn-alert.d.ts +1 -0
- package/usage-report/failed-turn-alert.js +64 -0
- package/usage-report/failed-turn-alert.js.map +1 -0
- package/intern/build-billing-outcome.d.ts +0 -12
- package/intern/build-billing-outcome.js +0 -9
- package/intern/build-billing-outcome.js.map +0 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { Result, exception2Result } from "@adviser/cement";
|
|
2
|
+
import { type } from "arktype";
|
|
3
|
+
const DISCORD_MARKUP_RE = /[\\`*_~|>#[\]()]/g;
|
|
4
|
+
export function sanitizeForDiscord(value) {
|
|
5
|
+
return value.replaceAll(DISCORD_MARKUP_RE, (c) => `\\${c}`);
|
|
6
|
+
}
|
|
7
|
+
export const FAILED_TURN_ALERT_ENV_VARS = [
|
|
8
|
+
"NEON_DATABASE_URL",
|
|
9
|
+
"DISCORD_WEBHOOK_URL",
|
|
10
|
+
"FAILED_TURN_ALERT_THRESHOLD",
|
|
11
|
+
"FAILED_TURN_ALERT_KNOWN_CATEGORIES",
|
|
12
|
+
];
|
|
13
|
+
export const DEFAULT_THRESHOLD = 10;
|
|
14
|
+
export const TOP_N = 5;
|
|
15
|
+
export const ROW_CAP = 50_000;
|
|
16
|
+
export const FAILED_TURN_CATEGORIES = [
|
|
17
|
+
"stream-incomplete",
|
|
18
|
+
"turn-lost",
|
|
19
|
+
"first-build-start",
|
|
20
|
+
"llm-request-failed",
|
|
21
|
+
"stale-file",
|
|
22
|
+
"other",
|
|
23
|
+
];
|
|
24
|
+
export const CATCH_ALL_CATEGORY = "other";
|
|
25
|
+
export const DEFAULT_KNOWN_CATEGORIES = [
|
|
26
|
+
"stream-incomplete",
|
|
27
|
+
"turn-lost",
|
|
28
|
+
"first-build-start",
|
|
29
|
+
"llm-request-failed",
|
|
30
|
+
"stale-file",
|
|
31
|
+
];
|
|
32
|
+
function num(raw, fallback) {
|
|
33
|
+
if (raw === undefined || raw.trim() === "")
|
|
34
|
+
return fallback;
|
|
35
|
+
const parsed = Number(raw);
|
|
36
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
37
|
+
}
|
|
38
|
+
export function resolveThresholds(env) {
|
|
39
|
+
const rawKnown = env.FAILED_TURN_ALERT_KNOWN_CATEGORIES;
|
|
40
|
+
const knownCategories = rawKnown === undefined || rawKnown.trim() === ""
|
|
41
|
+
? DEFAULT_KNOWN_CATEGORIES
|
|
42
|
+
: rawKnown
|
|
43
|
+
.split(",")
|
|
44
|
+
.map((s) => s.trim())
|
|
45
|
+
.filter((s) => s !== "" && s !== CATCH_ALL_CATEGORY);
|
|
46
|
+
return {
|
|
47
|
+
threshold: num(env.FAILED_TURN_ALERT_THRESHOLD, DEFAULT_THRESHOLD),
|
|
48
|
+
knownCategories,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function categorizeFailedTurn(error, code) {
|
|
52
|
+
if (code === "turn-lost" || error.includes("turn-lost"))
|
|
53
|
+
return "turn-lost";
|
|
54
|
+
if (error.includes("stream ended before completing"))
|
|
55
|
+
return "stream-incomplete";
|
|
56
|
+
if (error.includes("could not be started"))
|
|
57
|
+
return "first-build-start";
|
|
58
|
+
if (error.includes("LLM request failed"))
|
|
59
|
+
return "llm-request-failed";
|
|
60
|
+
if (error.startsWith("stale-file"))
|
|
61
|
+
return "stale-file";
|
|
62
|
+
return "other";
|
|
63
|
+
}
|
|
64
|
+
export function summarizeFailedTurns(rows, thresholds, skipped = 0) {
|
|
65
|
+
const byTurn = new Map();
|
|
66
|
+
for (const row of rows) {
|
|
67
|
+
const key = `${row.chatId}|${row.promptId}`;
|
|
68
|
+
if (!byTurn.has(key))
|
|
69
|
+
byTurn.set(key, row);
|
|
70
|
+
}
|
|
71
|
+
const turns = [...byTurn.values()];
|
|
72
|
+
const chats = new Set(turns.map((t) => t.chatId));
|
|
73
|
+
const perCategory = new Map();
|
|
74
|
+
for (const turn of turns) {
|
|
75
|
+
const category = categorizeFailedTurn(turn.error, turn.code);
|
|
76
|
+
const list = perCategory.get(category) ?? [];
|
|
77
|
+
list.push(turn);
|
|
78
|
+
perCategory.set(category, list);
|
|
79
|
+
}
|
|
80
|
+
const byCategory = [...perCategory.entries()]
|
|
81
|
+
.map(([category, list]) => ({
|
|
82
|
+
category,
|
|
83
|
+
turns: list.length,
|
|
84
|
+
chats: new Set(list.map((t) => t.chatId)).size,
|
|
85
|
+
sample: list.slice(0, TOP_N).map((t) => ({
|
|
86
|
+
chatId: t.chatId,
|
|
87
|
+
promptId: t.promptId,
|
|
88
|
+
ownerHandle: t.ownerHandle,
|
|
89
|
+
appSlug: t.appSlug,
|
|
90
|
+
})),
|
|
91
|
+
}))
|
|
92
|
+
.sort((a, b) => b.turns - a.turns);
|
|
93
|
+
const present = new Set(byCategory.map((c) => c.category));
|
|
94
|
+
const novelCategories = [...present].filter((c) => !thresholds.knownCategories.includes(c));
|
|
95
|
+
const tripped = [];
|
|
96
|
+
if (turns.length >= thresholds.threshold) {
|
|
97
|
+
tripped.push(`${turns.length} failed turns across ${chats.size} chats (threshold ${thresholds.threshold}).`);
|
|
98
|
+
}
|
|
99
|
+
for (const novel of novelCategories) {
|
|
100
|
+
const count = perCategory.get(novel)?.length ?? 0;
|
|
101
|
+
const turnsLabel = `${count} turn${count === 1 ? "" : "s"}`;
|
|
102
|
+
tripped.push(novel === CATCH_ALL_CATEGORY
|
|
103
|
+
? `unrecognized failures \`${novel}\` (${turnsLabel}) — triage, then give the understood shape its own category in failed-turn-alert-util.ts; \`other\` always alarms.`
|
|
104
|
+
: `new failure category \`${novel}\` (${turnsLabel}) — triage and add to FAILED_TURN_ALERT_KNOWN_CATEGORIES once understood.`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
failedTurns: turns.length,
|
|
108
|
+
failedChats: chats.size,
|
|
109
|
+
byCategory,
|
|
110
|
+
novelCategories,
|
|
111
|
+
tripped,
|
|
112
|
+
threshold: thresholds.threshold,
|
|
113
|
+
skipped,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const COLOR_TRIPPED = 15548997;
|
|
117
|
+
const COLOR_QUIET = 3447003;
|
|
118
|
+
const COLOR_DARK = 16776960;
|
|
119
|
+
export function vibeUrl(ownerHandle, appSlug) {
|
|
120
|
+
return `https://vibes.diy/vibe/${encodeURIComponent(ownerHandle)}/${encodeURIComponent(appSlug)}`;
|
|
121
|
+
}
|
|
122
|
+
const AUTOPSY_NOTE = `Autopsy per turn: \`ChatSections\` by \`chatId\` + \`promptId\` (agents/db-inspect.md § failed-codegen-turn autopsy).`;
|
|
123
|
+
export const DISCORD_CONTENT_CAP = 2000;
|
|
124
|
+
export const DISCORD_DESCRIPTION_CAP = 4096;
|
|
125
|
+
function categoryLines(summary) {
|
|
126
|
+
return summary.byCategory
|
|
127
|
+
.map((c) => `- \`${c.category}\`: ${c.turns} turn${c.turns === 1 ? "" : "s"} across ${c.chats} chat${c.chats === 1 ? "" : "s"}`)
|
|
128
|
+
.join("\n");
|
|
129
|
+
}
|
|
130
|
+
function sampleLine(category, s) {
|
|
131
|
+
const where = s.ownerHandle !== "" && s.appSlug !== "" ? ` ${vibeUrl(s.ownerHandle, s.appSlug)}` : "";
|
|
132
|
+
return `- \`${sanitizeForDiscord(category)}\` chat \`${sanitizeForDiscord(s.chatId)}\` turn \`${sanitizeForDiscord(s.promptId)}\`${where}`;
|
|
133
|
+
}
|
|
134
|
+
function allSampleLines(summary) {
|
|
135
|
+
const lines = [];
|
|
136
|
+
for (const c of summary.byCategory) {
|
|
137
|
+
for (const s of c.sample)
|
|
138
|
+
lines.push(sampleLine(c.category, s));
|
|
139
|
+
}
|
|
140
|
+
return lines;
|
|
141
|
+
}
|
|
142
|
+
export function fitSampleSection(allSamples, fixedChars) {
|
|
143
|
+
const omissionPrefix = "- …(";
|
|
144
|
+
const omissionSuffix = " more samples omitted)";
|
|
145
|
+
const room = DISCORD_DESCRIPTION_CAP - fixedChars - 1;
|
|
146
|
+
const joined = allSamples.join("\n");
|
|
147
|
+
if (joined.length <= room)
|
|
148
|
+
return joined;
|
|
149
|
+
const kept = [];
|
|
150
|
+
let used = 0;
|
|
151
|
+
for (const line of allSamples) {
|
|
152
|
+
const omitted = allSamples.length - kept.length;
|
|
153
|
+
const omissionLen = `\n${omissionPrefix}${omitted}${omissionSuffix}`.length;
|
|
154
|
+
if (used + line.length + 1 + omissionLen > room)
|
|
155
|
+
break;
|
|
156
|
+
kept.push(line);
|
|
157
|
+
used += line.length + 1;
|
|
158
|
+
}
|
|
159
|
+
const omitted = allSamples.length - kept.length;
|
|
160
|
+
return [...kept, `${omissionPrefix}${omitted}${omissionSuffix}`].join("\n");
|
|
161
|
+
}
|
|
162
|
+
function embed(title, description, color, content) {
|
|
163
|
+
return {
|
|
164
|
+
content: truncateTo(content, DISCORD_CONTENT_CAP),
|
|
165
|
+
allowed_mentions: { parse: [] },
|
|
166
|
+
embeds: [{ title, description: truncateTo(description, DISCORD_DESCRIPTION_CAP), color }],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function truncateTo(text, cap) {
|
|
170
|
+
if (text.length <= cap)
|
|
171
|
+
return text;
|
|
172
|
+
const ellipsis = "\n…(truncated)";
|
|
173
|
+
return text.slice(0, Math.max(0, cap - ellipsis.length)) + ellipsis;
|
|
174
|
+
}
|
|
175
|
+
export function buildFailedTurnEmbed(input) {
|
|
176
|
+
const s = input.summary;
|
|
177
|
+
const { sinceHours } = input;
|
|
178
|
+
const title = `Failed codegen turns (last ${sinceHours}h)`;
|
|
179
|
+
const skippedNote = s.skipped > 0 ? `⚠️ ${s.skipped} malformed row${s.skipped === 1 ? "" : "s"} omitted — counts below are partial.` : "";
|
|
180
|
+
if (input.capped === true) {
|
|
181
|
+
const description = [
|
|
182
|
+
`The ChatSections read was truncated at the ${ROW_CAP}-row cap, so every count below is a floor, not a total.`,
|
|
183
|
+
...(skippedNote !== "" ? [skippedNote] : []),
|
|
184
|
+
``,
|
|
185
|
+
categoryLines(s),
|
|
186
|
+
``,
|
|
187
|
+
AUTOPSY_NOTE,
|
|
188
|
+
].join("\n");
|
|
189
|
+
return embed(title, description, COLOR_DARK, `Failed turns: the read hit its row cap — counts are a floor this run`);
|
|
190
|
+
}
|
|
191
|
+
if (s.failedTurns === 0) {
|
|
192
|
+
if (s.skipped > 0) {
|
|
193
|
+
const description = [
|
|
194
|
+
`${s.skipped} row${s.skipped === 1 ? " was" : "s were"} read but none decoded into a failed turn — the table shape may have changed since this query was written. Nothing below covers the window.`,
|
|
195
|
+
``,
|
|
196
|
+
AUTOPSY_NOTE,
|
|
197
|
+
].join("\n");
|
|
198
|
+
return embed(title, description, COLOR_DARK, `Failed turns: ${s.skipped} row${s.skipped === 1 ? " was" : "s were"} read but none usable in the last ${sinceHours}h (counts unknown)`);
|
|
199
|
+
}
|
|
200
|
+
const description = [
|
|
201
|
+
`No \`prompt.error\` rows in \`ChatSections\` this window. Capture status unknown from this query alone: a clean day and a stopped capture look identical here.`,
|
|
202
|
+
``,
|
|
203
|
+
AUTOPSY_NOTE,
|
|
204
|
+
].join("\n");
|
|
205
|
+
return embed(title, description, COLOR_DARK, `Failed turns: no prompt.error rows in the last ${sinceHours}h (capture status unknown)`);
|
|
206
|
+
}
|
|
207
|
+
const tripped = s.tripped.length > 0;
|
|
208
|
+
const headerLines = [...s.tripped.map((t) => sanitizeForDiscord(t)), ...(skippedNote !== "" ? [skippedNote] : [])];
|
|
209
|
+
const header = headerLines.length > 0 ? [...headerLines, ``] : [];
|
|
210
|
+
const fixed = [...header, categoryLines(s), ``, ``, AUTOPSY_NOTE].join("\n");
|
|
211
|
+
const samples = fitSampleSection(allSampleLines(s), fixed.length);
|
|
212
|
+
const description = [...header, categoryLines(s), ``, samples, ``, AUTOPSY_NOTE].join("\n");
|
|
213
|
+
const partialSuffix = s.skipped > 0 ? ` (partial data: ${s.skipped} row${s.skipped === 1 ? "" : "s"} omitted)` : "";
|
|
214
|
+
const content = tripped || s.skipped > 0
|
|
215
|
+
? `Failed turns: ${s.failedTurns} across ${s.failedChats} chats in the last ${sinceHours}h${partialSuffix}`
|
|
216
|
+
: `Failed turns: ${s.failedTurns} across ${s.failedChats} chats in the last ${sinceHours}h — below threshold, nothing new`;
|
|
217
|
+
return embed(title, description, tripped ? COLOR_TRIPPED : COLOR_QUIET, content);
|
|
218
|
+
}
|
|
219
|
+
export async function postToDiscord(webhookUrl, body, fetchFn = fetch) {
|
|
220
|
+
const res = await exception2Result(() => fetchFn(webhookUrl, {
|
|
221
|
+
method: "POST",
|
|
222
|
+
headers: { "Content-Type": "application/json" },
|
|
223
|
+
body: JSON.stringify(body),
|
|
224
|
+
}));
|
|
225
|
+
if (res.isErr())
|
|
226
|
+
return Result.Err(new Error("discord delivery failed: transport error"));
|
|
227
|
+
if (res.Ok().status !== 204)
|
|
228
|
+
return Result.Err(new Error(`discord delivery failed: status ${res.Ok().status}`));
|
|
229
|
+
return Result.Ok(undefined);
|
|
230
|
+
}
|
|
231
|
+
const FailedTurnRowWire = type({
|
|
232
|
+
chatId: "string",
|
|
233
|
+
promptId: "string",
|
|
234
|
+
error: "string",
|
|
235
|
+
"code?": "string | null | undefined",
|
|
236
|
+
"created?": "string | null | undefined",
|
|
237
|
+
"ownerHandle?": "string | null | undefined",
|
|
238
|
+
"appSlug?": "string | null | undefined",
|
|
239
|
+
});
|
|
240
|
+
export function decodeFailedTurnRow(row) {
|
|
241
|
+
const parsed = FailedTurnRowWire(row);
|
|
242
|
+
if (parsed instanceof type.errors)
|
|
243
|
+
return Result.Err(new Error(parsed.summary));
|
|
244
|
+
if (parsed.chatId === "" || parsed.promptId === "") {
|
|
245
|
+
return Result.Err(new Error("failed-turn row has an empty chatId or promptId"));
|
|
246
|
+
}
|
|
247
|
+
return Result.Ok({
|
|
248
|
+
chatId: parsed.chatId,
|
|
249
|
+
promptId: parsed.promptId,
|
|
250
|
+
error: parsed.error,
|
|
251
|
+
code: parsed.code ?? "",
|
|
252
|
+
created: parsed.created ?? "",
|
|
253
|
+
ownerHandle: parsed.ownerHandle ?? "",
|
|
254
|
+
appSlug: parsed.appSlug ?? "",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
export function decodeFailedTurnRows(rows) {
|
|
258
|
+
const kept = [];
|
|
259
|
+
let skipped = 0;
|
|
260
|
+
for (const row of rows) {
|
|
261
|
+
const decoded = decodeFailedTurnRow(row);
|
|
262
|
+
if (decoded.isErr())
|
|
263
|
+
skipped += 1;
|
|
264
|
+
else
|
|
265
|
+
kept.push(decoded.Ok());
|
|
266
|
+
}
|
|
267
|
+
return { rows: kept, skipped };
|
|
268
|
+
}
|
|
269
|
+
export async function executeFailedTurnAlert(deps) {
|
|
270
|
+
const nowMs = deps.nowMs ?? Date.now();
|
|
271
|
+
const sinceIso = new Date(nowMs - deps.sinceHours * 3600_000).toISOString();
|
|
272
|
+
const queried = await exception2Result(() => deps.query(sinceIso));
|
|
273
|
+
if (queried.isErr())
|
|
274
|
+
return Result.Err(queried);
|
|
275
|
+
const { rows, skipped } = decodeFailedTurnRows(queried.Ok().rows);
|
|
276
|
+
const summary = summarizeFailedTurns(rows, deps.thresholds, skipped);
|
|
277
|
+
const body = buildFailedTurnEmbed({ summary, sinceHours: deps.sinceHours, capped: queried.Ok().capped });
|
|
278
|
+
if (deps.explicitDryRun)
|
|
279
|
+
return Result.Ok({ summary, body, posted: false, skipped, capped: queried.Ok().capped });
|
|
280
|
+
if (deps.webhookUrl === undefined || deps.webhookUrl === "") {
|
|
281
|
+
return Result.Err(new Error("DISCORD_WEBHOOK_URL is required — nothing was posted (pass --dry-run to print instead)"));
|
|
282
|
+
}
|
|
283
|
+
const posted = await deps.post(body);
|
|
284
|
+
if (posted.isErr())
|
|
285
|
+
return Result.Err(posted);
|
|
286
|
+
return Result.Ok({ summary, body, posted: true, skipped, capped: queried.Ok().capped });
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=failed-turn-alert-util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failed-turn-alert-util.js","sourceRoot":"","sources":["../../jsr/usage-report/failed-turn-alert-util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Pool } from "@neondatabase/serverless";
|
|
2
|
+
import { Result } from "@adviser/cement";
|
|
3
|
+
import { arg, flag, formatError, loadDevVars } from "./usage-report-util.js";
|
|
4
|
+
import { ROW_CAP, executeFailedTurnAlert, postToDiscord, resolveThresholds } from "./failed-turn-alert-util.js";
|
|
5
|
+
const DEFAULT_SINCE_HOURS = 24;
|
|
6
|
+
async function run() {
|
|
7
|
+
loadDevVars();
|
|
8
|
+
const sinceHours = Number(arg("--since-hours") ?? DEFAULT_SINCE_HOURS);
|
|
9
|
+
if (!Number.isFinite(sinceHours) || sinceHours <= 0) {
|
|
10
|
+
return Result.Err("usage: pnpm --dir vibes.diy/api/svc run failed-turn-alert [--since-hours 24] [--dry-run]");
|
|
11
|
+
}
|
|
12
|
+
const connectionString = process.env["NEON_DATABASE_URL"];
|
|
13
|
+
if (connectionString === undefined)
|
|
14
|
+
return Result.Err("NEON_DATABASE_URL is required (prod Neon)");
|
|
15
|
+
const webhookUrl = process.env["DISCORD_WEBHOOK_URL"];
|
|
16
|
+
const thresholds = resolveThresholds({
|
|
17
|
+
FAILED_TURN_ALERT_THRESHOLD: process.env["FAILED_TURN_ALERT_THRESHOLD"],
|
|
18
|
+
FAILED_TURN_ALERT_KNOWN_CATEGORIES: process.env["FAILED_TURN_ALERT_KNOWN_CATEGORIES"],
|
|
19
|
+
});
|
|
20
|
+
const dryRun = flag("--dry-run");
|
|
21
|
+
const pool = new Pool({ connectionString });
|
|
22
|
+
const result = await executeFailedTurnAlert({
|
|
23
|
+
sinceHours,
|
|
24
|
+
thresholds,
|
|
25
|
+
explicitDryRun: dryRun,
|
|
26
|
+
webhookUrl,
|
|
27
|
+
query: async (sinceIso) => {
|
|
28
|
+
const res = await pool.query(`select s."chatId", s."promptId",
|
|
29
|
+
min(b->>'error') as error,
|
|
30
|
+
min(coalesce(b->>'code', '')) as code,
|
|
31
|
+
min(s.created) as created,
|
|
32
|
+
min(c."userSlug") as "ownerHandle",
|
|
33
|
+
min(c."appSlug") as "appSlug"
|
|
34
|
+
from "ChatSections" s
|
|
35
|
+
left join "ChatContexts" c on c."chatId" = s."chatId",
|
|
36
|
+
lateral jsonb_array_elements(s.blocks) as b
|
|
37
|
+
where s.created >= $1 and b->>'type' = 'prompt.error'
|
|
38
|
+
group by s."chatId", s."promptId"
|
|
39
|
+
order by min(s.created) desc limit ${ROW_CAP}`, [sinceIso]);
|
|
40
|
+
return { rows: res.rows, capped: res.rows.length === ROW_CAP };
|
|
41
|
+
},
|
|
42
|
+
post: (body) => {
|
|
43
|
+
if (webhookUrl === undefined || webhookUrl === "") {
|
|
44
|
+
return Promise.resolve(Result.Err(new Error("DISCORD_WEBHOOK_URL is required — nothing was posted")));
|
|
45
|
+
}
|
|
46
|
+
return postToDiscord(webhookUrl, body);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
await pool.end();
|
|
50
|
+
if (result.isErr())
|
|
51
|
+
return result;
|
|
52
|
+
const outcome = result.Ok();
|
|
53
|
+
console.log(`[failed-turn-alert] window=${sinceHours}h failedTurns=${outcome.summary.failedTurns} chats=${outcome.summary.failedChats} signals=${outcome.summary.tripped.length} skipped=${outcome.skipped} capped=${outcome.capped} posted=${outcome.posted}`);
|
|
54
|
+
if (dryRun)
|
|
55
|
+
console.log(JSON.stringify(outcome.body, null, 2));
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
run().then((result) => {
|
|
59
|
+
if (result.isErr()) {
|
|
60
|
+
console.error(formatError(result.Err()));
|
|
61
|
+
process.exitCode = 1;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=failed-turn-alert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failed-turn-alert.js","sourceRoot":"","sources":["../../jsr/usage-report/failed-turn-alert.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export interface AdoptedBuild {
|
|
2
|
-
readonly promptId: string;
|
|
3
|
-
readonly fsId: string;
|
|
4
|
-
}
|
|
5
|
-
export interface AdoptedBuildSlot {
|
|
6
|
-
current: AdoptedBuild | undefined;
|
|
7
|
-
}
|
|
8
|
-
export declare function shouldMirrorBuildCost(args: {
|
|
9
|
-
readonly mode: unknown;
|
|
10
|
-
readonly builtThisTurn: boolean;
|
|
11
|
-
readonly adopted?: AdoptedBuild;
|
|
12
|
-
}): boolean;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { isSourceChangingMode } from "@vibes.diy/api-types";
|
|
2
|
-
export function shouldMirrorBuildCost(args) {
|
|
3
|
-
if (isSourceChangingMode(args.mode) === false)
|
|
4
|
-
return true;
|
|
5
|
-
if (args.builtThisTurn)
|
|
6
|
-
return true;
|
|
7
|
-
return args.adopted !== undefined;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=build-billing-outcome.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-billing-outcome.js","sourceRoot":"","sources":["../../jsr/intern/build-billing-outcome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAwC5D,MAAM,UAAU,qBAAqB,CAAC,IAOrC;IAEC,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAG3D,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC;AACpC,CAAC"}
|