@bobsworkshop/cli 1.0.0 → 1.1.0

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/bob.js CHANGED
@@ -1,7 +1,7 @@
1
- #!/usr/bin/env node
2
1
  import {
3
2
  buildLocalContext,
4
3
  callCloudFunction,
4
+ callHTTPFunction,
5
5
  callLocalModel,
6
6
  completeTask,
7
7
  createAnalysisRun,
@@ -27,7 +27,7 @@ import {
27
27
  setConfigValue,
28
28
  stripCodeBlockFromResponse,
29
29
  updateManifestProgress
30
- } from "./chunk-NZW7H2BY.js";
30
+ } from "./chunk-WRMNJJA6.js";
31
31
  import {
32
32
  agentExists,
33
33
  createAgent,
@@ -485,8 +485,8 @@ ${stderr}`);
485
485
 
486
486
  // bin/bob.ts
487
487
  import { Command } from "commander";
488
- import chalk31 from "chalk";
489
- import * as path22 from "path";
488
+ import chalk32 from "chalk";
489
+ import * as path23 from "path";
490
490
 
491
491
  // src/commands/config.ts
492
492
  import chalk from "chalk";
@@ -757,6 +757,29 @@ async function getTodayMessages(projectName) {
757
757
  return msg.timestamp >= twentyFourHoursAgo;
758
758
  });
759
759
  }
760
+ function buildDNAString() {
761
+ const dna = loadCurrentDNA();
762
+ if (!dna) return null;
763
+ const weekly = loadWeeklyProfiles(1)[0] || null;
764
+ const lines = [
765
+ "### USER BEHAVIORAL DNA ###",
766
+ `Archetype: ${dna.archetype || "Unknown"}`,
767
+ `Communication Style: ${dna.communicationStyle || "Unknown"}`,
768
+ `Work Rhythm: ${dna.workRhythm || "Unknown"}`,
769
+ `Decision Making: ${dna.decisionMaking || "Unknown"}`,
770
+ `Emotional State: ${dna.emotionalState || "Unknown"}`
771
+ ];
772
+ if (dna.growth) lines.push(`Growth Focus: ${dna.growth}`);
773
+ if (dna.source) lines.push(`Profile Source: ${dna.source} (${dna.lastUpdated || "unknown date"})`);
774
+ if (weekly) {
775
+ lines.push("");
776
+ lines.push("--- WEEKLY TRAJECTORY ---");
777
+ if (weekly.trajectory) lines.push(`Weekly Arc: ${weekly.trajectory}`);
778
+ if (weekly.moodShift) lines.push(`Mood Shift: ${weekly.moodShift}`);
779
+ if (weekly.focusEvolution) lines.push(`Focus Evolution: ${weekly.focusEvolution}`);
780
+ }
781
+ return lines.join("\n");
782
+ }
760
783
 
761
784
  // src/ai/persona.ts
762
785
  var STANDARD_STYLE_PROMPT = `You are Bob: friendly, direct, senior-level engineering partner.
@@ -1479,6 +1502,82 @@ function sleep2(ms) {
1479
1502
  return new Promise((resolve4) => setTimeout(resolve4, ms));
1480
1503
  }
1481
1504
 
1505
+ // src/core/reference-resolver.ts
1506
+ var RESERVED_COMMANDS = [
1507
+ "help",
1508
+ "clear",
1509
+ "reset",
1510
+ "surface",
1511
+ "promote",
1512
+ "constraints",
1513
+ "personalized",
1514
+ "exit",
1515
+ "quit",
1516
+ "new",
1517
+ "ref",
1518
+ "pin",
1519
+ "unpin",
1520
+ "sticky"
1521
+ ];
1522
+ function detectReference(input) {
1523
+ if (!input.startsWith("/")) return null;
1524
+ const match = input.match(
1525
+ /^\/([a-zA-Z0-9_-]+)(?:\s*-\s*(.+?))?(?:\s|$)/
1526
+ );
1527
+ if (!match) return null;
1528
+ const alias = match[1].toLowerCase().trim();
1529
+ if (RESERVED_COMMANDS.includes(alias)) return null;
1530
+ return {
1531
+ alias,
1532
+ filename: match[2]?.trim()
1533
+ };
1534
+ }
1535
+ async function fetchAvailableReferences(domain, uid) {
1536
+ try {
1537
+ const result = await callCloudFunction("getAvailableReferences", {
1538
+ domain,
1539
+ uid
1540
+ });
1541
+ return result?.references ?? [];
1542
+ } catch (e) {
1543
+ console.error("[REF] fetchAvailableReferences failed:", e);
1544
+ return [];
1545
+ }
1546
+ }
1547
+ async function fetchProjectFiles(domain, projectId, query = "") {
1548
+ try {
1549
+ const result = await callCloudFunction("getProjectReferenceFiles", {
1550
+ domain,
1551
+ projectId,
1552
+ query
1553
+ });
1554
+ return result?.files ?? [];
1555
+ } catch (e) {
1556
+ console.error("[REF] fetchProjectFiles failed:", e);
1557
+ return [];
1558
+ }
1559
+ }
1560
+ async function loadStickyReference(docPath) {
1561
+ try {
1562
+ const result = await callCloudFunction("getStickyReference", { docPath });
1563
+ if (!result?.active || !result?.alias) return null;
1564
+ return { alias: result.alias };
1565
+ } catch (e) {
1566
+ return null;
1567
+ }
1568
+ }
1569
+ async function saveStickyReference(docPath, alias, active) {
1570
+ try {
1571
+ await callCloudFunction("setStickyReference", {
1572
+ docPath,
1573
+ alias,
1574
+ active
1575
+ });
1576
+ } catch (e) {
1577
+ console.error("[REF] saveStickyReference failed:", e);
1578
+ }
1579
+ }
1580
+
1482
1581
  // src/commands/deepdive.ts
1483
1582
  var BRAND_SECONDARY2 = chalk5.hex("#FFAB00");
1484
1583
  var SUCCESS2 = chalk5.hex("#66BB6A");
@@ -1682,6 +1781,10 @@ async function enterDeepDive(config, conversationId, rl) {
1682
1781
  async function runDeepDiveSession(config, conversationId, parentMessageId, initiatingPrompt, rl) {
1683
1782
  const previewText = initiatingPrompt.slice(0, 50) + (initiatingPrompt.length > 50 ? "..." : "");
1684
1783
  const isLocalProvider = config.provider === "local" && config.localEndpoint;
1784
+ const domain = config.email?.split("@").pop()?.toLowerCase() ?? "";
1785
+ const uid = config.uid ?? "";
1786
+ const threadDocPath = `Organizations/${domain}/OrgUsers/${uid}/BobGlobalChat/${conversationId}/Messages/${parentMessageId}/sandbox/thread`;
1787
+ let stickyRef = await loadStickyReference(threadDocPath);
1685
1788
  console.log("");
1686
1789
  console.log(MODE_DEEPDIVE2(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1687
1790
  console.log(MODE_DEEPDIVE2(" \u2551") + chalk5.bold(MODE_DEEPDIVE2(" \u{1F93F} DEEP DIVE ")) + MODE_DEEPDIVE2("\u2551"));
@@ -1689,15 +1792,20 @@ async function runDeepDiveSession(config, conversationId, parentMessageId, initi
1689
1792
  if (isLocalProvider) {
1690
1793
  console.log(MODE_DEEPDIVE2(" \u2551") + MUTED2(" Provider: Local model (sovereign handoff)"));
1691
1794
  }
1795
+ if (stickyRef) {
1796
+ console.log(MODE_DEEPDIVE2(" \u2551") + AMBER(` \u{1F4CC} Sticky ref: /${stickyRef.alias}`));
1797
+ }
1692
1798
  console.log(MODE_DEEPDIVE2(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1693
- console.log(MODE_DEEPDIVE2(" \u2551") + MUTED2(" Commands: /surface /promote /clear /constraints ") + MODE_DEEPDIVE2("\u2551"));
1799
+ console.log(MODE_DEEPDIVE2(" \u2551") + MUTED2(" /surface /promote /clear /constraints ") + MODE_DEEPDIVE2("\u2551"));
1800
+ console.log(MODE_DEEPDIVE2(" \u2551") + MUTED2(" /ref /pin \u2014 manage reference projects ") + MODE_DEEPDIVE2("\u2551"));
1694
1801
  console.log(MODE_DEEPDIVE2(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1695
1802
  console.log("");
1696
1803
  let lastBobResponse = "";
1697
1804
  let lastConstraints3 = [];
1698
1805
  return new Promise((resolve4) => {
1699
1806
  const deepDivePrompt = () => {
1700
- rl.question(MODE_DEEPDIVE2(" \u{1F93F} You: "), async (input) => {
1807
+ const promptText = stickyRef ? MODE_DEEPDIVE2(` \u{1F4CC} /${stickyRef.alias} \u{1F93F} \u203A `) : MODE_DEEPDIVE2(" \u{1F93F} You: ");
1808
+ rl.question(promptText, async (input) => {
1701
1809
  const trimmed = input.trim();
1702
1810
  if (!trimmed) {
1703
1811
  deepDivePrompt();
@@ -1772,6 +1880,30 @@ async function runDeepDiveSession(config, conversationId, parentMessageId, initi
1772
1880
  deepDivePrompt();
1773
1881
  return;
1774
1882
  }
1883
+ if (trimmed === "/ref") {
1884
+ stickyRef = await handleDeepDiveRefBrowser(domain, uid, threadDocPath, rl);
1885
+ deepDivePrompt();
1886
+ return;
1887
+ }
1888
+ if (trimmed === "/pin") {
1889
+ if (stickyRef) {
1890
+ await saveStickyReference(threadDocPath, null, false);
1891
+ stickyRef = null;
1892
+ console.log("");
1893
+ console.log(MUTED2(" \u{1F4CC} Sticky reference cleared."));
1894
+ console.log("");
1895
+ } else {
1896
+ stickyRef = await handleDeepDiveRefBrowser(domain, uid, threadDocPath, rl);
1897
+ }
1898
+ deepDivePrompt();
1899
+ return;
1900
+ }
1901
+ const inlineRef = detectReference(trimmed);
1902
+ const activeRef = inlineRef ?? stickyRef ?? null;
1903
+ if (activeRef) {
1904
+ console.log("");
1905
+ console.log(AMBER(` \u{1F4CE} Referencing /${activeRef.alias}${activeRef.filename ? ` \u2014 ${activeRef.filename}` : ""}...`));
1906
+ }
1775
1907
  renderUserMessage(trimmed);
1776
1908
  startElapsedTimer();
1777
1909
  try {
@@ -1798,7 +1930,10 @@ Current request: ${trimmed}` : trimmed;
1798
1930
  isLocalModel: true,
1799
1931
  activePersonaId: null,
1800
1932
  localContext,
1801
- cliMode: true
1933
+ cliMode: true,
1934
+ // ─── REFERENCE PARAMS ───
1935
+ ...activeRef && { referenceAlias: activeRef.alias },
1936
+ ...activeRef?.filename && { referenceFilename: activeRef.filename }
1802
1937
  });
1803
1938
  if (!handoffResult?.isHandoff || !handoffResult?.masterPrompt) {
1804
1939
  throw new Error("Handoff failed \u2014 no master prompt returned.");
@@ -1807,7 +1942,18 @@ Current request: ${trimmed}` : trimmed;
1807
1942
  responseText = await callLocalModel(config.localEndpoint, localMessages);
1808
1943
  await callCloudFunction("saveCLIDeepDiveMessage", { conversationId, parentMessageId, message: responseText, sender: "bob", origin: "local-sovereign" });
1809
1944
  } else {
1810
- await callCloudFunction("generateDeepDiveResponse", { conversationId, parentMessageId, userMessage: trimmed, isLocalModel: false, activePersonaId: null, localContext, cliMode: true });
1945
+ await callCloudFunction("generateDeepDiveResponse", {
1946
+ conversationId,
1947
+ parentMessageId,
1948
+ userMessage: trimmed,
1949
+ isLocalModel: false,
1950
+ activePersonaId: null,
1951
+ localContext,
1952
+ cliMode: true,
1953
+ // ─── REFERENCE PARAMS ───
1954
+ ...activeRef && { referenceAlias: activeRef.alias },
1955
+ ...activeRef?.filename && { referenceFilename: activeRef.filename }
1956
+ });
1811
1957
  const latestResult = await callCloudFunction("listCLIDeepDives", { conversationId, action: "getLatestSandboxMessage", parentMessageId });
1812
1958
  responseText = latestResult?.message || "Deep dive response saved.";
1813
1959
  }
@@ -1842,6 +1988,77 @@ Current request: ${trimmed}` : trimmed;
1842
1988
  deepDivePrompt();
1843
1989
  });
1844
1990
  }
1991
+ async function handleDeepDiveRefBrowser(domain, uid, threadDocPath, rl) {
1992
+ const refs = await fetchAvailableReferences(domain, uid);
1993
+ if (refs.length === 0) {
1994
+ console.log("");
1995
+ console.log(MUTED2(" No shared references available for your account."));
1996
+ console.log("");
1997
+ return null;
1998
+ }
1999
+ console.log("");
2000
+ console.log(AMBER(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2001
+ console.log(AMBER(" \u2551") + chalk5.bold(" \u{1F4CE} AVAILABLE REFERENCES ") + AMBER("\u2551"));
2002
+ console.log(AMBER(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2003
+ refs.forEach((ref, i) => {
2004
+ const line = ` ${String(i + 1).padStart(2)}. /${ref.alias.padEnd(18)} ${MUTED2(ref.repoDisplayName)}`;
2005
+ console.log(AMBER(" \u2551") + line);
2006
+ });
2007
+ console.log(AMBER(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2008
+ console.log(AMBER(" \u2551") + MUTED2(" Enter number to select, 0 to cancel ") + AMBER("\u2551"));
2009
+ console.log(AMBER(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2010
+ console.log("");
2011
+ const answer = await new Promise((resolve4) => {
2012
+ rl.question(AMBER(" Select reference: "), resolve4);
2013
+ });
2014
+ const num = parseInt(answer.trim());
2015
+ if (isNaN(num) || num === 0 || num < 1 || num > refs.length) {
2016
+ console.log(MUTED2(" Cancelled."));
2017
+ console.log("");
2018
+ return null;
2019
+ }
2020
+ const selected = refs[num - 1];
2021
+ const modeAnswer = await new Promise((resolve4) => {
2022
+ rl.question(AMBER(` /${selected.alias} \u2014 whole project (p) or specific file (f)? `), resolve4);
2023
+ });
2024
+ if (modeAnswer.trim().toLowerCase() === "f") {
2025
+ const filterAnswer = await new Promise((resolve4) => {
2026
+ rl.question(AMBER(" Filter files (or Enter for all): "), resolve4);
2027
+ });
2028
+ const files = await fetchProjectFiles(domain, selected.projectId, filterAnswer.trim());
2029
+ if (files.length === 0) {
2030
+ console.log(MUTED2(" No files found. Referencing whole project."));
2031
+ console.log("");
2032
+ return { alias: selected.alias };
2033
+ }
2034
+ console.log("");
2035
+ files.slice(0, 20).forEach((fp, i) => {
2036
+ console.log(MUTED2(` ${String(i + 1).padStart(2)}. ${fp}`));
2037
+ });
2038
+ console.log("");
2039
+ const fileAnswer = await new Promise((resolve4) => {
2040
+ rl.question(AMBER(" Select file (or Enter for whole project): "), resolve4);
2041
+ });
2042
+ const fileNum = parseInt(fileAnswer.trim());
2043
+ if (isNaN(fileNum) || fileNum < 1 || fileNum > files.length) {
2044
+ await saveStickyReference(threadDocPath, selected.alias, true);
2045
+ console.log("");
2046
+ console.log(AMBER(` \u{1F4CC} Sticky reference set: /${selected.alias}`));
2047
+ console.log("");
2048
+ return { alias: selected.alias };
2049
+ }
2050
+ const filename = files[fileNum - 1];
2051
+ console.log("");
2052
+ console.log(AMBER(` \u{1F4CE} File reference: /${selected.alias} \u2014 ${filename}`));
2053
+ console.log("");
2054
+ return { alias: selected.alias, filename };
2055
+ }
2056
+ await saveStickyReference(threadDocPath, selected.alias, true);
2057
+ console.log("");
2058
+ console.log(AMBER(` \u{1F4CC} Sticky reference set: /${selected.alias}`));
2059
+ console.log("");
2060
+ return { alias: selected.alias };
2061
+ }
1845
2062
 
1846
2063
  // src/ui/session-header.ts
1847
2064
  import chalk6 from "chalk";
@@ -2040,6 +2257,7 @@ var WARNING5 = chalk9.hex("#FFC107");
2040
2257
  var ERROR4 = chalk9.hex("#EF5350");
2041
2258
  var MUTED6 = chalk9.hex("#78909C");
2042
2259
  var MODE_CHAT3 = chalk9.hex("#26C6DA");
2260
+ var AMBER2 = chalk9.hex("#FFAB00");
2043
2261
  var lastConstraints = [];
2044
2262
  function registerChatCommand(program2) {
2045
2263
  program2.command("chat [message]").description("Chat with Bob \u2014 code-friendly engineering partner").option("-f, --file <path>", "Include a specific file as context").option("--no-context", "Skip local directory context").option("--personalized", "Use personalization mode (Tier 3 only)").option("--new", "Start a fresh conversation").option("-i, --interactive", "Enter interactive conversation mode").action(async (message, options) => {
@@ -2077,7 +2295,7 @@ ${fileContent}
2077
2295
  await sendMessage(message, config, conversationId, localContext, options.personalized || false, "standard", [], void 0);
2078
2296
  });
2079
2297
  }
2080
- async function sendMessage(message, config, conversationId, localContext, personalized, mode, history, existingRl) {
2298
+ async function sendMessage(message, config, conversationId, localContext, personalized, mode, history, existingRl, activeRef) {
2081
2299
  const providerReady = await ensureProvider();
2082
2300
  if (!providerReady) return "";
2083
2301
  config = getConfig();
@@ -2143,7 +2361,10 @@ ${fullContext}` : "") },
2143
2361
  userMessage: message,
2144
2362
  additionalContext: { localContext: fullContext || null },
2145
2363
  isLocalModel: false,
2146
- activePersonaId: null
2364
+ activePersonaId: null,
2365
+ // ─── REFERENCE PARAMS ───
2366
+ ...activeRef && { referenceAlias: activeRef.alias },
2367
+ ...activeRef?.filename && { referenceFilename: activeRef.filename }
2147
2368
  });
2148
2369
  response = result?.response || result?.data?.response || result?.text || result?.message || "No response received.";
2149
2370
  hasProjectContext = result?.hasProjectContext ?? null;
@@ -2156,7 +2377,21 @@ ${fullContext}` : "") },
2156
2377
  console.log(MUTED6(" Run `bob login` to authenticate, or set provider to local."));
2157
2378
  return "";
2158
2379
  }
2159
- const result = await callCloudFunction("chatWithBobStream", { userEmail: config.email, userId: config.uid, conversationId, userMessage: message, useContext: true, consultantModelId: "gemini-2.5-flash", useOrgContext: false, isPassalongActive: false, linkedConvoId: null, localContext: fullContext || null });
2380
+ const result = await callCloudFunction("chatWithBobStream", {
2381
+ userEmail: config.email,
2382
+ userId: config.uid,
2383
+ conversationId,
2384
+ userMessage: message,
2385
+ useContext: true,
2386
+ consultantModelId: "gemini-2.5-flash",
2387
+ useOrgContext: false,
2388
+ isPassalongActive: false,
2389
+ linkedConvoId: null,
2390
+ localContext: fullContext || null,
2391
+ // ─── REFERENCE PARAMS ───
2392
+ ...activeRef && { referenceAlias: activeRef.alias },
2393
+ ...activeRef?.filename && { referenceFilename: activeRef.filename }
2394
+ });
2160
2395
  response = result?.text || result?.response || result?.message || "No response received.";
2161
2396
  hasProjectContext = result?.hasProjectContext ?? null;
2162
2397
  constraints = result?.constraints || [];
@@ -2197,15 +2432,22 @@ async function runInteractiveSession(config, conversationId, localContext, perso
2197
2432
  renderSessionHeader("chat");
2198
2433
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
2199
2434
  const history = [];
2435
+ const domain = config.email?.split("@").pop()?.toLowerCase() ?? "";
2436
+ const uid = config.uid ?? "";
2437
+ const convoDocPath = `Organizations/${domain}/OrgUsers/${uid}/BobGlobalChat/${conversationId}`;
2438
+ let stickyRef = await loadStickyReference(convoDocPath);
2200
2439
  if (initialMessage) {
2201
- const response = await sendMessage(initialMessage, config, conversationId, localContext, personalized, mode, history, rl);
2440
+ const inlineRef = detectReference(initialMessage);
2441
+ const activeRef = inlineRef ?? stickyRef ?? null;
2442
+ const response = await sendMessage(initialMessage, config, conversationId, localContext, personalized, mode, history, rl, activeRef);
2202
2443
  if (response) {
2203
2444
  history.push({ role: "user", content: initialMessage });
2204
2445
  history.push({ role: "assistant", content: response });
2205
2446
  }
2206
2447
  }
2207
2448
  const prompt = () => {
2208
- rl.question(SUCCESS6(" You: "), async (input) => {
2449
+ const promptText = stickyRef ? AMBER2(` \u{1F4CC} /${stickyRef.alias} \u203A `) : SUCCESS6(" You: ");
2450
+ rl.question(promptText, async (input) => {
2209
2451
  const trimmed = input.trim();
2210
2452
  if (!trimmed) {
2211
2453
  prompt();
@@ -2244,6 +2486,24 @@ async function runInteractiveSession(config, conversationId, localContext, perso
2244
2486
  prompt();
2245
2487
  return;
2246
2488
  }
2489
+ if (trimmed === "/ref") {
2490
+ stickyRef = await handleRefBrowser(domain, uid, convoDocPath, rl);
2491
+ prompt();
2492
+ return;
2493
+ }
2494
+ if (trimmed === "/pin") {
2495
+ if (stickyRef) {
2496
+ await saveStickyReference(convoDocPath, null, false);
2497
+ stickyRef = null;
2498
+ console.log("");
2499
+ console.log(MUTED6(" \u{1F4CC} Sticky reference cleared."));
2500
+ console.log("");
2501
+ } else {
2502
+ stickyRef = await handleRefBrowser(domain, uid, convoDocPath, rl);
2503
+ }
2504
+ prompt();
2505
+ return;
2506
+ }
2247
2507
  if (trimmed.startsWith("/include ")) {
2248
2508
  const filePath = trimmed.slice(9).trim();
2249
2509
  const content = readFileContent(filePath);
@@ -2314,7 +2574,13 @@ ${content}
2314
2574
  prompt();
2315
2575
  return;
2316
2576
  }
2317
- const response = await sendMessage(trimmed, config, conversationId, localContext, personalized, mode, history, rl);
2577
+ const inlineRef = detectReference(trimmed);
2578
+ const activeRef = inlineRef ?? stickyRef ?? null;
2579
+ if (activeRef) {
2580
+ console.log("");
2581
+ console.log(AMBER2(` \u{1F4CE} Referencing /${activeRef.alias}${activeRef.filename ? ` \u2014 ${activeRef.filename}` : ""}...`));
2582
+ }
2583
+ const response = await sendMessage(trimmed, config, conversationId, localContext, personalized, mode, history, rl, activeRef);
2318
2584
  if (response) {
2319
2585
  history.push({ role: "user", content: trimmed });
2320
2586
  history.push({ role: "assistant", content: response });
@@ -2324,6 +2590,81 @@ ${content}
2324
2590
  };
2325
2591
  prompt();
2326
2592
  }
2593
+ async function handleRefBrowser(domain, uid, docPath, rl) {
2594
+ const refs = await fetchAvailableReferences(domain, uid);
2595
+ if (refs.length === 0) {
2596
+ console.log("");
2597
+ console.log(MUTED6(" No shared references available for your account."));
2598
+ console.log("");
2599
+ return null;
2600
+ }
2601
+ console.log("");
2602
+ console.log(AMBER2(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2603
+ console.log(AMBER2(" \u2551") + chalk9.bold(" \u{1F4CE} AVAILABLE REFERENCES ") + AMBER2("\u2551"));
2604
+ console.log(AMBER2(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2605
+ refs.forEach((ref, i) => {
2606
+ const line = ` ${String(i + 1).padStart(2)}. /${ref.alias.padEnd(18)} ${MUTED6(ref.repoDisplayName)}`;
2607
+ console.log(AMBER2(" \u2551") + line);
2608
+ });
2609
+ console.log(AMBER2(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
2610
+ console.log(AMBER2(" \u2551") + MUTED6(" Enter number to select, 0 to cancel ") + AMBER2("\u2551"));
2611
+ console.log(AMBER2(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2612
+ console.log("");
2613
+ const answer = await new Promise((resolve4) => {
2614
+ rl.question(AMBER2(" Select reference: "), resolve4);
2615
+ });
2616
+ const num = parseInt(answer.trim());
2617
+ if (isNaN(num) || num === 0 || num < 1 || num > refs.length) {
2618
+ console.log(MUTED6(" Cancelled."));
2619
+ console.log("");
2620
+ return null;
2621
+ }
2622
+ const selected = refs[num - 1];
2623
+ const modeAnswer = await new Promise((resolve4) => {
2624
+ rl.question(AMBER2(` /${selected.alias} \u2014 whole project (p) or specific file (f)? `), resolve4);
2625
+ });
2626
+ if (modeAnswer.trim().toLowerCase() === "f") {
2627
+ return await handleFileBrowser(domain, selected, rl, docPath);
2628
+ }
2629
+ await saveStickyReference(docPath, selected.alias, true);
2630
+ console.log("");
2631
+ console.log(AMBER2(` \u{1F4CC} Sticky reference set: /${selected.alias}`));
2632
+ console.log("");
2633
+ return { alias: selected.alias };
2634
+ }
2635
+ async function handleFileBrowser(domain, project, rl, docPath) {
2636
+ const filterAnswer = await new Promise((resolve4) => {
2637
+ rl.question(AMBER2(" Filter files (or Enter for all): "), resolve4);
2638
+ });
2639
+ const files = await fetchProjectFiles(domain, project.projectId, filterAnswer.trim());
2640
+ if (files.length === 0) {
2641
+ console.log(MUTED6(" No files found. Referencing whole project."));
2642
+ console.log("");
2643
+ return { alias: project.alias };
2644
+ }
2645
+ console.log("");
2646
+ console.log(AMBER2(` \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`));
2647
+ console.log(AMBER2(` \u2551`) + chalk9.bold(` \u{1F4C4} /${project.alias} \u2014 Files `) + AMBER2(`\u2551`));
2648
+ console.log(AMBER2(` \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563`));
2649
+ files.slice(0, 20).forEach((fp, i) => {
2650
+ const line = ` ${String(i + 1).padStart(2)}. ${fp}`;
2651
+ console.log(AMBER2(" \u2551") + MUTED6(line.slice(0, 42).padEnd(42)) + AMBER2("\u2551"));
2652
+ });
2653
+ console.log(AMBER2(` \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`));
2654
+ console.log("");
2655
+ const fileAnswer = await new Promise((resolve4) => {
2656
+ rl.question(AMBER2(" Select file (or Enter for whole project): "), resolve4);
2657
+ });
2658
+ const fileNum = parseInt(fileAnswer.trim());
2659
+ if (isNaN(fileNum) || fileNum < 1 || fileNum > files.length) {
2660
+ return { alias: project.alias };
2661
+ }
2662
+ const filename = files[fileNum - 1];
2663
+ console.log("");
2664
+ console.log(AMBER2(` \u{1F4CE} File reference: /${project.alias} \u2014 ${filename}`));
2665
+ console.log("");
2666
+ return { alias: project.alias, filename };
2667
+ }
2327
2668
 
2328
2669
  // src/commands/consult.ts
2329
2670
  import chalk10 from "chalk";
@@ -3462,7 +3803,7 @@ function registerAnalyseCommand(program2) {
3462
3803
  program2.command("analyse").description("Analyse the current project for bugs, features, improvements, and upgrades").option("--results", "Show analysis dashboard or filtered list").option("--bugs", "Show bugs list (interactive)").option("--features", "Show features list (interactive)").option("--improvements", "Show improvements list (interactive)").option("--upgrades", "Show upgrades list (interactive)").option("--sort <method>", "Sort by: priority (default) or file").option("--search <query>", "Filter results by keyword").option("--status", "Show current analysis job status").option("--auto", "Auto-fix mode: Bob triages and MiniBob implements").option("--confidence <number>", "Confidence gate for auto-fix (default: 90)", "90").option("--priority <level>", "Priority gate for auto-fix: critical, high, medium, low (default: critical)", "critical").action(async (options) => {
3463
3804
  const config = getConfig();
3464
3805
  if (options.auto) {
3465
- const { runAutoFix } = await import("./analyse-auto-I7TIDS4E.js");
3806
+ const { runAutoFix } = await import("./analyse-auto-VFZGDTTQ.js");
3466
3807
  const category = options.bugs ? "bugs" : options.features ? "features" : options.improvements ? "improvements" : options.upgrades ? "upgrades" : void 0;
3467
3808
  await runAutoFix({
3468
3809
  category,
@@ -3472,7 +3813,7 @@ function registerAnalyseCommand(program2) {
3472
3813
  return;
3473
3814
  }
3474
3815
  if (options.bugs || options.features || options.improvements || options.upgrades) {
3475
- const { showInteractiveResults } = await import("./analyse-results-QSTTMRQE.js");
3816
+ const { showInteractiveResults } = await import("./analyse-results-XAVKSCF4.js");
3476
3817
  const category = options.bugs ? "bugs" : options.features ? "features" : options.improvements ? "improvements" : "upgrades";
3477
3818
  await showInteractiveResults(config, category, options.sort, options.search);
3478
3819
  return;
@@ -3833,7 +4174,7 @@ import * as fs8 from "fs";
3833
4174
  import * as path9 from "path";
3834
4175
  var RED = chalk18.hex("#EF5350");
3835
4176
  var GREEN = chalk18.hex("#66BB6A");
3836
- var AMBER2 = chalk18.hex("#FFAB00");
4177
+ var AMBER3 = chalk18.hex("#FFAB00");
3837
4178
  var BLUE = chalk18.hex("#42A5F5");
3838
4179
  var GRAY = chalk18.gray;
3839
4180
  var BORDER4 = chalk18.hex("#455A64");
@@ -3927,7 +4268,7 @@ async function runTier3Autonomy(config, conversationId) {
3927
4268
  if (text.includes("[ACTION:GITHUB_PUSH_REQUEST:")) {
3928
4269
  console.log("");
3929
4270
  console.log(GREEN(" \u2705 All tasks complete!"));
3930
- console.log(AMBER2(" \u{1F4E4} MiniBob wants to push to GitHub."));
4271
+ console.log(AMBER3(" \u{1F4E4} MiniBob wants to push to GitHub."));
3931
4272
  const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
3932
4273
  const answer = await new Promise((resolve4) => {
3933
4274
  rl.question(CYAN(" Approve push? (y/n): "), resolve4);
@@ -3965,7 +4306,7 @@ async function runTier3Autonomy(config, conversationId) {
3965
4306
  }
3966
4307
  console.log("");
3967
4308
  console.log(BORDER4(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
3968
- console.log(BORDER4(" \u2551") + AMBER2(" \u25C6 AUTONOMY SESSION COMPLETE"));
4309
+ console.log(BORDER4(" \u2551") + AMBER3(" \u25C6 AUTONOMY SESSION COMPLETE"));
3969
4310
  console.log(BORDER4(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
3970
4311
  console.log(BORDER4(" \u2551") + GREEN(` \u2705 Tasks completed: ${tasksDone}/${totalTasks}`));
3971
4312
  console.log(BORDER4(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
@@ -4039,7 +4380,7 @@ async function runTier1Autonomy(config, options) {
4039
4380
  console.log("");
4040
4381
  console.log("");
4041
4382
  console.log(BORDER4(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
4042
- console.log(BORDER4(" \u2551") + AMBER2(" \u25C6 MINIBOB AUTONOMY REPORT"));
4383
+ console.log(BORDER4(" \u2551") + AMBER3(" \u25C6 MINIBOB AUTONOMY REPORT"));
4043
4384
  console.log(BORDER4(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
4044
4385
  console.log(BORDER4(" \u2551") + GREEN(` \u2705 Fixed: ${fixed} files`));
4045
4386
  if (failed > 0) {
@@ -4100,7 +4441,7 @@ async function showAutonomyStatus(config, conversationId) {
4100
4441
  spinner.stop();
4101
4442
  if (result?.lines && result.lines.length > 0) {
4102
4443
  console.log("");
4103
- console.log(AMBER2(" \u25C6 Recent Autonomy Activity:"));
4444
+ console.log(AMBER3(" \u25C6 Recent Autonomy Activity:"));
4104
4445
  console.log(GRAY(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
4105
4446
  for (const line of result.lines) {
4106
4447
  console.log(GRAY(` ${line.text}`));
@@ -4218,7 +4559,7 @@ var lastLocalTodoLines = 0;
4218
4559
  function renderLocalTodoList(queue) {
4219
4560
  const lines = [];
4220
4561
  lines.push("");
4221
- lines.push(AMBER2(" \u{1F4CB} MiniBob Autonomy Queue"));
4562
+ lines.push(AMBER3(" \u{1F4CB} MiniBob Autonomy Queue"));
4222
4563
  lines.push(GRAY(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
4223
4564
  for (let i = 0; i < queue.length; i++) {
4224
4565
  const task = queue[i];
@@ -4232,7 +4573,7 @@ function renderLocalTodoList(queue) {
4232
4573
  break;
4233
4574
  case "working":
4234
4575
  icon = "\u23F3";
4235
- color = AMBER2;
4576
+ color = AMBER3;
4236
4577
  break;
4237
4578
  case "failed":
4238
4579
  icon = "\u2717";
@@ -4283,7 +4624,7 @@ import * as path10 from "path";
4283
4624
  import * as crypto2 from "crypto";
4284
4625
  import axios from "axios";
4285
4626
  var GREEN2 = chalk19.hex("#66BB6A");
4286
- var AMBER3 = chalk19.hex("#FFAB00");
4627
+ var AMBER4 = chalk19.hex("#FFAB00");
4287
4628
  var RED2 = chalk19.hex("#EF5350");
4288
4629
  var GRAY2 = chalk19.gray;
4289
4630
  var CYAN2 = chalk19.cyan;
@@ -4413,11 +4754,11 @@ function registerServeCommand(program2) {
4413
4754
  console.log(GRAY2(` Your current tier: ${userTier}`));
4414
4755
  console.log("");
4415
4756
  if (isOrgUser) {
4416
- console.log(AMBER3(" \u{1F3E2} Contact your organization administrator to upgrade your tier."));
4757
+ console.log(AMBER4(" \u{1F3E2} Contact your organization administrator to upgrade your tier."));
4417
4758
  console.log(GRAY2(` Organization: ${domain}`));
4418
4759
  console.log(GRAY2(" Admin Dashboard: https://bobs-workshop.web.app/#/bobsadmindashboard"));
4419
4760
  } else {
4420
- console.log(AMBER3(" \u{1F680} Upgrade to unlock remote execution:"));
4761
+ console.log(AMBER4(" \u{1F680} Upgrade to unlock remote execution:"));
4421
4762
  console.log("");
4422
4763
  console.log(GRAY2(" Starter \u2014 15s polling, 15 min idle timeout"));
4423
4764
  console.log(GRAY2(" Pro \u2014 10s polling, sleep mode, 1 hour idle timeout"));
@@ -4445,7 +4786,7 @@ async function startActiveBob(config, sessionId, machineId, projectName, tierCon
4445
4786
  console.log(BORDER5(" \u2551") + GRAY2(` Project: ${projectName} (${process.cwd()})`));
4446
4787
  console.log(BORDER5(" \u2551") + GRAY2(` Session: ${sessionId.slice(0, 30)}...`));
4447
4788
  console.log(BORDER5(" \u2551") + GRAY2(` Convo: ${config.conversationId?.slice(0, 24)}...`));
4448
- console.log(BORDER5(" \u2551") + AMBER3(` Tier: ${userTier}`));
4789
+ console.log(BORDER5(" \u2551") + AMBER4(` Tier: ${userTier}`));
4449
4790
  console.log(BORDER5(" \u2551") + GRAY2(` Polling: every ${tierConfig.activeInterval / 1e3}s`));
4450
4791
  if (tierConfig.sleepInterval) {
4451
4792
  console.log(BORDER5(" \u2551") + GRAY2(` Sleep: every ${tierConfig.sleepInterval / 1e3}s after ${tierConfig.idleThreshold / 6e4} min idle`));
@@ -4507,7 +4848,7 @@ async function startActiveBob(config, sessionId, machineId, projectName, tierCon
4507
4848
  const timeSinceLastCommand = Date.now() - lastCommandTime;
4508
4849
  if (tierConfig.extendedIdleTimeout && timeSinceLastCommand > tierConfig.extendedIdleTimeout) {
4509
4850
  console.log("");
4510
- console.log(AMBER3(` \u23F8\uFE0F No commands received in ${Math.round(tierConfig.extendedIdleTimeout / 6e4)} minutes.`));
4851
+ console.log(AMBER4(` \u23F8\uFE0F No commands received in ${Math.round(tierConfig.extendedIdleTimeout / 6e4)} minutes.`));
4511
4852
  console.log(GRAY2(" Active Bob is going offline. Run `bob serve` to restart."));
4512
4853
  console.log("");
4513
4854
  try {
@@ -4543,7 +4884,7 @@ async function startActiveBob(config, sessionId, machineId, projectName, tierCon
4543
4884
  }
4544
4885
  lastCommandTime = Date.now();
4545
4886
  const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
4546
- console.log(AMBER3(` [${timestamp}] \u23F3 Received: ${type}${payload.message ? ` "${payload.message.slice(0, 40)}${payload.message.length > 40 ? "..." : ""}"` : ""}`));
4887
+ console.log(AMBER4(` [${timestamp}] \u23F3 Received: ${type}${payload.message ? ` "${payload.message.slice(0, 40)}${payload.message.length > 40 ? "..." : ""}"` : ""}`));
4547
4888
  const commandResult = await executeRemoteCommand(type, payload, config);
4548
4889
  await callCloudFunction("completeRemoteCommand", {
4549
4890
  conversationId: config.conversationId,
@@ -5414,7 +5755,7 @@ import ora10 from "ora";
5414
5755
  // src/core/cloud-profiler.ts
5415
5756
  import chalk21 from "chalk";
5416
5757
  import ora8 from "ora";
5417
- var AMBER4 = chalk21.hex("#FFAB00");
5758
+ var AMBER5 = chalk21.hex("#FFAB00");
5418
5759
  var ORANGE = chalk21.hex("#E66F24");
5419
5760
  var GREEN3 = chalk21.hex("#66BB6A");
5420
5761
  var CYAN3 = chalk21.cyan;
@@ -5438,7 +5779,7 @@ function renderProgressBar(score, width = 30) {
5438
5779
  function renderChunkBar(current, total, width = 30) {
5439
5780
  const filled = Math.round(current / total * width);
5440
5781
  const empty = width - filled;
5441
- return AMBER4("\u2588".repeat(filled)) + chalk21.hex("#333333")("\u2591".repeat(empty)) + GRAY3(` ${current}/${total}`);
5782
+ return AMBER5("\u2588".repeat(filled)) + chalk21.hex("#333333")("\u2591".repeat(empty)) + GRAY3(` ${current}/${total}`);
5442
5783
  }
5443
5784
  function truncate2(text, max) {
5444
5785
  if (!text) return "";
@@ -5485,7 +5826,7 @@ async function runCloudProfiler(options) {
5485
5826
  throw new Error("Cloud profiling requires authentication. Run `bob login` first.");
5486
5827
  }
5487
5828
  console.log("");
5488
- console.log(AMBER4(` \u{1F9EC} Running cloud ${scope} profiling (Power tier)...`));
5829
+ console.log(AMBER5(` \u{1F9EC} Running cloud ${scope} profiling (Power tier)...`));
5489
5830
  console.log("");
5490
5831
  const spinner = ora8({ text: CYAN3(" Initiating profiling job..."), spinner: "dots" }).start();
5491
5832
  const startResult = await callCloudFunction("startCloudProfiling", {
@@ -5646,7 +5987,7 @@ async function runCloudProfiler(options) {
5646
5987
  const archetype = archMatch ? archMatch[1].trim() : "profiled";
5647
5988
  const description = descMatch ? truncate2(descMatch[1].trim(), 50) : "";
5648
5989
  renderBox("\u{1F3AF}", "Stage 4: Decision Profile", [
5649
- `${GRAY3("Archetype:")} ${AMBER4(archetype)}`,
5990
+ `${GRAY3("Archetype:")} ${AMBER5(archetype)}`,
5650
5991
  description ? `${GRAY3('"' + description + '"')}` : ""
5651
5992
  ].filter(Boolean));
5652
5993
  stage4Rendered = true;
@@ -5697,7 +6038,7 @@ async function runCloudProfiler(options) {
5697
6038
  const archetype = archMatch ? archMatch[1].trim() : "profiled";
5698
6039
  const edge = edgeMatch ? parseInt(edgeMatch[1]) : 0;
5699
6040
  renderBox("\u{1F3AF}", "Weekly Decision Profile", [
5700
- `${GRAY3("Archetype:")} ${AMBER4(archetype)}`,
6041
+ `${GRAY3("Archetype:")} ${AMBER5(archetype)}`,
5701
6042
  `${GRAY3("Edge Score:")} ${renderProgressBar(edge)}`
5702
6043
  ]);
5703
6044
  weeklyDecisionRendered = true;
@@ -5715,7 +6056,7 @@ async function runCloudProfiler(options) {
5715
6056
  const synthMatch = msg.match(/Weekly synthesis complete: (.+)/);
5716
6057
  const synthesis = synthMatch ? truncate2(synthMatch[1].trim(), 50) : "synthesized";
5717
6058
  renderBox("\u{1F9EC}", "Weekly DNA Synthesis", [
5718
- `${GRAY3("Archetype:")} ${AMBER4(synthesis)}`,
6059
+ `${GRAY3("Archetype:")} ${AMBER5(synthesis)}`,
5719
6060
  `${GRAY3("Your weekly personality profile has been updated.")}`
5720
6061
  ]);
5721
6062
  weeklySynthesisRendered = true;
@@ -5747,7 +6088,7 @@ async function runCloudProfiler(options) {
5747
6088
  const archMatch = msg.match(/Monthly synthesis complete: (.+)/);
5748
6089
  const archetype = archMatch ? truncate2(archMatch[1].trim(), 50) : "synthesized";
5749
6090
  renderBox("\u{1F9EC}", "Monthly DNA Synthesis", [
5750
- `${GRAY3("Monthly Archetype:")} ${AMBER4(archetype)}`,
6091
+ `${GRAY3("Monthly Archetype:")} ${AMBER5(archetype)}`,
5751
6092
  `${GRAY3("Your complete monthly personality profile is now active.")}`,
5752
6093
  `${GRAY3("Bob will adapt to match your patterns going forward.")}`
5753
6094
  ]);
@@ -6075,7 +6416,7 @@ async function renderProfileDashboard() {
6075
6416
 
6076
6417
  // src/commands/profile.ts
6077
6418
  import * as path11 from "path";
6078
- var AMBER5 = chalk23.hex("#FFAB00");
6419
+ var AMBER6 = chalk23.hex("#FFAB00");
6079
6420
  var GREEN4 = chalk23.hex("#66BB6A");
6080
6421
  var BLUE2 = chalk23.hex("#42A5F5");
6081
6422
  var GRAY4 = chalk23.gray;
@@ -6133,7 +6474,7 @@ async function handleCloudProfile(scope) {
6133
6474
  return;
6134
6475
  }
6135
6476
  console.log("");
6136
- console.log(AMBER5(` \u{1F9EC} Running cloud ${scope} profiling (Power tier)...`));
6477
+ console.log(AMBER6(` \u{1F9EC} Running cloud ${scope} profiling (Power tier)...`));
6137
6478
  console.log("");
6138
6479
  try {
6139
6480
  await runCloudProfiler({
@@ -6170,14 +6511,14 @@ function showCurrentProfile() {
6170
6511
  const dna = loadCurrentDNA();
6171
6512
  if (!dna) {
6172
6513
  console.log("");
6173
- console.log(AMBER5(" \u26A0\uFE0F No profile generated yet."));
6514
+ console.log(AMBER6(" \u26A0\uFE0F No profile generated yet."));
6174
6515
  console.log(GRAY4(" Run `bob profile --today` to generate your first profile."));
6175
6516
  console.log("");
6176
6517
  return;
6177
6518
  }
6178
6519
  console.log("");
6179
6520
  console.log(BORDER9(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
6180
- console.log(BORDER9(" \u2551") + AMBER5(" \u{1F9EC} Your Current DNA Profile"));
6521
+ console.log(BORDER9(" \u2551") + AMBER6(" \u{1F9EC} Your Current DNA Profile"));
6181
6522
  console.log(BORDER9(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
6182
6523
  console.log(BORDER9(" \u2551") + CYAN4(` Archetype: ${dna.archetype || "Unknown"}`));
6183
6524
  console.log(BORDER9(" \u2551") + GRAY4(` Communication: ${dna.communicationStyle || "Unknown"}`));
@@ -6204,7 +6545,7 @@ async function generateDailyProfile(config) {
6204
6545
  const messages = await getTodayMessages();
6205
6546
  if (messages.length === 0) {
6206
6547
  console.log("");
6207
- console.log(AMBER5(" \u26A0\uFE0F No conversations found for today."));
6548
+ console.log(AMBER6(" \u26A0\uFE0F No conversations found for today."));
6208
6549
  console.log(GRAY4(" Chat with Bob first, then run this command."));
6209
6550
  console.log("");
6210
6551
  return;
@@ -6299,7 +6640,7 @@ IMPORTANT: Only include assessments you have EVIDENCE for. Use exact quotes from
6299
6640
  saveDailyProfile(profile);
6300
6641
  console.log("");
6301
6642
  console.log(BORDER9(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
6302
- console.log(BORDER9(" \u2551") + AMBER5(` \u{1F9EC} Daily Profile \u2014 ${today}`));
6643
+ console.log(BORDER9(" \u2551") + AMBER6(` \u{1F9EC} Daily Profile \u2014 ${today}`));
6303
6644
  console.log(BORDER9(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
6304
6645
  console.log(BORDER9(" \u2551") + CYAN4(` Communication: ${parsed.communicationStyle?.tone || "Unknown"} (${parsed.communicationStyle?.confidence || 0}%)`));
6305
6646
  console.log(BORDER9(" \u2551") + CYAN4(` Mentality: ${parsed.mentality?.approach || "Unknown"}, ${parsed.mentality?.optimism || ""} (${parsed.mentality?.confidence || 0}%)`));
@@ -6326,7 +6667,7 @@ async function generateWeeklyProfile(config) {
6326
6667
  const dailies = loadDailyProfiles(7);
6327
6668
  if (dailies.length === 0) {
6328
6669
  console.log("");
6329
- console.log(AMBER5(" \u26A0\uFE0F No daily profiles found."));
6670
+ console.log(AMBER6(" \u26A0\uFE0F No daily profiles found."));
6330
6671
  console.log(GRAY4(" Run `bob profile --today` for at least a few days first."));
6331
6672
  console.log("");
6332
6673
  return;
@@ -6388,7 +6729,7 @@ Use REAL quotes from the daily profiles as evidence. Show how the person CHANGED
6388
6729
  saveWeeklyProfile(profile);
6389
6730
  console.log("");
6390
6731
  console.log(BORDER9(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
6391
- console.log(BORDER9(" \u2551") + AMBER5(` \u{1F9EC} Weekly Profile \u2014 ${weekId}`));
6732
+ console.log(BORDER9(" \u2551") + AMBER6(` \u{1F9EC} Weekly Profile \u2014 ${weekId}`));
6392
6733
  console.log(BORDER9(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
6393
6734
  console.log(BORDER9(" \u2551") + CYAN4(` Trajectory: ${parsed.trajectory || "Unknown"}`));
6394
6735
  console.log(BORDER9(" \u2551") + GRAY4(` Energy: ${parsed.energyPattern || "Unknown"}`));
@@ -6417,7 +6758,7 @@ async function generateMonthlyProfile(config) {
6417
6758
  const weeklies = loadWeeklyProfiles(5);
6418
6759
  if (dailies.length === 0 && weeklies.length === 0) {
6419
6760
  console.log("");
6420
- console.log(AMBER5(" \u26A0\uFE0F No profiles found for this month."));
6761
+ console.log(AMBER6(" \u26A0\uFE0F No profiles found for this month."));
6421
6762
  console.log(GRAY4(" Run `bob profile --today` daily and `bob profile --week` weekly first."));
6422
6763
  console.log("");
6423
6764
  return;
@@ -6487,7 +6828,7 @@ Show the JOURNEY, not just the destination. Use real quotes as evidence for ever
6487
6828
  saveMonthlyProfile(profile);
6488
6829
  console.log("");
6489
6830
  console.log(BORDER9(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
6490
- console.log(BORDER9(" \u2551") + AMBER5(` \u{1F9EC} Monthly Profile \u2014 ${monthId}`));
6831
+ console.log(BORDER9(" \u2551") + AMBER6(` \u{1F9EC} Monthly Profile \u2014 ${monthId}`));
6491
6832
  console.log(BORDER9(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
6492
6833
  console.log(BORDER9(" \u2551") + CYAN4(` Archetype: ${parsed.personalitySnapshot?.archetype || "Unknown"}`));
6493
6834
  console.log(BORDER9(" \u2551"));
@@ -6541,7 +6882,7 @@ var BRAND = chalk24.hex("#E66F24");
6541
6882
  var CYAN5 = chalk24.cyan;
6542
6883
  var GREEN5 = chalk24.hex("#66BB6A");
6543
6884
  var RED5 = chalk24.hex("#EF5350");
6544
- var AMBER6 = chalk24.hex("#FFAB00");
6885
+ var AMBER7 = chalk24.hex("#FFAB00");
6545
6886
  var GRAY5 = chalk24.gray;
6546
6887
  var BORDER10 = chalk24.hex("#455A64");
6547
6888
  var BOB_DIR3 = path12.join(os3.homedir(), ".bob");
@@ -6609,19 +6950,19 @@ function normalizeFilePath(filePath) {
6609
6950
  function handleBackupError(error) {
6610
6951
  if (error.message?.includes("BOB_BACKUP_LICENSE_REQUIRED")) {
6611
6952
  console.log("");
6612
- console.log(AMBER6(" \u26A0\uFE0F No active backup license found."));
6953
+ console.log(AMBER7(" \u26A0\uFE0F No active backup license found."));
6613
6954
  console.log(GRAY5(" Purchase one at: app.bobsworkshop.com/iap \u2192 Bob Backup"));
6614
6955
  } else if (error.message?.includes("STORAGE_QUOTA_EXCEEDED")) {
6615
6956
  console.log("");
6616
- console.log(AMBER6(" \u26A0\uFE0F Storage quota exceeded."));
6957
+ console.log(AMBER7(" \u26A0\uFE0F Storage quota exceeded."));
6617
6958
  console.log(GRAY5(" Purchase a storage pack: app.bobsworkshop.com/iap \u2192 Storage Packs"));
6618
6959
  } else if (error.message?.includes("ARCHIVE_SLOTS_EXHAUSTED")) {
6619
6960
  console.log("");
6620
- console.log(AMBER6(" \u26A0\uFE0F All archive slots are used."));
6961
+ console.log(AMBER7(" \u26A0\uFE0F All archive slots are used."));
6621
6962
  console.log(GRAY5(" Upgrade your Workshop SKU for more archive slots."));
6622
6963
  } else if (error.message?.includes("GRID_REQUIRED")) {
6623
6964
  console.log("");
6624
- console.log(AMBER6(" \u26A0\uFE0F Global backup requires the Grid Workshop plan."));
6965
+ console.log(AMBER7(" \u26A0\uFE0F Global backup requires the Grid Workshop plan."));
6625
6966
  console.log(GRAY5(" Upgrade at: app.bobsworkshop.com/iap \u2192 Workshop"));
6626
6967
  } else {
6627
6968
  console.log("");
@@ -6759,7 +7100,7 @@ async function runBackup(options) {
6759
7100
  }
6760
7101
  recordSpinner.succeed(GREEN5(" Recording usage ..."));
6761
7102
  } catch {
6762
- recordSpinner.warn(AMBER6(" Usage recording failed (non-fatal). Backup was saved."));
7103
+ recordSpinner.warn(AMBER7(" Usage recording failed (non-fatal). Backup was saved."));
6763
7104
  }
6764
7105
  const now = (/* @__PURE__ */ new Date()).toLocaleString();
6765
7106
  console.log(BORDER10(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
@@ -6884,7 +7225,7 @@ async function runSourceBackup(options) {
6884
7225
  await callCloudFunction("cliBackupLicense", recordPayload);
6885
7226
  recordSpinner.succeed(GREEN5(" Recording usage ..."));
6886
7227
  } catch {
6887
- recordSpinner.warn(AMBER6(" Usage recording failed (non-fatal). Backup was saved."));
7228
+ recordSpinner.warn(AMBER7(" Usage recording failed (non-fatal). Backup was saved."));
6888
7229
  }
6889
7230
  const now = (/* @__PURE__ */ new Date()).toLocaleString();
6890
7231
  console.log(BORDER10(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
@@ -6984,12 +7325,12 @@ function registerBackupCommand(program2) {
6984
7325
  }
6985
7326
  if (archives.length > 0) {
6986
7327
  console.log(BORDER10(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
6987
- console.log(BORDER10(" \u2551") + AMBER6(" Named Archives"));
7328
+ console.log(BORDER10(" \u2551") + AMBER7(" Named Archives"));
6988
7329
  console.log(BORDER10(" \u2551") + GRAY5(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
6989
7330
  for (const a of archives) {
6990
7331
  const date = new Date(a.createdAt).toLocaleString();
6991
7332
  const expires = new Date(a.expiresAt).toLocaleString();
6992
- console.log(BORDER10(" \u2551") + ` \u{1F4CC} ${AMBER6(a.name.padEnd(24))} ${GRAY5(formatBytes(a.sizeGB * 1024 * 1024 * 1024))}`);
7333
+ console.log(BORDER10(" \u2551") + ` \u{1F4CC} ${AMBER7(a.name.padEnd(24))} ${GRAY5(formatBytes(a.sizeGB * 1024 * 1024 * 1024))}`);
6993
7334
  console.log(BORDER10(" \u2551") + GRAY5(` Created: ${date} | Expires: ${expires}`));
6994
7335
  }
6995
7336
  }
@@ -7036,7 +7377,7 @@ function registerBackupCommand(program2) {
7036
7377
  if (versions.length === 0 && archives.length === 0) {
7037
7378
  console.log("");
7038
7379
  const scopeMsg = isSource ? filePath ? `file "${filePath}"` : `source of ${projectName}` : isGlobal ? "global" : projectName;
7039
- console.log(AMBER6(` \u26A0\uFE0F No backups found for ${scopeMsg}.`));
7380
+ console.log(AMBER7(` \u26A0\uFE0F No backups found for ${scopeMsg}.`));
7040
7381
  console.log("");
7041
7382
  return;
7042
7383
  }
@@ -7052,11 +7393,11 @@ function registerBackupCommand(program2) {
7052
7393
  }
7053
7394
  }
7054
7395
  if (archives.length > 0) {
7055
- choices.push(new inquirer.Separator(AMBER6(" \u2500\u2500 Named Archives \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")));
7396
+ choices.push(new inquirer.Separator(AMBER7(" \u2500\u2500 Named Archives \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")));
7056
7397
  for (const a of archives) {
7057
7398
  const date = new Date(a.createdAt).toLocaleString();
7058
7399
  choices.push({
7059
- name: ` \u{1F4CC} ${AMBER6(a.name.padEnd(24))} ${GRAY5(date)}`,
7400
+ name: ` \u{1F4CC} ${AMBER7(a.name.padEnd(24))} ${GRAY5(date)}`,
7060
7401
  value: { type: "archive", archiveId: a.archiveId, name: a.name }
7061
7402
  });
7062
7403
  }
@@ -7080,20 +7421,20 @@ function registerBackupCommand(program2) {
7080
7421
  const label = selected.type === "archive" ? `archive "${selected.name}"` : selected.label;
7081
7422
  console.log("");
7082
7423
  if (isSource && filePath) {
7083
- console.log(AMBER6(` \u26A0\uFE0F This will restore ${filePath} from ${label}.`));
7424
+ console.log(AMBER7(` \u26A0\uFE0F This will restore ${filePath} from ${label}.`));
7084
7425
  console.log(GRAY5(" Current file will be backed up to .bob-backups/ first."));
7085
7426
  } else if (isSource) {
7086
- console.log(AMBER6(` \u26A0\uFE0F This will restore source code of ${projectName} from ${label}.`));
7427
+ console.log(AMBER7(` \u26A0\uFE0F This will restore source code of ${projectName} from ${label}.`));
7087
7428
  console.log(GRAY5(" Current project will be backed up locally first."));
7088
7429
  } else {
7089
- console.log(AMBER6(` \u26A0\uFE0F This will restore ${isGlobal ? "~/.bob/" : `~/.bob/projects/${projectName}/`} from ${label}.`));
7430
+ console.log(AMBER7(` \u26A0\uFE0F This will restore ${isGlobal ? "~/.bob/" : `~/.bob/projects/${projectName}/`} from ${label}.`));
7090
7431
  console.log(GRAY5(" Your current data will be backed up locally first."));
7091
7432
  }
7092
7433
  console.log("");
7093
7434
  const { confirmed } = await inquirer.prompt([{
7094
7435
  type: "confirm",
7095
7436
  name: "confirmed",
7096
- message: AMBER6(" Continue with restore?"),
7437
+ message: AMBER7(" Continue with restore?"),
7097
7438
  default: false
7098
7439
  }]);
7099
7440
  if (!confirmed) {
@@ -7492,7 +7833,7 @@ ${userMessage}`,
7492
7833
  // src/ui/agent-renderer.ts
7493
7834
  import chalk25 from "chalk";
7494
7835
  var PURPLE = chalk25.hex("#AB47BC");
7495
- var AMBER7 = chalk25.hex("#FFAB00");
7836
+ var AMBER8 = chalk25.hex("#FFAB00");
7496
7837
  var GREEN6 = chalk25.hex("#66BB6A");
7497
7838
  var RED6 = chalk25.hex("#EF5350");
7498
7839
  var CYAN6 = chalk25.cyan;
@@ -7690,7 +8031,7 @@ function renderUnifiedMessages(messages, allAgentNames, options = {}) {
7690
8031
  console.log("");
7691
8032
  console.log(BORDER11(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
7692
8033
  console.log(
7693
- BORDER11(" \u2551") + AMBER7(" \u{1F4CB} Messages") + GRAY6(
8034
+ BORDER11(" \u2551") + AMBER8(" \u{1F4CB} Messages") + GRAY6(
7694
8035
  ` ${totalMessages} total` + (options.filterAgent ? ` filter: @${options.filterAgent}` : "") + (options.search ? ` search: "${options.search}"` : "")
7695
8036
  )
7696
8037
  );
@@ -7790,7 +8131,7 @@ async function runMessagesView(agentNames, cwd, rl, initialFilter, initialSearch
7790
8131
  render();
7791
8132
  return new Promise((resolve4) => {
7792
8133
  const messagesPrompt = () => {
7793
- rl.question(AMBER7(" Messages > "), async (input) => {
8134
+ rl.question(AMBER8(" Messages > "), async (input) => {
7794
8135
  const trimmed = input.trim();
7795
8136
  if (!trimmed) {
7796
8137
  messagesPrompt();
@@ -7871,7 +8212,7 @@ async function runAgentHub(cwd) {
7871
8212
  const registry = loadRegistry(cwd);
7872
8213
  if (registry.agents.length === 0) {
7873
8214
  console.log("");
7874
- console.log(AMBER7(" \u26A0\uFE0F No agents found."));
8215
+ console.log(AMBER8(" \u26A0\uFE0F No agents found."));
7875
8216
  console.log(GRAY6(' Spawn one first: bob agent spawn <name> "<task>"'));
7876
8217
  console.log("");
7877
8218
  return;
@@ -7928,7 +8269,7 @@ async function runAgentHub(cwd) {
7928
8269
  }
7929
8270
  if (parsed.type === "unknown") {
7930
8271
  console.log("");
7931
- console.log(AMBER7(" \u26A0\uFE0F Use @name to talk to an agent."));
8272
+ console.log(AMBER8(" \u26A0\uFE0F Use @name to talk to an agent."));
7932
8273
  console.log(GRAY6(` Available: ${agentNames.map((n) => `@${n}`).join(", ")}`));
7933
8274
  console.log(GRAY6(" Or use @all to broadcast to everyone."));
7934
8275
  console.log("");
@@ -7936,7 +8277,7 @@ async function runAgentHub(cwd) {
7936
8277
  return;
7937
8278
  }
7938
8279
  if (!parsed.message) {
7939
- console.log(AMBER7(" \u26A0\uFE0F Message cannot be empty."));
8280
+ console.log(AMBER8(" \u26A0\uFE0F Message cannot be empty."));
7940
8281
  prompt();
7941
8282
  return;
7942
8283
  }
@@ -7959,7 +8300,7 @@ async function runAgentHub(cwd) {
7959
8300
  renderAgentResponse(targetName, result.response, agentColor);
7960
8301
  if (result.summaryGenerated && result.summary) {
7961
8302
  console.log("");
7962
- console.log(AMBER7(` \u{1F9EC} @${targetName} session summarized (${result.messageCount} messages)`));
8303
+ console.log(AMBER8(` \u{1F9EC} @${targetName} session summarized (${result.messageCount} messages)`));
7963
8304
  console.log(GRAY6(" Summary saved. Other agents will see this context."));
7964
8305
  console.log(GRAY6(" View with: /summary"));
7965
8306
  }
@@ -8149,7 +8490,7 @@ async function runAgentChat(agentName, cwd, initialSearch) {
8149
8490
  const summary = loadAgentSummary2(agentName, cwd);
8150
8491
  console.log("");
8151
8492
  if (summary) {
8152
- console.log(AMBER7(` \u{1F9EC} @${agentName} Summary`));
8493
+ console.log(AMBER8(` \u{1F9EC} @${agentName} Summary`));
8153
8494
  console.log(GRAY6(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
8154
8495
  const lines = summary.split("\n").filter((l) => l.trim());
8155
8496
  for (const line of lines) {
@@ -8217,7 +8558,7 @@ async function runAgentChat(agentName, cwd, initialSearch) {
8217
8558
  renderAgentResponse(agentName, result.response, agentColor);
8218
8559
  if (result.summaryGenerated && result.summary) {
8219
8560
  console.log("");
8220
- console.log(AMBER7(` \u{1F9EC} Session summarized (${result.messageCount} messages)`));
8561
+ console.log(AMBER8(` \u{1F9EC} Session summarized (${result.messageCount} messages)`));
8221
8562
  const lines = result.summary.split("\n").filter((l) => l.trim()).slice(0, 5);
8222
8563
  for (const line of lines) {
8223
8564
  console.log(GRAY6(` ${line.slice(0, 62)}`));
@@ -8240,7 +8581,7 @@ async function runAgentChat(agentName, cwd, initialSearch) {
8240
8581
 
8241
8582
  // src/commands/agent.ts
8242
8583
  var PURPLE3 = chalk28.hex("#AB47BC");
8243
- var AMBER8 = chalk28.hex("#FFAB00");
8584
+ var AMBER9 = chalk28.hex("#FFAB00");
8244
8585
  var GREEN8 = chalk28.hex("#66BB6A");
8245
8586
  var RED7 = chalk28.hex("#EF5350");
8246
8587
  var CYAN8 = chalk28.cyan;
@@ -8272,7 +8613,7 @@ function statusIcon(status) {
8272
8613
  case "active":
8273
8614
  return GREEN8("\u25CF");
8274
8615
  case "idle":
8275
- return AMBER8("\u25CF");
8616
+ return AMBER9("\u25CF");
8276
8617
  case "stopped":
8277
8618
  return GRAY7("\u25CB");
8278
8619
  default:
@@ -8284,7 +8625,7 @@ function statusLabel(status) {
8284
8625
  case "active":
8285
8626
  return GREEN8("ACTIVE");
8286
8627
  case "idle":
8287
- return AMBER8("IDLE");
8628
+ return AMBER9("IDLE");
8288
8629
  case "stopped":
8289
8630
  return GRAY7("STOPPED");
8290
8631
  default:
@@ -8480,7 +8821,7 @@ function registerAgentCommand(program2) {
8480
8821
  }
8481
8822
  if (summary) {
8482
8823
  console.log(BORDER12(" \u2502"));
8483
- console.log(BORDER12(" \u2502") + AMBER8(" Last Summary:"));
8824
+ console.log(BORDER12(" \u2502") + AMBER9(" Last Summary:"));
8484
8825
  const summaryLines = summary.split("\n").filter((l) => l.trim()).slice(0, 4);
8485
8826
  for (const line of summaryLines) {
8486
8827
  console.log(
@@ -8517,7 +8858,7 @@ function registerAgentCommand(program2) {
8517
8858
  const session = loadSession(name, cwd);
8518
8859
  console.log("");
8519
8860
  console.log(BORDER12(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
8520
- console.log(BORDER12(" \u2502") + AMBER8(` \u26A0\uFE0F WARNING: Reset @${name}`));
8861
+ console.log(BORDER12(" \u2502") + AMBER9(` \u26A0\uFE0F WARNING: Reset @${name}`));
8521
8862
  console.log(BORDER12(" \u2502"));
8522
8863
  console.log(BORDER12(" \u2502") + RED7(" This will permanently delete:"));
8523
8864
  console.log(BORDER12(" \u2502") + GRAY7(` \u2022 ${session?.messageCount || 0} messages of conversation history`));
@@ -8532,7 +8873,7 @@ function registerAgentCommand(program2) {
8532
8873
  const { confirmed } = await inquirer2.prompt([{
8533
8874
  type: "input",
8534
8875
  name: "confirmed",
8535
- message: AMBER8(` Type "@${name}" to confirm reset:`),
8876
+ message: AMBER9(` Type "@${name}" to confirm reset:`),
8536
8877
  validate: (v) => v.trim() === `@${name}` || v.trim() === name ? true : `Type @${name} to confirm.`
8537
8878
  }]);
8538
8879
  if (confirmed.trim() !== `@${name}` && confirmed.trim() !== name) {
@@ -8560,7 +8901,7 @@ function registerAgentCommand(program2) {
8560
8901
  }, 0);
8561
8902
  console.log("");
8562
8903
  console.log(BORDER12(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
8563
- console.log(BORDER12(" \u2502") + AMBER8(" \u26A0\uFE0F WARNING: Reset ALL Agents"));
8904
+ console.log(BORDER12(" \u2502") + AMBER9(" \u26A0\uFE0F WARNING: Reset ALL Agents"));
8564
8905
  console.log(BORDER12(" \u2502"));
8565
8906
  console.log(BORDER12(" \u2502") + RED7(" This will permanently delete:"));
8566
8907
  console.log(BORDER12(" \u2502") + GRAY7(` \u2022 ${registry.agents.length} agents`));
@@ -8574,7 +8915,7 @@ function registerAgentCommand(program2) {
8574
8915
  const { confirmed } = await inquirer2.prompt([{
8575
8916
  type: "confirm",
8576
8917
  name: "confirmed",
8577
- message: AMBER8(" Reset ALL agents?"),
8918
+ message: AMBER9(" Reset ALL agents?"),
8578
8919
  default: false
8579
8920
  }]);
8580
8921
  if (!confirmed) {
@@ -8617,7 +8958,7 @@ function registerAgentCommand(program2) {
8617
8958
  }
8618
8959
  console.log("");
8619
8960
  console.log(BORDER12(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
8620
- console.log(BORDER12(" \u2551") + AMBER8(" \u{1F4CB} Agent Summary"));
8961
+ console.log(BORDER12(" \u2551") + AMBER9(" \u{1F4CB} Agent Summary"));
8621
8962
  console.log(BORDER12(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
8622
8963
  for (const agent of registry.agents) {
8623
8964
  const summary = loadAgentSummary(agent.name, cwd);
@@ -10502,7 +10843,7 @@ import * as fs17 from "fs";
10502
10843
  import * as path21 from "path";
10503
10844
  import { diffLines as diffLines2 } from "diff";
10504
10845
  var PURPLE4 = chalk29.hex("#AB47BC");
10505
- var AMBER9 = chalk29.hex("#FFAB00");
10846
+ var AMBER10 = chalk29.hex("#FFAB00");
10506
10847
  var GREEN9 = chalk29.hex("#66BB6A");
10507
10848
  var RED8 = chalk29.hex("#EF5350");
10508
10849
  var CYAN9 = chalk29.cyan;
@@ -10545,7 +10886,7 @@ function renderMissionHeader(mission, agentNames) {
10545
10886
  console.log(BORDER13(" \u2551"));
10546
10887
  console.log(BORDER13(" \u2551") + ` ${chips}`);
10547
10888
  console.log(BORDER13(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
10548
- console.log(BORDER13(" \u2551") + AMBER9(" Live Commands:"));
10889
+ console.log(BORDER13(" \u2551") + AMBER10(" Live Commands:"));
10549
10890
  console.log(BORDER13(" \u2551") + CYAN9(" /pause") + GRAY8(" \u2014 pause after active tasks"));
10550
10891
  console.log(BORDER13(" \u2551") + CYAN9(" /resume") + GRAY8(" \u2014 resume from pause"));
10551
10892
  console.log(BORDER13(" \u2551") + CYAN9(" /status") + GRAY8(" \u2014 full task map"));
@@ -10563,7 +10904,7 @@ function renderTaskMap(mission, agentNames) {
10563
10904
  const summary = getMissionSummary(mission);
10564
10905
  console.log("");
10565
10906
  console.log(DIRECTOR_COLOR(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
10566
- console.log(DIRECTOR_COLOR(" \u2551") + AMBER9(" \u{1F4CB} Task Map") + GRAY8(` \u2014 ${summary.total} tasks`));
10907
+ console.log(DIRECTOR_COLOR(" \u2551") + AMBER10(" \u{1F4CB} Task Map") + GRAY8(` \u2014 ${summary.total} tasks`));
10567
10908
  console.log(DIRECTOR_COLOR(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
10568
10909
  const running = mission.tasks.filter((t) => t.status === "running");
10569
10910
  const pending = mission.tasks.filter((t) => t.status === "pending");
@@ -10679,7 +11020,7 @@ function renderExecutionEvent(event, agentNames) {
10679
11020
  const toolName = event.data?.tool || "unknown";
10680
11021
  const toolColors = {
10681
11022
  createFile: GREEN9,
10682
- modifyFile: AMBER9,
11023
+ modifyFile: AMBER10,
10683
11024
  readFile: CYAN9,
10684
11025
  writeOutput: BLUE4,
10685
11026
  readAgentOutput: BLUE4,
@@ -10728,13 +11069,13 @@ function renderExecutionEvent(event, agentNames) {
10728
11069
  }
10729
11070
  }
10730
11071
  async function renderPostMissionFeedback(mission, cwd) {
10731
- const readline11 = await import("readline");
10732
- const path23 = await import("path");
10733
- const fs18 = await import("fs");
10734
- const os8 = await import("os");
11072
+ const readline12 = await import("readline");
11073
+ const path24 = await import("path");
11074
+ const fs19 = await import("fs");
11075
+ const os9 = await import("os");
10735
11076
  console.log("");
10736
11077
  console.log(DIRECTOR_COLOR(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
10737
- console.log(DIRECTOR_COLOR(" \u2551") + AMBER9(" \u{1F4DD} Mission Feedback \u2014 Help train the agents"));
11078
+ console.log(DIRECTOR_COLOR(" \u2551") + AMBER10(" \u{1F4DD} Mission Feedback \u2014 Help train the agents"));
10738
11079
  console.log(DIRECTOR_COLOR(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
10739
11080
  console.log(DIRECTOR_COLOR(" \u2551") + GRAY8(" Your feedback improves future missions."));
10740
11081
  console.log(DIRECTOR_COLOR(" \u2551") + GRAY8(" Press Enter to skip any task."));
@@ -10742,12 +11083,12 @@ async function renderPostMissionFeedback(mission, cwd) {
10742
11083
  console.log("");
10743
11084
  const completedTasks = mission.tasks.filter((t) => t.status === "completed");
10744
11085
  const feedback = [];
10745
- const rl = readline11.createInterface({ input: process.stdin, output: process.stdout });
11086
+ const rl = readline12.createInterface({ input: process.stdin, output: process.stdout });
10746
11087
  for (const task of completedTasks) {
10747
11088
  const chip = renderAgentChip(task.assignedTo, mission.tasks.map((t) => t.assignedTo), true);
10748
11089
  console.log(` ${chip} ${GRAY8(task.instruction.slice(0, 60))}`);
10749
11090
  const rating = await new Promise((resolve4) => {
10750
- rl.question(AMBER9(" Rate (\u{1F44D} good / \u{1F44E} bad / skip): "), resolve4);
11091
+ rl.question(AMBER10(" Rate (\u{1F44D} good / \u{1F44E} bad / skip): "), resolve4);
10751
11092
  });
10752
11093
  const trimmed = rating.trim().toLowerCase();
10753
11094
  if (trimmed === "" || trimmed === "skip") {
@@ -10774,21 +11115,21 @@ async function renderPostMissionFeedback(mission, cwd) {
10774
11115
  }
10775
11116
  rl.close();
10776
11117
  if (feedback.length === 0) return;
10777
- const projectName = path23.basename(cwd);
10778
- const feedbackDir = path23.join(os8.homedir(), ".bob", "projects", projectName, "agents", "feedback");
10779
- if (!fs18.existsSync(feedbackDir)) fs18.mkdirSync(feedbackDir, { recursive: true });
11118
+ const projectName = path24.basename(cwd);
11119
+ const feedbackDir = path24.join(os9.homedir(), ".bob", "projects", projectName, "agents", "feedback");
11120
+ if (!fs19.existsSync(feedbackDir)) fs19.mkdirSync(feedbackDir, { recursive: true });
10780
11121
  const sessionFeedback = {
10781
11122
  missionId: mission.id,
10782
11123
  missionDescription: mission.description,
10783
11124
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10784
11125
  tasks: feedback
10785
11126
  };
10786
- const feedbackFile = path23.join(feedbackDir, `${mission.id}.json`);
10787
- fs18.writeFileSync(feedbackFile, JSON.stringify(sessionFeedback, null, 2));
10788
- const globalDir = path23.join(os8.homedir(), ".bob", "global", "agent-training");
10789
- if (!fs18.existsSync(globalDir)) fs18.mkdirSync(globalDir, { recursive: true });
10790
- const globalFile = path23.join(globalDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}_${mission.id}.json`);
10791
- fs18.writeFileSync(globalFile, JSON.stringify(sessionFeedback, null, 2));
11127
+ const feedbackFile = path24.join(feedbackDir, `${mission.id}.json`);
11128
+ fs19.writeFileSync(feedbackFile, JSON.stringify(sessionFeedback, null, 2));
11129
+ const globalDir = path24.join(os9.homedir(), ".bob", "global", "agent-training");
11130
+ if (!fs19.existsSync(globalDir)) fs19.mkdirSync(globalDir, { recursive: true });
11131
+ const globalFile = path24.join(globalDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}_${mission.id}.json`);
11132
+ fs19.writeFileSync(globalFile, JSON.stringify(sessionFeedback, null, 2));
10792
11133
  console.log(GREEN9(` \u2705 Feedback saved. Thank you for helping train the agents.`));
10793
11134
  console.log(GRAY8(` Saved to: ~/.bob/projects/${projectName}/agents/feedback/`));
10794
11135
  console.log(GRAY8(` Global: ~/.bob/global/agent-training/`));
@@ -10823,7 +11164,7 @@ function renderMissionComplete(mission) {
10823
11164
  console.log("");
10824
11165
  }
10825
11166
  async function renderPostMissionCommitPrompt(mission, cwd) {
10826
- const readline11 = await import("readline");
11167
+ const readline12 = await import("readline");
10827
11168
  const allCreated = [];
10828
11169
  const allModified = [];
10829
11170
  for (const task of mission.tasks) {
@@ -10839,7 +11180,7 @@ async function renderPostMissionCommitPrompt(mission, cwd) {
10839
11180
  if (totalFiles === 0) return;
10840
11181
  console.log("");
10841
11182
  console.log(BORDER13(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
10842
- console.log(BORDER13(" \u2551") + AMBER9(" \u{1F4E6} Mission Changes \u2014 Ready to Commit"));
11183
+ console.log(BORDER13(" \u2551") + AMBER10(" \u{1F4E6} Mission Changes \u2014 Ready to Commit"));
10843
11184
  console.log(BORDER13(" \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
10844
11185
  console.log("");
10845
11186
  for (const filePath of allCreated) {
@@ -10899,12 +11240,12 @@ async function renderPostMissionCommitPrompt(mission, cwd) {
10899
11240
  console.log(BORDER13(" \u2551") + GRAY8(` ${allCreated.length} created \u2502 ${allModified.length} modified \u2502 ${totalFiles} total`));
10900
11241
  console.log(BORDER13(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
10901
11242
  console.log("");
10902
- const rl = readline11.createInterface({
11243
+ const rl = readline12.createInterface({
10903
11244
  input: process.stdin,
10904
11245
  output: process.stdout
10905
11246
  });
10906
11247
  const answer = await new Promise((resolve4) => {
10907
- rl.question(AMBER9(" Commit these changes? (y/n): "), resolve4);
11248
+ rl.question(AMBER10(" Commit these changes? (y/n): "), resolve4);
10908
11249
  });
10909
11250
  if (answer.trim().toLowerCase() !== "y" && answer.trim().toLowerCase() !== "yes") {
10910
11251
  rl.close();
@@ -10914,7 +11255,7 @@ async function renderPostMissionCommitPrompt(mission, cwd) {
10914
11255
  }
10915
11256
  const defaultMessage = `feat(agents): ${mission.description.slice(0, 60)}`;
10916
11257
  const messageAnswer = await new Promise((resolve4) => {
10917
- rl.question(AMBER9(` Commit message (Enter for default: "${defaultMessage.slice(0, 40)}..."): `), resolve4);
11258
+ rl.question(AMBER10(` Commit message (Enter for default: "${defaultMessage.slice(0, 40)}..."): `), resolve4);
10918
11259
  });
10919
11260
  rl.close();
10920
11261
  const commitMessage = messageAnswer.trim() || defaultMessage;
@@ -10942,7 +11283,7 @@ function handleRunCommand(input, state, mission, cwd) {
10942
11283
  const trimmed = input.trim();
10943
11284
  if (trimmed === "/pause") {
10944
11285
  state.paused = true;
10945
- return { handled: true, message: AMBER9(" \u23F8\uFE0F Pausing after active tasks complete...") };
11286
+ return { handled: true, message: AMBER10(" \u23F8\uFE0F Pausing after active tasks complete...") };
10946
11287
  }
10947
11288
  if (trimmed === "/resume") {
10948
11289
  state.paused = false;
@@ -10966,7 +11307,7 @@ function handleRunCommand(input, state, mission, cwd) {
10966
11307
  }
10967
11308
  if (trimmed === "/view-targets") {
10968
11309
  const lines = [""];
10969
- lines.push(AMBER9(" Satisfaction Targets:"));
11310
+ lines.push(AMBER10(" Satisfaction Targets:"));
10970
11311
  lines.push(GRAY8(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
10971
11312
  for (const task of mission.tasks) {
10972
11313
  const statusIcon2 = getTaskStatusIcon(task.status);
@@ -11023,7 +11364,7 @@ function getTaskStatusIcon(status) {
11023
11364
 
11024
11365
  // src/commands/agent-run.ts
11025
11366
  init_agent_tools();
11026
- var AMBER10 = chalk30.hex("#FFAB00");
11367
+ var AMBER11 = chalk30.hex("#FFAB00");
11027
11368
  var GREEN10 = chalk30.hex("#66BB6A");
11028
11369
  var RED9 = chalk30.hex("#EF5350");
11029
11370
  var CYAN10 = chalk30.cyan;
@@ -11042,7 +11383,7 @@ function registerAgentRunCommand(program2) {
11042
11383
  const registry = loadRegistry(cwd);
11043
11384
  if (registry.agents.length === 0) {
11044
11385
  console.log("");
11045
- console.log(AMBER10(" \u26A0\uFE0F No agents found."));
11386
+ console.log(AMBER11(" \u26A0\uFE0F No agents found."));
11046
11387
  console.log(GRAY9(' Spawn agents first: bob agent spawn <name> "<task>"'));
11047
11388
  console.log("");
11048
11389
  return;
@@ -11052,7 +11393,7 @@ function registerAgentRunCommand(program2) {
11052
11393
  );
11053
11394
  if (agents.length === 0) {
11054
11395
  console.log("");
11055
- console.log(AMBER10(" \u26A0\uFE0F No active agents found."));
11396
+ console.log(AMBER11(" \u26A0\uFE0F No active agents found."));
11056
11397
  console.log("");
11057
11398
  return;
11058
11399
  }
@@ -11060,7 +11401,7 @@ function registerAgentRunCommand(program2) {
11060
11401
  const activeMissionId = getActiveMissionId(cwd);
11061
11402
  if (!activeMissionId) {
11062
11403
  console.log("");
11063
- console.log(AMBER10(" \u26A0\uFE0F No active mission to resume."));
11404
+ console.log(AMBER11(" \u26A0\uFE0F No active mission to resume."));
11064
11405
  console.log("");
11065
11406
  return;
11066
11407
  }
@@ -11072,7 +11413,7 @@ function registerAgentRunCommand(program2) {
11072
11413
  return;
11073
11414
  }
11074
11415
  console.log("");
11075
- console.log(AMBER10(` \u{1F504} Resuming mission: ${existingMission.description.slice(0, 50)}...`));
11416
+ console.log(AMBER11(` \u{1F504} Resuming mission: ${existingMission.description.slice(0, 50)}...`));
11076
11417
  await executeMission(existingMission, agents, cwd, config.localEndpoint, options);
11077
11418
  return;
11078
11419
  }
@@ -11083,7 +11424,7 @@ function registerAgentRunCommand(program2) {
11083
11424
  output: process.stdout
11084
11425
  });
11085
11426
  missionDescription = await new Promise((resolve4) => {
11086
- rl.question(AMBER10(" \u{1F3AC} What is the mission? > "), resolve4);
11427
+ rl.question(AMBER11(" \u{1F3AC} What is the mission? > "), resolve4);
11087
11428
  });
11088
11429
  rl.close();
11089
11430
  if (!missionDescription.trim()) {
@@ -11095,7 +11436,7 @@ function registerAgentRunCommand(program2) {
11095
11436
  clearAllPendingCommits(cwd);
11096
11437
  console.log("");
11097
11438
  const planSpinner = ora13({
11098
- text: AMBER10(" \u{1F3AC} DirectorBob is analyzing your team and building the task map..."),
11439
+ text: AMBER11(" \u{1F3AC} DirectorBob is analyzing your team and building the task map..."),
11099
11440
  spinner: "dots"
11100
11441
  }).start();
11101
11442
  let taskDefs;
@@ -11152,7 +11493,7 @@ function registerAgentRunCommand(program2) {
11152
11493
  console.log("");
11153
11494
  return;
11154
11495
  }
11155
- console.log(AMBER10(" Starting in 3 seconds... (Ctrl+C to abort)"));
11496
+ console.log(AMBER11(" Starting in 3 seconds... (Ctrl+C to abort)"));
11156
11497
  await new Promise((r) => setTimeout(r, 3e3));
11157
11498
  await executeMission(mission, agents, cwd, config.localEndpoint, options);
11158
11499
  });
@@ -11231,7 +11572,7 @@ async function executeMission(mission, agents, cwd, localEndpoint, options) {
11231
11572
  console.log("");
11232
11573
  } else if (result.surfacedToUser) {
11233
11574
  console.log("");
11234
- console.log(AMBER10(" \u26A0\uFE0F Mission needs your attention."));
11575
+ console.log(AMBER11(" \u26A0\uFE0F Mission needs your attention."));
11235
11576
  console.log(RED9(` Reason: ${result.surfaceReason}`));
11236
11577
  console.log("");
11237
11578
  console.log(GRAY9(" Options:"));
@@ -11248,26 +11589,574 @@ async function executeMission(mission, agents, cwd, localEndpoint, options) {
11248
11589
  }
11249
11590
  }
11250
11591
 
11592
+ // src/commands/userbob.ts
11593
+ import chalk31 from "chalk";
11594
+ import * as readline11 from "readline";
11595
+ import * as fs18 from "fs";
11596
+ import * as path22 from "path";
11597
+ import * as os8 from "os";
11598
+ var PURPLE5 = chalk31.hex("#AB47BC");
11599
+ var AMBER12 = chalk31.hex("#FFAB00");
11600
+ var GREEN11 = chalk31.hex("#66BB6A");
11601
+ var CYAN11 = chalk31.hex("#26C6DA");
11602
+ var RED10 = chalk31.hex("#EF5350");
11603
+ var GRAY10 = chalk31.gray;
11604
+ var BLUE5 = chalk31.hex("#42A5F5");
11605
+ var BOB_COLOR = chalk31.hex("#E66F24");
11606
+ var BORDER14 = chalk31.hex("#455A64");
11607
+ var WHITE7 = chalk31.white;
11608
+ var BOB_DIR8 = path22.join(os8.homedir(), ".bob");
11609
+ function getSessionFilePath() {
11610
+ const projectName = path22.basename(process.cwd());
11611
+ return path22.join(BOB_DIR8, "projects", projectName, "userbob-session.json");
11612
+ }
11613
+ function writeSessionFile(data) {
11614
+ const filePath = getSessionFilePath();
11615
+ const dir = path22.dirname(filePath);
11616
+ if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
11617
+ fs18.writeFileSync(filePath, JSON.stringify(data, null, 2));
11618
+ }
11619
+ function readSessionFile() {
11620
+ const filePath = getSessionFilePath();
11621
+ if (!fs18.existsSync(filePath)) return null;
11622
+ try {
11623
+ return JSON.parse(fs18.readFileSync(filePath, "utf-8"));
11624
+ } catch {
11625
+ return null;
11626
+ }
11627
+ }
11628
+ function clearSessionFile() {
11629
+ const filePath = getSessionFilePath();
11630
+ if (fs18.existsSync(filePath)) fs18.unlinkSync(filePath);
11631
+ }
11632
+ function renderHUD(sat, target, stag, stagTarget, div, divTarget, grading) {
11633
+ const satBar = sat >= target ? GREEN11(`${sat}%`) : sat >= target * 0.7 ? AMBER12(`${sat}%`) : RED10(`${sat}%`);
11634
+ console.log("");
11635
+ console.log(BORDER14(" \u2500\u2500\u2500 MISSION CONTROL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11636
+ console.log(
11637
+ ` SAT: ${satBar} \u2192 ${target}% \u2502 STAG: ${stag}/${stagTarget > 0 ? stagTarget : "\u221E"} \u2502 DIV: ${div}/${divTarget > 0 ? divTarget : "\u221E"} \u2502 GRADE: ${grading}`
11638
+ );
11639
+ console.log(BORDER14(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11640
+ console.log("");
11641
+ }
11642
+ function stripMarkdown2(text) {
11643
+ return text.replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/^#{1,6}\s+/gm, "").replace(/^---+$/gm, "").replace(/^>\s?/gm, "").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*+]\s+/gm, " \u2022 ").replace(/^\s*\d+\.\s+/gm, " ").replace(/\n{3,}/g, "\n\n").trim();
11644
+ }
11645
+ function renderMessage(sender, message, audit) {
11646
+ const cleanMsg = stripMarkdown2(message);
11647
+ const maxWidth = 70;
11648
+ const lines = wrapText3(cleanMsg, maxWidth - 4);
11649
+ if (sender === "userBob") {
11650
+ const topBar = PURPLE5(` \u250C\u2500 UserBob ${"\u2500".repeat(maxWidth - 13)}\u2510`);
11651
+ const bottomBar = PURPLE5(` \u2514${"\u2500".repeat(maxWidth - 2)}\u2518`);
11652
+ console.log("");
11653
+ console.log(topBar);
11654
+ for (const line of lines) {
11655
+ const padded = line.padEnd(maxWidth - 4);
11656
+ console.log(PURPLE5(" \u2502") + ` ${padded}` + PURPLE5(" \u2502"));
11657
+ }
11658
+ console.log(bottomBar);
11659
+ if (audit) {
11660
+ const chips = [];
11661
+ if (audit.satisfactionScore !== void 0) chips.push(CYAN11(`[SAT: ${audit.satisfactionScore}%]`));
11662
+ if (audit.resemblanceScore !== void 0) chips.push(BLUE5(`[RES: ${audit.resemblanceScore}%]`));
11663
+ if (audit.reasoning) chips.push(GRAY10(`[${String(audit.reasoning).slice(0, 50)}...]`));
11664
+ if (chips.length > 0) console.log(" " + chips.join(" "));
11665
+ }
11666
+ } else if (sender === "bob") {
11667
+ const indent = " ";
11668
+ const topBar = BOB_COLOR(`${indent}\u250C${"\u2500".repeat(maxWidth - 12)}\u2500 Bob \u2500\u2510`);
11669
+ const bottomBar = BOB_COLOR(`${indent}\u2514${"\u2500".repeat(maxWidth - 2)}\u2518`);
11670
+ console.log("");
11671
+ console.log(topBar);
11672
+ for (const line of lines) {
11673
+ const padded = line.padEnd(maxWidth - 4);
11674
+ console.log(BOB_COLOR(`${indent}\u2502`) + ` ${padded}` + BOB_COLOR(" \u2502"));
11675
+ }
11676
+ console.log(bottomBar);
11677
+ } else if (sender === "system") {
11678
+ console.log("");
11679
+ console.log(CYAN11(" \u2500\u2500 SYSTEM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11680
+ console.log(GRAY10(` ${cleanMsg}`));
11681
+ console.log(CYAN11(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11682
+ } else {
11683
+ console.log("");
11684
+ console.log(GRAY10(` [${sender.toUpperCase()}] ${cleanMsg}`));
11685
+ }
11686
+ }
11687
+ function wrapText3(text, maxWidth) {
11688
+ const lines = [];
11689
+ const paragraphs = text.split("\n");
11690
+ for (const paragraph of paragraphs) {
11691
+ if (paragraph.trim() === "") {
11692
+ lines.push("");
11693
+ continue;
11694
+ }
11695
+ const words = paragraph.split(" ");
11696
+ let currentLine = "";
11697
+ for (const word of words) {
11698
+ if ((currentLine + " " + word).trim().length > maxWidth) {
11699
+ if (currentLine) lines.push(currentLine.trim());
11700
+ currentLine = word;
11701
+ } else {
11702
+ currentLine = currentLine ? currentLine + " " + word : word;
11703
+ }
11704
+ }
11705
+ if (currentLine.trim()) lines.push(currentLine.trim());
11706
+ }
11707
+ return lines;
11708
+ }
11709
+ async function handleSlashCommand(input, config, conversationId) {
11710
+ const trimmed = input.trim();
11711
+ if (trimmed === "/status") {
11712
+ try {
11713
+ const response = await callCloudFunction("getCLIConversationMessages", { conversationId, since: null });
11714
+ const state = response?.state || {};
11715
+ console.log("");
11716
+ console.log(AMBER12(" \u2500\u2500\u2500 Current Parameters \u2500\u2500\u2500"));
11717
+ console.log(GRAY10(` Target Satisfaction : ${state.targetSatisfaction ?? "N/A"}`));
11718
+ console.log(GRAY10(` Grading Standard : ${state.gradingStandard ?? "N/A"}`));
11719
+ console.log(GRAY10(` Current Satisfaction: ${state.currentSatisfaction ?? "N/A"}`));
11720
+ console.log(GRAY10(` Stalemate : ${state.stalemateState?.current ?? 0}/${state.stalemateState?.target ?? "\u221E"}`));
11721
+ console.log(GRAY10(` Divergence : ${state.divergenceState?.current ?? 0}/${state.divergenceState?.target ?? "\u221E"}`));
11722
+ console.log(GRAY10(` Status : ${state.simulationStatus ?? "UNKNOWN"}`));
11723
+ console.log(GRAY10(` Active : ${state.userBobActive ?? "UNKNOWN"}`));
11724
+ console.log("");
11725
+ } catch {
11726
+ console.log(RED10(" \u274C Could not fetch conversation state."));
11727
+ }
11728
+ return;
11729
+ }
11730
+ const setMatch = trimmed.match(/^\/set\s+(grading|target|stag|div)\s+(\d+)$/i);
11731
+ if (setMatch) {
11732
+ const param = setMatch[1].toLowerCase();
11733
+ const value = parseInt(setMatch[2], 10);
11734
+ const paramMap = {
11735
+ grading: "gradingStandard",
11736
+ target: "targetSatisfaction",
11737
+ stag: "stalemateZone",
11738
+ div: "divergenceThreshold"
11739
+ };
11740
+ try {
11741
+ await callHTTPFunction("userSimManagerService", {
11742
+ action: "updateParameters",
11743
+ conversationId,
11744
+ uid: config.uid,
11745
+ email: config.email,
11746
+ params: { [paramMap[param]]: value }
11747
+ });
11748
+ console.log(GREEN11(` \u2705 ${param} updated to ${value}`));
11749
+ } catch (e) {
11750
+ console.log(RED10(` \u274C Failed to update ${param}: ${e.message}`));
11751
+ }
11752
+ return;
11753
+ }
11754
+ const injectMatch = trimmed.match(/^\/inject\s+"(.+)"$/);
11755
+ if (injectMatch) {
11756
+ const note = injectMatch[1];
11757
+ try {
11758
+ await callHTTPFunction("userSimManagerService", {
11759
+ action: "injectNote",
11760
+ conversationId,
11761
+ uid: config.uid,
11762
+ email: config.email,
11763
+ note
11764
+ });
11765
+ console.log(GREEN11(` \u2705 Director's note injected.`));
11766
+ } catch (e) {
11767
+ console.log(RED10(` \u274C Failed to inject note: ${e.message}`));
11768
+ }
11769
+ return;
11770
+ }
11771
+ console.log(GRAY10(' Commands: /set grading|target|stag|div <n> /inject "note" /status /abort'));
11772
+ }
11773
+ async function runPlatformSimulation(config, conversationId, mission, params) {
11774
+ await callHTTPFunction("userSimManagerService", {
11775
+ action: "updateParameters",
11776
+ conversationId,
11777
+ uid: config.uid,
11778
+ email: config.email,
11779
+ params: {
11780
+ targetSatisfaction: params.target,
11781
+ gradingStandard: params.grading,
11782
+ stalemateZone: params.stag,
11783
+ divergenceThreshold: params.div
11784
+ }
11785
+ });
11786
+ await callHTTPFunction("userSimManagerService", {
11787
+ action: "injectNote",
11788
+ conversationId,
11789
+ uid: config.uid,
11790
+ email: config.email,
11791
+ note: mission
11792
+ });
11793
+ console.log(GREEN11(" \u2705 Mission injected. Simulation is running."));
11794
+ console.log("");
11795
+ console.log(BORDER14(" \u2500\u2500\u2500 LIVE SIMULATION \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11796
+ console.log(GRAY10(" Messages will stream below as Bob and UserBob interact."));
11797
+ console.log(GRAY10(" You can type commands at any time:"));
11798
+ console.log("");
11799
+ console.log(AMBER12(" /abort") + GRAY10(" \u2014 Stop the simulation immediately"));
11800
+ console.log(AMBER12(" /set target 90") + GRAY10(" \u2014 Update satisfaction target"));
11801
+ console.log(AMBER12(" /set grading 70") + GRAY10(" \u2014 Update Teacher's Curve"));
11802
+ console.log(AMBER12(" /set stag 5") + GRAY10(" \u2014 Update stalemate threshold"));
11803
+ console.log(AMBER12(" /set div 3") + GRAY10(" \u2014 Update divergence threshold"));
11804
+ console.log(AMBER12(' /inject "note"') + GRAY10(" \u2014 Inject a director's note mid-session"));
11805
+ console.log(AMBER12(" /status") + GRAY10(" \u2014 Show current simulation parameters"));
11806
+ console.log("");
11807
+ console.log(BORDER14(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11808
+ console.log("");
11809
+ let running = true;
11810
+ let lastMessageTimestamp = 0;
11811
+ let hudState = { sat: 0, target: params.target, stag: 0, stagTarget: params.stag, div: 0, divTarget: params.div, grading: params.grading };
11812
+ const sigintHandler = async () => {
11813
+ if (!running) return;
11814
+ running = false;
11815
+ console.log("\n");
11816
+ console.log(AMBER12(" \u{1F6D1} Aborting simulation..."));
11817
+ try {
11818
+ await callHTTPFunction("userSimManagerService", {
11819
+ action: "abortMission",
11820
+ conversationId,
11821
+ uid: config.uid,
11822
+ email: config.email
11823
+ });
11824
+ console.log(GREEN11(" \u2705 Simulation aborted."));
11825
+ } catch {
11826
+ }
11827
+ process.exit(0);
11828
+ };
11829
+ process.on("SIGINT", sigintHandler);
11830
+ const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
11831
+ rl.setPrompt("");
11832
+ rl.on("line", async (line) => {
11833
+ const trimmed = line.trim();
11834
+ if (!trimmed) return;
11835
+ if (trimmed === "/abort" || trimmed === "abort") {
11836
+ running = false;
11837
+ console.log(AMBER12(" \u{1F6D1} Aborting simulation..."));
11838
+ try {
11839
+ await callHTTPFunction("userSimManagerService", {
11840
+ action: "abortMission",
11841
+ conversationId,
11842
+ uid: config.uid,
11843
+ email: config.email
11844
+ });
11845
+ console.log(GREEN11(" \u2705 Simulation aborted."));
11846
+ } catch {
11847
+ }
11848
+ rl.close();
11849
+ process.exit(0);
11850
+ }
11851
+ await handleSlashCommand(trimmed, config, conversationId);
11852
+ });
11853
+ while (running) {
11854
+ await new Promise((r) => setTimeout(r, 3e3));
11855
+ try {
11856
+ const response = await callCloudFunction("getCLIConversationMessages", {
11857
+ conversationId,
11858
+ since: lastMessageTimestamp || null
11859
+ });
11860
+ const messages = response?.messages || [];
11861
+ const state = response?.state || {};
11862
+ for (const msg of messages) {
11863
+ renderMessage(msg.sender, msg.message, msg.simulationAudit);
11864
+ if (msg.timestamp && msg.timestamp > lastMessageTimestamp) {
11865
+ lastMessageTimestamp = msg.timestamp;
11866
+ }
11867
+ }
11868
+ if (state.currentSatisfaction !== void 0) hudState.sat = state.currentSatisfaction;
11869
+ if (state.targetSatisfaction !== void 0) hudState.target = state.targetSatisfaction;
11870
+ if (state.gradingStandard !== void 0) hudState.grading = state.gradingStandard;
11871
+ if (state.stalemateState) {
11872
+ hudState.stag = state.stalemateState.current ?? hudState.stag;
11873
+ hudState.stagTarget = state.stalemateState.target ?? hudState.stagTarget;
11874
+ }
11875
+ if (state.divergenceState) {
11876
+ hudState.div = state.divergenceState.current ?? hudState.div;
11877
+ hudState.divTarget = state.divergenceState.target ?? hudState.divTarget;
11878
+ }
11879
+ if (state.userBobActive === false || state.simulationStatus && state.simulationStatus !== "RUNNING") {
11880
+ if (messages.length > 0) {
11881
+ renderHUD(hudState.sat, hudState.target, hudState.stag, hudState.stagTarget, hudState.div, hudState.divTarget, hudState.grading);
11882
+ }
11883
+ console.log("");
11884
+ console.log(AMBER12(` \u{1F3C1} Simulation ended: ${state.simulationStatus || "INACTIVE"}`));
11885
+ console.log("");
11886
+ running = false;
11887
+ break;
11888
+ }
11889
+ if (messages.length > 0) {
11890
+ renderHUD(hudState.sat, hudState.target, hudState.stag, hudState.stagTarget, hudState.div, hudState.divTarget, hudState.grading);
11891
+ }
11892
+ } catch (e) {
11893
+ console.log(RED10(` \u274C Poll error: ${e.message}`));
11894
+ }
11895
+ }
11896
+ rl.close();
11897
+ process.removeListener("SIGINT", sigintHandler);
11898
+ }
11899
+ async function runLocalSimulation(config, dnaString, mission, params) {
11900
+ writeSessionFile({ active: true, turns: 0, mission });
11901
+ let running = true;
11902
+ let turns = 0;
11903
+ let conversationHistory = [];
11904
+ let sat = 0;
11905
+ let stalemateCurrent = 0;
11906
+ let divergenceCurrent = 0;
11907
+ let lastStatus = "";
11908
+ const sigintHandler = () => {
11909
+ running = false;
11910
+ writeSessionFile({ active: false });
11911
+ clearSessionFile();
11912
+ console.log("\n" + AMBER12(" \u{1F6D1} Simulation stopped."));
11913
+ process.exit(0);
11914
+ };
11915
+ process.on("SIGINT", sigintHandler);
11916
+ const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
11917
+ rl.setPrompt("");
11918
+ rl.on("line", (line) => {
11919
+ const t = line.trim();
11920
+ if (t === "/abort" || t === "abort") {
11921
+ running = false;
11922
+ writeSessionFile({ active: false });
11923
+ clearSessionFile();
11924
+ console.log(AMBER12(" \u{1F6D1} Simulation stopped."));
11925
+ rl.close();
11926
+ process.exit(0);
11927
+ }
11928
+ if (t.startsWith("/set ")) {
11929
+ const m = t.match(/^\/set\s+(grading|target|stag|div)\s+(\d+)$/i);
11930
+ if (m) {
11931
+ const val = parseInt(m[2], 10);
11932
+ if (m[1] === "grading") params.grading = val;
11933
+ if (m[1] === "target") params.target = val;
11934
+ if (m[1] === "stag") params.stag = val;
11935
+ if (m[1] === "div") params.div = val;
11936
+ console.log(GREEN11(` \u2705 ${m[1]} updated to ${val} (local)`));
11937
+ }
11938
+ }
11939
+ if (t === "/status") {
11940
+ console.log("");
11941
+ console.log(AMBER12(" \u2500\u2500\u2500 Local Sim Parameters \u2500\u2500\u2500"));
11942
+ console.log(GRAY10(` Target: ${params.target} \u2502 Grading: ${params.grading} \u2502 Stag Limit: ${params.stag} \u2502 Div Limit: ${params.div}`));
11943
+ console.log(GRAY10(` Current SAT: ${sat} \u2502 Turns: ${turns} \u2502 Stag: ${stalemateCurrent} \u2502 Div: ${divergenceCurrent}`));
11944
+ console.log("");
11945
+ }
11946
+ });
11947
+ const bobSystem = `You are Bob \u2014 a senior AI engineering consultant. A developer's digital twin (UserBob) is evaluating your work. Respond helpfully and directly to advance the mission. Mission context: ${mission}`;
11948
+ const userBobSystem = dnaString ? `You are a digital twin of a software engineer. You ARE this developer. Your personality, communication style, and engineering philosophy are defined below.
11949
+
11950
+ Mission: ${mission}
11951
+
11952
+ ${dnaString}
11953
+
11954
+ After each Bob response, evaluate it 0-100 on how well it advances YOUR mission. Reply with your natural reaction, then append exactly one JSON footer on its own line:
11955
+ {"satisfactionScore": <0-100>, "status": "CONVERGING|STAGNATING|DIVERGING"}` : `You are a digital twin of a software engineer. You have no personal profile loaded \u2014 respond based on the mission context only.
11956
+
11957
+ Mission: ${mission}
11958
+
11959
+ After each Bob response, evaluate it 0-100 on mission alignment. Reply with your reaction, then append exactly one JSON footer on its own line:
11960
+ {"satisfactionScore": <0-100>, "status": "CONVERGING|STAGNATING|DIVERGING"}`;
11961
+ console.log(BORDER14(" \u2500\u2500\u2500 LIVE LOCAL SIMULATION \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11962
+ console.log(GRAY10(" Bob and UserBob will converse autonomously below."));
11963
+ console.log(GRAY10(" Commands:"));
11964
+ console.log(AMBER12(" /abort") + GRAY10(" \u2014 Stop the simulation"));
11965
+ console.log(AMBER12(" /set target 90") + GRAY10(" \u2014 Update satisfaction target"));
11966
+ console.log(AMBER12(" /set grading 70") + GRAY10(" \u2014 Update Teacher's Curve"));
11967
+ console.log(AMBER12(" /set stag 5") + GRAY10(" \u2014 Update stalemate threshold"));
11968
+ console.log(AMBER12(" /set div 3") + GRAY10(" \u2014 Update divergence threshold"));
11969
+ console.log(AMBER12(" /status") + GRAY10(" \u2014 Show current parameters"));
11970
+ console.log(BORDER14(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11971
+ console.log("");
11972
+ const kickstart = `Mission received: "${mission}". Bob, what's your first move?`;
11973
+ console.log(PURPLE5(" UserBob > ") + WHITE7(kickstart));
11974
+ conversationHistory.push({ role: "user", content: kickstart });
11975
+ while (running) {
11976
+ const session = readSessionFile();
11977
+ if (!session?.active) {
11978
+ running = false;
11979
+ break;
11980
+ }
11981
+ turns++;
11982
+ try {
11983
+ const bobMessages = [
11984
+ { role: "system", content: bobSystem },
11985
+ ...conversationHistory
11986
+ ];
11987
+ const bobResponse = await callLocalModel(config.localEndpoint, bobMessages);
11988
+ console.log(BOB_COLOR(" Bob > ") + WHITE7(bobResponse));
11989
+ conversationHistory.push({ role: "assistant", content: bobResponse });
11990
+ const ubMessages = [
11991
+ { role: "system", content: userBobSystem },
11992
+ ...conversationHistory
11993
+ ];
11994
+ const ubResponse = await callLocalModel(config.localEndpoint, ubMessages);
11995
+ const jsonMatch = ubResponse.match(/\{[^}]*"satisfactionScore"[^}]*\}/);
11996
+ const cleanResponse = ubResponse.replace(/\{[^}]*"satisfactionScore"[^}]*\}/, "").trim();
11997
+ console.log(PURPLE5(" UserBob > ") + WHITE7(cleanResponse));
11998
+ let auditChips = [];
11999
+ if (jsonMatch) {
12000
+ try {
12001
+ const audit = JSON.parse(jsonMatch[0]);
12002
+ const rawScore = audit.satisfactionScore || 0;
12003
+ sat = Math.round(rawScore * (params.grading / 100));
12004
+ lastStatus = audit.status || "";
12005
+ auditChips = [CYAN11(`[SAT: ${sat}%]`), BLUE5(`[RAW: ${rawScore}]`), GRAY10(`[${lastStatus}]`)];
12006
+ if (lastStatus === "STAGNATING") {
12007
+ stalemateCurrent++;
12008
+ if (params.stag > 0 && stalemateCurrent >= params.stag) {
12009
+ console.log(" " + auditChips.join(" "));
12010
+ renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
12011
+ console.log(AMBER12(` \u{1F3C1} Stalemate threshold reached (${stalemateCurrent}/${params.stag}). Simulation ended.`));
12012
+ running = false;
12013
+ break;
12014
+ }
12015
+ } else if (lastStatus === "DIVERGING") {
12016
+ divergenceCurrent++;
12017
+ stalemateCurrent = 0;
12018
+ if (params.div > 0 && divergenceCurrent >= params.div) {
12019
+ console.log(" " + auditChips.join(" "));
12020
+ renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
12021
+ console.log(AMBER12(` \u{1F3C1} Divergence threshold reached (${divergenceCurrent}/${params.div}). Simulation ended.`));
12022
+ running = false;
12023
+ break;
12024
+ }
12025
+ } else if (lastStatus === "CONVERGING") {
12026
+ stalemateCurrent = 0;
12027
+ divergenceCurrent = 0;
12028
+ }
12029
+ } catch {
12030
+ }
12031
+ }
12032
+ if (auditChips.length) console.log(" " + auditChips.join(" "));
12033
+ conversationHistory.push({ role: "user", content: ubResponse });
12034
+ writeSessionFile({ active: true, turns, mission, sat });
12035
+ renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
12036
+ if (sat >= params.target) {
12037
+ console.log(GREEN11(` \u{1F3AF} Target satisfaction ${params.target}% reached! Mission complete.`));
12038
+ running = false;
12039
+ break;
12040
+ }
12041
+ await new Promise((r) => setTimeout(r, 1e3));
12042
+ } catch (e) {
12043
+ console.log(RED10(` \u274C Local model error: ${e.message}`));
12044
+ console.log(GRAY10(" Retrying in 3 seconds..."));
12045
+ await new Promise((r) => setTimeout(r, 3e3));
12046
+ }
12047
+ }
12048
+ clearSessionFile();
12049
+ rl.close();
12050
+ process.removeListener("SIGINT", sigintHandler);
12051
+ console.log("");
12052
+ console.log(GRAY10(` Session complete. ${turns} turns processed.`));
12053
+ console.log("");
12054
+ }
12055
+ function registerUserBobCommand(program2) {
12056
+ program2.command("userbob [mission...]").description("Launch your UserBob digital twin simulation").option("--local", "Force local Ollama mode (Tier 1)").option("--target <number>", "Satisfaction target (default: 85)", "85").option("--grading <number>", "Teacher's curve grading standard (default: 50)", "50").option("--stag <number>", "Stalemate threshold \u2014 0 = infinite (default: 0)", "0").option("--div <number>", "Divergence threshold \u2014 0 = infinite (default: 0)", "0").option("--resume", "Resume without injecting a new mission note").action(async (missionArgs, options) => {
12057
+ const config = getConfig();
12058
+ const params = {
12059
+ target: parseInt(options.target, 10),
12060
+ grading: parseInt(options.grading, 10),
12061
+ stag: parseInt(options.stag, 10),
12062
+ div: parseInt(options.div, 10)
12063
+ };
12064
+ const usePlatform = !options.local && isAuthenticated();
12065
+ console.log("");
12066
+ console.log(BORDER14(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
12067
+ console.log(BORDER14(" \u2551") + PURPLE5(" \u{1F916} UserBob \u2014 Digital Twin Simulation"));
12068
+ console.log(BORDER14(" \u2551") + GRAY10(` Mode: ${usePlatform ? "Platform (Tier 3)" : "Local Ollama (Tier 1)"}`));
12069
+ console.log(BORDER14(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
12070
+ console.log("");
12071
+ const dna = buildDNAString();
12072
+ if (dna) {
12073
+ console.log(GREEN11(" \u2705 Behavioral DNA loaded."));
12074
+ } else {
12075
+ console.log(AMBER12(" \u26A0\uFE0F No behavioral profile found."));
12076
+ console.log(GRAY10(" UserBob performs significantly better with your DNA loaded."));
12077
+ console.log("");
12078
+ const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
12079
+ const answer = await new Promise((resolve4) => rl.question(AMBER12(" Run `bob profile --today` now? (y/n): "), resolve4));
12080
+ rl.close();
12081
+ if (answer.trim().toLowerCase() === "y") {
12082
+ console.log("");
12083
+ console.log(GRAY10(" Run `bob profile --today` in a separate terminal, then re-run `bob userbob`."));
12084
+ process.exit(0);
12085
+ } else {
12086
+ console.log("");
12087
+ console.log(RED10(" \u26A0\uFE0F Running in Generic Mode \u2014 no behavioral profile loaded."));
12088
+ console.log(RED10(" UserBob will respond using project context only."));
12089
+ console.log(RED10(" Responses won't reflect your personal communication style,"));
12090
+ console.log(RED10(" decision patterns, or engineering philosophy."));
12091
+ console.log(GRAY10(" Run `bob profile --today` anytime to unlock full personalization."));
12092
+ console.log("");
12093
+ }
12094
+ }
12095
+ let mission = missionArgs.length > 0 ? missionArgs.join(" ") : "";
12096
+ if (!mission && !options.resume) {
12097
+ const mrl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
12098
+ mission = await new Promise((resolve4) => mrl.question(AMBER12(" What's the mission? > "), resolve4));
12099
+ mrl.close();
12100
+ if (!mission.trim()) {
12101
+ console.log(RED10(" \u274C Mission cannot be empty. Exiting."));
12102
+ process.exit(1);
12103
+ }
12104
+ mission = mission.trim();
12105
+ }
12106
+ console.log("");
12107
+ console.log(GRAY10(` Target: ${params.target}% \u2502 Grade: ${params.grading} \u2502 Stag: ${params.stag || "\u221E"} \u2502 Div: ${params.div || "\u221E"}`));
12108
+ console.log("");
12109
+ if (usePlatform) {
12110
+ const conversationId = getActiveConversationId(process.cwd()) || config.conversationId;
12111
+ if (!conversationId) {
12112
+ console.log(RED10(" \u274C No active conversation. Run `bob conversations join` first."));
12113
+ process.exit(1);
12114
+ }
12115
+ if (options.resume) {
12116
+ console.log(AMBER12(" \u{1F504} Resuming simulation (no new mission note)..."));
12117
+ await callHTTPFunction("userSimManagerService", {
12118
+ action: "resumeMission",
12119
+ conversationId,
12120
+ uid: config.uid,
12121
+ email: config.email
12122
+ });
12123
+ console.log(GREEN11(" \u2705 Simulation resumed. Entering watch mode..."));
12124
+ console.log("");
12125
+ await runPlatformSimulation(config, conversationId, mission || "Resumed session", params);
12126
+ } else {
12127
+ await runPlatformSimulation(config, conversationId, mission, params);
12128
+ }
12129
+ return;
12130
+ }
12131
+ if (!config.localEndpoint) {
12132
+ console.log(RED10(" \u274C No local model configured."));
12133
+ console.log(GRAY10(" Run: bob config set localEndpoint http://127.0.0.1:11434/api/chat"));
12134
+ process.exit(1);
12135
+ }
12136
+ await runLocalSimulation(config, dna, mission, params);
12137
+ });
12138
+ }
12139
+
11251
12140
  // bin/bob.ts
11252
12141
  var program = new Command();
11253
12142
  program.name("bob").description("Bob's CLI \u2014 AI coding assistant and Forge orchestrator").version("0.8.0");
11254
12143
  program.command("whoami").description("Show current authentication status and configuration").action(() => {
11255
12144
  const config = getConfig();
11256
- const projectName = path22.basename(process.cwd());
12145
+ const projectName = path23.basename(process.cwd());
11257
12146
  const projectConvoId = getActiveConversationId(process.cwd()) || config.conversationId;
11258
12147
  console.log("");
11259
- console.log(chalk31.bold(" \u{1F916} Bob's CLI"));
11260
- console.log(chalk31.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11261
- console.log(` ${chalk31.cyan("Status:")} ${config.loggedIn ? chalk31.green("Logged in as " + config.email) : "Not logged in"}`);
11262
- console.log(` ${chalk31.cyan("Tier:")} ${config.tier === "platform" ? "Platform (Tier 3)" : "Local-first (Tier 1)"}`);
11263
- console.log(` ${chalk31.cyan("Provider:")} ${config.provider || "Not configured"}`);
11264
- console.log(` ${chalk31.cyan("Mode:")} ${config.personalizationMode ? "Personalized" : config.consultantMode ? "Consultant" : "Standard"}`);
11265
- console.log(` ${chalk31.cyan("IDRP:")} ${config.idrp ? "Enabled" : "Disabled"}`);
11266
- console.log(` ${chalk31.cyan("Project:")} ${projectName} (${process.cwd()})`);
11267
- console.log(` ${chalk31.cyan("Session:")} ${projectConvoId ? projectConvoId.slice(0, 20) + "..." : "None"}`);
12148
+ console.log(chalk32.bold(" \u{1F916} Bob's CLI"));
12149
+ console.log(chalk32.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
12150
+ console.log(` ${chalk32.cyan("Status:")} ${config.loggedIn ? chalk32.green("Logged in as " + config.email) : "Not logged in"}`);
12151
+ console.log(` ${chalk32.cyan("Tier:")} ${config.tier === "platform" ? "Platform (Tier 3)" : "Local-first (Tier 1)"}`);
12152
+ console.log(` ${chalk32.cyan("Provider:")} ${config.provider || "Not configured"}`);
12153
+ console.log(` ${chalk32.cyan("Mode:")} ${config.personalizationMode ? "Personalized" : config.consultantMode ? "Consultant" : "Standard"}`);
12154
+ console.log(` ${chalk32.cyan("IDRP:")} ${config.idrp ? "Enabled" : "Disabled"}`);
12155
+ console.log(` ${chalk32.cyan("Project:")} ${projectName} (${process.cwd()})`);
12156
+ console.log(` ${chalk32.cyan("Session:")} ${projectConvoId ? projectConvoId.slice(0, 20) + "..." : "None"}`);
11268
12157
  console.log("");
11269
12158
  if (!config.loggedIn) {
11270
- console.log(chalk31.gray(" Run `bob login` to authenticate."));
12159
+ console.log(chalk32.gray(" Run `bob login` to authenticate."));
11271
12160
  console.log("");
11272
12161
  }
11273
12162
  });
@@ -11289,4 +12178,5 @@ registerProfileCommand(program);
11289
12178
  registerBackupCommand(program);
11290
12179
  registerAgentCommand(program);
11291
12180
  registerAgentRunCommand(program);
12181
+ registerUserBobCommand(program);
11292
12182
  program.parse();