@mestreyoda/fabrica 0.1.14 → 0.1.15

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 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.14") {
111333
- return "0.1.14";
111332
+ if ("0.1.15") {
111333
+ return "0.1.15";
111334
111334
  }
111335
111335
  try {
111336
111336
  const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
@@ -142322,6 +142322,7 @@ function shouldSuppressTelegramBootstrapReply(session, request2) {
142322
142322
 
142323
142323
  // lib/dispatch/telegram-bootstrap-hook.ts
142324
142324
  var BOOTSTRAP_TIMEOUT_MS = 5 * 6e4;
142325
+ var LAYER3_CONFIDENCE_THRESHOLD = 0.6;
142325
142326
  var BOOTSTRAP_MESSAGES = {
142326
142327
  ack: {
142327
142328
  pt: "Recebi! Vou analisar e come\xE7ar a montar o projeto...",
@@ -142360,6 +142361,9 @@ function normalizeText3(value) {
142360
142361
  const trimmed = value?.trim();
142361
142362
  return trimmed ? trimmed : void 0;
142362
142363
  }
142364
+ function normalizeUserResponse(text) {
142365
+ return text.trim().replace(/[.,!?;:\u2026]+$/, "").toLowerCase();
142366
+ }
142363
142367
  function detectStackHint(text) {
142364
142368
  const lower2 = text.toLowerCase();
142365
142369
  if (/\b(nextjs|next\.js)\b/.test(lower2)) return "nextjs";
@@ -142466,8 +142470,8 @@ function parseClarificationResponse(text, session) {
142466
142470
  if (session.pendingClarification === "name") {
142467
142471
  const trimmed = text.trim();
142468
142472
  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 };
142473
+ if (autoPatterns.test(normalizeUserResponse(text))) {
142474
+ return { recognized: true, projectName: inferProjectSlug(session.rawIdea) ?? `project-${Date.now()}`, stackHint: session.stackHint ?? void 0 };
142471
142475
  }
142472
142476
  const nameField = parseField(text, ["project name", "nome do projeto", "nome", "name"]);
142473
142477
  if (nameField) {
@@ -142486,7 +142490,7 @@ function parseClarificationResponse(text, session) {
142486
142490
  if (detectedStack) {
142487
142491
  return { recognized: true, stackHint: detectedStack };
142488
142492
  }
142489
- const lower2 = text.toLowerCase().trim();
142493
+ const lower2 = normalizeUserResponse(text);
142490
142494
  const bareStackMap = {
142491
142495
  python: "python-cli",
142492
142496
  py: "python-cli",
@@ -142521,11 +142525,6 @@ function buildClarificationMessage(parsed, pendingClarification, language = "pt"
142521
142525
  }
142522
142526
  return BOOTSTRAP_MESSAGES.clarifyStack[language];
142523
142527
  }
142524
- function buildFollowUpClarification(session) {
142525
- const lang = session.language ?? "pt";
142526
- if (!session.stackHint) return BOOTSTRAP_MESSAGES.clarifyStackFollowUp[lang];
142527
- return lang === "en" ? "Can you give me more details about what you want to build?" : "Pode me dar mais detalhes sobre o que voc\xEA quer construir?";
142528
- }
142529
142528
  function buildTopicDeepLink(chatId, topicId) {
142530
142529
  const stripped = chatId.replace(/^-100/, "");
142531
142530
  return `https://t.me/c/${stripped}/${topicId}`;
@@ -142568,7 +142567,7 @@ async function classifyAndBootstrap(ctx, workspaceDir, conversationId, content)
142568
142567
  status: "classifying"
142569
142568
  });
142570
142569
  const classification = await classifyDmIntent(ctx, content, workspaceDir);
142571
- if (!classification || classification.intent !== "create_project" || classification.confidence < 0.7) {
142570
+ if (!classification || classification.intent !== "create_project" || classification.confidence < LAYER3_CONFIDENCE_THRESHOLD) {
142572
142571
  if (!classification) {
142573
142572
  logBootstrapWarning(ctx, `[telegram-bootstrap] LLM classify failed, falling back (conversation: ${conversationId})`);
142574
142573
  }
@@ -142656,7 +142655,6 @@ async function continueBootstrap(ctx, conversationId, workspaceDir, request2, so
142656
142655
  );
142657
142656
  return;
142658
142657
  }
142659
- const projectName = request2.projectName ?? void 0;
142660
142658
  const stackHint = request2.stackHint;
142661
142659
  if (!stackHint) {
142662
142660
  const existingSession = await readTelegramBootstrapSession(workspaceDir, conversationId);
@@ -142676,29 +142674,38 @@ async function continueBootstrap(ctx, conversationId, workspaceDir, request2, so
142676
142674
  ));
142677
142675
  return;
142678
142676
  }
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;
142677
+ if (!request2.projectName) {
142678
+ const inferredSlug = inferProjectSlug(request2.rawIdea);
142679
+ if (inferredSlug) {
142680
+ request2.projectName = inferredSlug;
142681
+ } else {
142682
+ const existingSession = await readTelegramBootstrapSession(workspaceDir, conversationId);
142683
+ if (existingSession?.pendingClarification === "name") {
142684
+ request2.projectName = `project-${Date.now()}`;
142685
+ } else {
142686
+ const lang = existingSession?.language ?? "pt";
142687
+ await upsertTelegramBootstrapSession(workspaceDir, {
142688
+ conversationId,
142689
+ rawIdea: request2.rawIdea,
142690
+ stackHint: request2.stackHint ?? void 0,
142691
+ status: "clarifying",
142692
+ pendingClarification: "name",
142693
+ language: lang
142694
+ });
142695
+ await sendTelegramText(
142696
+ ctx,
142697
+ conversationId,
142698
+ buildClarificationMessage(
142699
+ { rawIdea: request2.rawIdea, projectName: void 0, stackHint: request2.stackHint ?? void 0 },
142700
+ "name",
142701
+ lang
142702
+ )
142703
+ );
142704
+ return;
142705
+ }
142706
+ }
142700
142707
  }
142701
- const candidateSlug = inferProjectSlug(projectName ?? request2.rawIdea);
142708
+ const candidateSlug = inferProjectSlug(request2.projectName ?? request2.rawIdea);
142702
142709
  if (candidateSlug) {
142703
142710
  const projects = await readProjects(workspaceDir).catch(() => null);
142704
142711
  if (projects?.projects?.[candidateSlug]) {
@@ -142747,7 +142754,7 @@ async function continueBootstrap(ctx, conversationId, workspaceDir, request2, so
142747
142754
  metadata: {
142748
142755
  source: "telegram-dm-bootstrap",
142749
142756
  factory_change: false,
142750
- project_name: projectName ?? null,
142757
+ project_name: request2.projectName ?? null,
142751
142758
  repo_url: request2.repoUrl ?? null,
142752
142759
  repo_path: request2.repoPath ?? null,
142753
142760
  stack_hint: stackHint,
@@ -142804,7 +142811,7 @@ Erro: ${result.error ?? "erro desconhecido"}`
142804
142811
  );
142805
142812
  return;
142806
142813
  }
142807
- const resolvedProjectName = result.payload.metadata.project_name ?? result.payload.metadata.project_slug ?? projectName ?? "projeto";
142814
+ const resolvedProjectName = result.payload.metadata.project_name ?? result.payload.metadata.project_slug ?? request2.projectName ?? "projeto";
142808
142815
  const projectChannelId = result.payload.metadata.channel_id ?? telegramConfig.projectsForumChatId;
142809
142816
  const messageThreadId = result.payload.metadata.message_thread_id;
142810
142817
  const projectSlug = result.payload.metadata.project_slug ?? result.payload.scaffold?.project_slug ?? null;
@@ -142935,7 +142942,11 @@ function registerTelegramBootstrapHook(api, ctx) {
142935
142942
  const clarResult = parseClarificationResponse(content, existingSession);
142936
142943
  if (!clarResult.recognized) {
142937
142944
  ctx.logger.info(`[telegram-bootstrap] clarification response not recognized, re-asking (conversation: ${conversationId})`);
142938
- await sendTelegramText(ctx, conversationId, buildFollowUpClarification(existingSession));
142945
+ await sendTelegramText(ctx, conversationId, buildClarificationMessage(
142946
+ { rawIdea: existingSession.rawIdea, stackHint: existingSession.stackHint ?? void 0, projectName: existingSession.projectName ?? void 0 },
142947
+ existingSession.pendingClarification ?? void 0,
142948
+ existingSession.language ?? "pt"
142949
+ ));
142939
142950
  return;
142940
142951
  }
142941
142952
  const mergedRequest = {
@@ -142967,28 +142978,22 @@ function registerTelegramBootstrapHook(api, ctx) {
142967
142978
  return;
142968
142979
  }
142969
142980
  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
- }
142976
- const incomingRequest = {
142981
+ const preClassifyRequest = {
142977
142982
  rawIdea: parsed.rawIdea,
142978
142983
  projectName: parsed.projectName ?? null,
142979
142984
  stackHint: parsed.stackHint ?? null,
142980
142985
  repoUrl: parsed.repoUrl ?? null,
142981
142986
  repoPath: parsed.repoPath ?? null
142982
142987
  };
142983
- const incomingRequestHash = buildBootstrapRequestHash(incomingRequest);
142984
- const sessionForHash = await readTelegramBootstrapSession(workspaceDir, conversationId);
142985
- if (sessionForHash?.requestHash === incomingRequestHash) {
142986
- if (sessionForHash.status === "completed") {
142988
+ const preClassifyHash = buildBootstrapRequestHash(preClassifyRequest);
142989
+ const sessionForHashPreClassify = await readTelegramBootstrapSession(workspaceDir, conversationId);
142990
+ if (sessionForHashPreClassify?.requestHash === preClassifyHash) {
142991
+ if (sessionForHashPreClassify.status === "completed") {
142987
142992
  ctx.logger.info(`[telegram-bootstrap] duplicate completed DM ignored for conversation ${conversationId}`);
142988
142993
  return;
142989
142994
  }
142990
- const isExpiredReceived = sessionForHash.status === "received" && Date.parse(sessionForHash.suppressUntil) < Date.now();
142991
- if (sessionForHash.status !== "failed" && !isExpiredReceived) {
142995
+ const isExpiredReceived = sessionForHashPreClassify.status === "received" && Date.parse(sessionForHashPreClassify.suppressUntil) < Date.now();
142996
+ if (sessionForHashPreClassify.status !== "failed" && !isExpiredReceived) {
142992
142997
  ctx.logger.info(`[telegram-bootstrap] duplicate in-flight DM ignored for conversation ${conversationId}`);
142993
142998
  return;
142994
142999
  }
@@ -142996,6 +143001,25 @@ function registerTelegramBootstrapHook(api, ctx) {
142996
143001
  ctx.logger.info(`[telegram-bootstrap] stale received session (expired) \u2014 restarting pipeline for conversation ${conversationId}`);
142997
143002
  }
142998
143003
  }
143004
+ if (!parsed.projectName && ctx.runtime?.subagent?.run) {
143005
+ await upsertTelegramBootstrapSession(workspaceDir, {
143006
+ conversationId,
143007
+ rawIdea: parsed.rawIdea,
143008
+ sourceRoute: { channel: "telegram", channelId: conversationId },
143009
+ status: "pending_classify"
143010
+ });
143011
+ const classification = await classifyDmIntent(ctx, content, workspaceDir);
143012
+ if (classification?.projectSlug) {
143013
+ parsed.projectName = classification.projectSlug;
143014
+ }
143015
+ }
143016
+ const incomingRequest = {
143017
+ rawIdea: parsed.rawIdea,
143018
+ projectName: parsed.projectName ?? null,
143019
+ stackHint: parsed.stackHint ?? null,
143020
+ repoUrl: parsed.repoUrl ?? null,
143021
+ repoPath: parsed.repoPath ?? null
143022
+ };
142999
143023
  const language = /\b(cria|crie|criar|construa|desenvolva|registre|novo projeto)\b/i.test(content) ? "pt" : "en";
143000
143024
  await sendTelegramText(ctx, conversationId, BOOTSTRAP_MESSAGES.ack[language]);
143001
143025
  const session = await upsertTelegramBootstrapSession(workspaceDir, {