@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/README.md +111 -3
- package/dist/analyse-auto-VFZGDTTQ.js +530 -0
- package/dist/analyse-results-XAVKSCF4.js +9 -0
- package/dist/bob.js +1017 -127
- package/dist/chunk-WRMNJJA6.js +1259 -0
- package/package.json +1 -1
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-
|
|
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
|
|
489
|
-
import * as
|
|
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("
|
|
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
|
-
|
|
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", {
|
|
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", {
|
|
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
|
|
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
|
-
|
|
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
|
|
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-
|
|
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-
|
|
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
|
|
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(
|
|
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") +
|
|
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") +
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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(
|
|
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") +
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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:")} ${
|
|
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:")} ${
|
|
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:")} ${
|
|
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:")} ${
|
|
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
|
|
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(
|
|
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(
|
|
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") +
|
|
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(
|
|
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") +
|
|
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(
|
|
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") +
|
|
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(
|
|
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") +
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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") +
|
|
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} ${
|
|
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(
|
|
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(
|
|
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} ${
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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
|
|
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") +
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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") +
|
|
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") +
|
|
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:
|
|
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") +
|
|
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:
|
|
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") +
|
|
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
|
|
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") +
|
|
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") +
|
|
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:
|
|
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
|
|
10732
|
-
const
|
|
10733
|
-
const
|
|
10734
|
-
const
|
|
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") +
|
|
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 =
|
|
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(
|
|
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 =
|
|
10778
|
-
const feedbackDir =
|
|
10779
|
-
if (!
|
|
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 =
|
|
10787
|
-
|
|
10788
|
-
const globalDir =
|
|
10789
|
-
if (!
|
|
10790
|
-
const globalFile =
|
|
10791
|
-
|
|
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
|
|
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") +
|
|
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 =
|
|
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(
|
|
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(
|
|
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:
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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(
|
|
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(
|
|
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 =
|
|
12145
|
+
const projectName = path23.basename(process.cwd());
|
|
11257
12146
|
const projectConvoId = getActiveConversationId(process.cwd()) || config.conversationId;
|
|
11258
12147
|
console.log("");
|
|
11259
|
-
console.log(
|
|
11260
|
-
console.log(
|
|
11261
|
-
console.log(` ${
|
|
11262
|
-
console.log(` ${
|
|
11263
|
-
console.log(` ${
|
|
11264
|
-
console.log(` ${
|
|
11265
|
-
console.log(` ${
|
|
11266
|
-
console.log(` ${
|
|
11267
|
-
console.log(` ${
|
|
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(
|
|
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();
|