@mestreyoda/fabrica 0.1.13 → 0.1.14
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/dist/index.js +85 -24
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -111329,8 +111329,8 @@ import fsSync from "node:fs";
|
|
|
111329
111329
|
import path5 from "node:path";
|
|
111330
111330
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
111331
111331
|
function getCurrentVersion() {
|
|
111332
|
-
if ("0.1.
|
|
111333
|
-
return "0.1.
|
|
111332
|
+
if ("0.1.14") {
|
|
111333
|
+
return "0.1.14";
|
|
111334
111334
|
}
|
|
111335
111335
|
try {
|
|
111336
111336
|
const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
|
|
@@ -142208,8 +142208,6 @@ function registerAttachmentHook(api, ctx) {
|
|
|
142208
142208
|
|
|
142209
142209
|
// lib/dispatch/telegram-bootstrap-hook.ts
|
|
142210
142210
|
import { homedir as homedir3 } from "node:os";
|
|
142211
|
-
init_runtime_paths();
|
|
142212
|
-
init_extract_json();
|
|
142213
142211
|
init_zod();
|
|
142214
142212
|
|
|
142215
142213
|
// lib/dispatch/telegram-bootstrap-session.ts
|
|
@@ -142244,14 +142242,14 @@ function buildBootstrapRequestHash(input) {
|
|
|
142244
142242
|
return buildBootstrapRequestFingerprint(input);
|
|
142245
142243
|
}
|
|
142246
142244
|
function nextSuppressUntil(status) {
|
|
142247
|
-
const ttl = status === "classifying" ? CLASSIFYING_TTL_MS : SESSION_TTL_MS;
|
|
142245
|
+
const ttl = status === "classifying" || status === "pending_classify" ? CLASSIFYING_TTL_MS : SESSION_TTL_MS;
|
|
142248
142246
|
return new Date(Date.now() + ttl).toISOString();
|
|
142249
142247
|
}
|
|
142250
142248
|
async function readTelegramBootstrapSession(workspaceDir, conversationId) {
|
|
142251
142249
|
try {
|
|
142252
142250
|
const raw = await fs38.readFile(sessionPath(workspaceDir, conversationId), "utf-8");
|
|
142253
142251
|
const session = JSON.parse(raw);
|
|
142254
|
-
if ((session.status === "clarifying" || session.status === "classifying") && Date.parse(session.suppressUntil) < Date.now()) {
|
|
142252
|
+
if ((session.status === "clarifying" || session.status === "classifying" || session.status === "pending_classify") && Date.parse(session.suppressUntil) < Date.now()) {
|
|
142255
142253
|
await fs38.unlink(sessionPath(workspaceDir, conversationId)).catch(() => {
|
|
142256
142254
|
});
|
|
142257
142255
|
return null;
|
|
@@ -142341,6 +142339,10 @@ var BOOTSTRAP_MESSAGES = {
|
|
|
142341
142339
|
pt: "N\xE3o consegui identificar a stack. Pode me dizer qual linguagem/framework voc\xEA quer usar? Ex: Python, Node.js, Go, Java...",
|
|
142342
142340
|
en: "Couldn't identify the stack. Can you tell me which language/framework you'd like to use? e.g., Python, Node.js, Go, Java..."
|
|
142343
142341
|
},
|
|
142342
|
+
clarifyName: {
|
|
142343
|
+
pt: "Como voc\xEA quer chamar o projeto? Se preferir, posso escolher um nome.",
|
|
142344
|
+
en: "What do you want to name the project? If you prefer, I can pick one."
|
|
142345
|
+
},
|
|
142344
142346
|
registered: {
|
|
142345
142347
|
pt: (name, link) => `Projeto "${name}" registrado.
|
|
142346
142348
|
Vou continuar o fluxo em ${link}`,
|
|
@@ -142349,7 +142351,9 @@ I'll continue the flow at ${link}`
|
|
|
142349
142351
|
}
|
|
142350
142352
|
};
|
|
142351
142353
|
function inferProjectSlug(text) {
|
|
142352
|
-
|
|
142354
|
+
let cleaned = text.replace(/^(create|build|crie|cria|criar|fazer?|quero|i need|i want)\s+(uma|um|me\s+a?|an|a)?\s*/i, "").replace(/\s+(that|which|que|para|for|pra)\s+.*/i, "").trim();
|
|
142355
|
+
if (!cleaned) cleaned = text;
|
|
142356
|
+
const slug = cleaned.toLowerCase().normalize("NFKD").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").slice(0, 64);
|
|
142353
142357
|
return slug || void 0;
|
|
142354
142358
|
}
|
|
142355
142359
|
function normalizeText3(value) {
|
|
@@ -142422,26 +142426,31 @@ Examples:
|
|
|
142422
142426
|
- "How's the project going?" \u2192 {"intent":"other","confidence":0.95,"stackHint":null,"projectSlug":null,"language":"en"}
|
|
142423
142427
|
- "Oi, tudo bem?" \u2192 {"intent":"other","confidence":0.99,"stackHint":null,"projectSlug":null,"language":"pt"}
|
|
142424
142428
|
- "Me faz um app que converte temperaturas" \u2192 {"intent":"create_project","confidence":0.9,"stackHint":null,"projectSlug":"conversor-temperaturas","language":"pt"}`;
|
|
142425
|
-
async function classifyDmIntent(ctx, content,
|
|
142429
|
+
async function classifyDmIntent(ctx, content, _workspaceDir) {
|
|
142426
142430
|
try {
|
|
142431
|
+
const runtime = ctx.runtime;
|
|
142432
|
+
if (!runtime?.subagent?.run) return null;
|
|
142427
142433
|
const truncated = content.slice(0, MAX_CLASSIFY_LENGTH);
|
|
142428
142434
|
const prompt = CLASSIFY_PROMPT_TEMPLATE.replace("$CONTENT", truncated.replace(/"/g, '\\"'));
|
|
142429
|
-
const
|
|
142430
|
-
const
|
|
142431
|
-
|
|
142432
|
-
|
|
142433
|
-
|
|
142434
|
-
|
|
142435
|
-
|
|
142436
|
-
|
|
142437
|
-
|
|
142438
|
-
|
|
142439
|
-
|
|
142440
|
-
const
|
|
142435
|
+
const sessionKey = `dm-classify-${Date.now()}`;
|
|
142436
|
+
const { runId } = await runtime.subagent.run({
|
|
142437
|
+
sessionKey,
|
|
142438
|
+
message: prompt,
|
|
142439
|
+
extraSystemPrompt: "You are a JSON classifier. Return ONLY valid JSON, no markdown fences.",
|
|
142440
|
+
lane: "subagent",
|
|
142441
|
+
deliver: false,
|
|
142442
|
+
idempotencyKey: sessionKey
|
|
142443
|
+
});
|
|
142444
|
+
const waitResult = await runtime.subagent.waitForRun({ runId, timeoutMs: 15e3 });
|
|
142445
|
+
if (waitResult.status !== "ok") return null;
|
|
142446
|
+
const messages = await runtime.subagent.getSessionMessages({ sessionKey });
|
|
142447
|
+
const lastAssistant = messages?.filter((m2) => m2.role === "assistant").pop();
|
|
142448
|
+
const text = lastAssistant?.content ?? "";
|
|
142449
|
+
if (!text.trim()) return null;
|
|
142450
|
+
const jsonStr = text.replace(/^```(json)?/gm, "").replace(/```$/gm, "").trim();
|
|
142441
142451
|
const intentData = JSON.parse(jsonStr);
|
|
142442
142452
|
const validated = DmIntentSchema.safeParse(intentData);
|
|
142443
|
-
|
|
142444
|
-
return validated.data;
|
|
142453
|
+
return validated.success ? validated.data : null;
|
|
142445
142454
|
} catch {
|
|
142446
142455
|
return null;
|
|
142447
142456
|
}
|
|
@@ -142454,6 +142463,21 @@ function isBootstrapCandidate(text) {
|
|
|
142454
142463
|
return createCue && softwareCue;
|
|
142455
142464
|
}
|
|
142456
142465
|
function parseClarificationResponse(text, session) {
|
|
142466
|
+
if (session.pendingClarification === "name") {
|
|
142467
|
+
const trimmed = text.trim();
|
|
142468
|
+
const autoPatterns = /^(escolha|pick one|tanto faz|you choose|pode escolher|auto|skip)$/i;
|
|
142469
|
+
if (autoPatterns.test(trimmed)) {
|
|
142470
|
+
return { recognized: true, projectName: inferProjectSlug(session.rawIdea) ?? void 0, stackHint: session.stackHint ?? void 0 };
|
|
142471
|
+
}
|
|
142472
|
+
const nameField = parseField(text, ["project name", "nome do projeto", "nome", "name"]);
|
|
142473
|
+
if (nameField) {
|
|
142474
|
+
return { recognized: true, projectName: nameField, stackHint: session.stackHint ?? void 0 };
|
|
142475
|
+
}
|
|
142476
|
+
if (trimmed.length > 0 && trimmed.length <= 64) {
|
|
142477
|
+
return { recognized: true, projectName: trimmed, stackHint: session.stackHint ?? void 0 };
|
|
142478
|
+
}
|
|
142479
|
+
return { recognized: false };
|
|
142480
|
+
}
|
|
142457
142481
|
const stackField = parseField(text, ["stack", "framework", "linguagem", "language"]);
|
|
142458
142482
|
if (stackField) {
|
|
142459
142483
|
return { recognized: true, stackHint: detectStackHint(stackField) ?? stackField };
|
|
@@ -142489,6 +142513,9 @@ function parseClarificationResponse(text, session) {
|
|
|
142489
142513
|
return { recognized: false };
|
|
142490
142514
|
}
|
|
142491
142515
|
function buildClarificationMessage(parsed, pendingClarification, language = "pt") {
|
|
142516
|
+
if (pendingClarification === "name") {
|
|
142517
|
+
return BOOTSTRAP_MESSAGES.clarifyName[language];
|
|
142518
|
+
}
|
|
142492
142519
|
if (pendingClarification === "stack_and_name" || !parsed.stackHint && !parsed.projectName) {
|
|
142493
142520
|
return BOOTSTRAP_MESSAGES.clarifyBoth[language];
|
|
142494
142521
|
}
|
|
@@ -142534,6 +142561,12 @@ function logBootstrapWarning(ctx, message) {
|
|
|
142534
142561
|
}
|
|
142535
142562
|
}
|
|
142536
142563
|
async function classifyAndBootstrap(ctx, workspaceDir, conversationId, content) {
|
|
142564
|
+
await upsertTelegramBootstrapSession(workspaceDir, {
|
|
142565
|
+
conversationId,
|
|
142566
|
+
rawIdea: content,
|
|
142567
|
+
sourceRoute: { channel: "telegram", channelId: conversationId },
|
|
142568
|
+
status: "classifying"
|
|
142569
|
+
});
|
|
142537
142570
|
const classification = await classifyDmIntent(ctx, content, workspaceDir);
|
|
142538
142571
|
if (!classification || classification.intent !== "create_project" || classification.confidence < 0.7) {
|
|
142539
142572
|
if (!classification) {
|
|
@@ -142643,6 +142676,28 @@ async function continueBootstrap(ctx, conversationId, workspaceDir, request2, so
|
|
|
142643
142676
|
));
|
|
142644
142677
|
return;
|
|
142645
142678
|
}
|
|
142679
|
+
if (!projectName) {
|
|
142680
|
+
const existingSession = await readTelegramBootstrapSession(workspaceDir, conversationId);
|
|
142681
|
+
const lang = existingSession?.language ?? "pt";
|
|
142682
|
+
await upsertTelegramBootstrapSession(workspaceDir, {
|
|
142683
|
+
conversationId,
|
|
142684
|
+
rawIdea: request2.rawIdea,
|
|
142685
|
+
stackHint: request2.stackHint ?? void 0,
|
|
142686
|
+
status: "clarifying",
|
|
142687
|
+
pendingClarification: "name",
|
|
142688
|
+
language: lang
|
|
142689
|
+
});
|
|
142690
|
+
await sendTelegramText(
|
|
142691
|
+
ctx,
|
|
142692
|
+
conversationId,
|
|
142693
|
+
buildClarificationMessage(
|
|
142694
|
+
{ rawIdea: request2.rawIdea, projectName: void 0, stackHint: request2.stackHint ?? void 0 },
|
|
142695
|
+
"name",
|
|
142696
|
+
lang
|
|
142697
|
+
)
|
|
142698
|
+
);
|
|
142699
|
+
return;
|
|
142700
|
+
}
|
|
142646
142701
|
const candidateSlug = inferProjectSlug(projectName ?? request2.rawIdea);
|
|
142647
142702
|
if (candidateSlug) {
|
|
142648
142703
|
const projects = await readProjects(workspaceDir).catch(() => null);
|
|
@@ -142872,7 +142927,7 @@ function registerTelegramBootstrapHook(api, ctx) {
|
|
|
142872
142927
|
}
|
|
142873
142928
|
const existingSession = await readTelegramBootstrapSession(workspaceDir, conversationId);
|
|
142874
142929
|
const sessionIsExpired = existingSession != null && Date.parse(existingSession.suppressUntil) < Date.now();
|
|
142875
|
-
if (existingSession && !sessionIsExpired && existingSession.status === "classifying") {
|
|
142930
|
+
if (existingSession && !sessionIsExpired && (existingSession.status === "classifying" || existingSession.status === "pending_classify")) {
|
|
142876
142931
|
ctx.logger.info(`[telegram-bootstrap] LLM classification in progress for ${conversationId}, ignoring concurrent message`);
|
|
142877
142932
|
return;
|
|
142878
142933
|
}
|
|
@@ -142903,7 +142958,7 @@ function registerTelegramBootstrapHook(api, ctx) {
|
|
|
142903
142958
|
conversationId,
|
|
142904
142959
|
rawIdea: content,
|
|
142905
142960
|
sourceRoute: { channel: "telegram", channelId: conversationId },
|
|
142906
|
-
status: "
|
|
142961
|
+
status: "pending_classify"
|
|
142907
142962
|
});
|
|
142908
142963
|
classifyAndBootstrap(ctx, workspaceDir, conversationId, content).catch((err) => {
|
|
142909
142964
|
logBootstrapWarning(ctx, `[telegram-bootstrap] LLM classify error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -142912,6 +142967,12 @@ function registerTelegramBootstrapHook(api, ctx) {
|
|
|
142912
142967
|
return;
|
|
142913
142968
|
}
|
|
142914
142969
|
const parsed = parseBootstrapRequest(content);
|
|
142970
|
+
if (!parsed.projectName && ctx.runtime?.subagent?.run) {
|
|
142971
|
+
const classification = await classifyDmIntent(ctx, content, workspaceDir);
|
|
142972
|
+
if (classification?.projectSlug) {
|
|
142973
|
+
parsed.projectName = classification.projectSlug;
|
|
142974
|
+
}
|
|
142975
|
+
}
|
|
142915
142976
|
const incomingRequest = {
|
|
142916
142977
|
rawIdea: parsed.rawIdea,
|
|
142917
142978
|
projectName: parsed.projectName ?? null,
|