@bobsworkshop/cli 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyse-auto-VFZGDTTQ.js +530 -0
- package/dist/analyse-results-XAVKSCF4.js +9 -0
- package/dist/bob.js +605 -33
- 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.
|
|
@@ -3462,7 +3485,7 @@ function registerAnalyseCommand(program2) {
|
|
|
3462
3485
|
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
3486
|
const config = getConfig();
|
|
3464
3487
|
if (options.auto) {
|
|
3465
|
-
const { runAutoFix } = await import("./analyse-auto-
|
|
3488
|
+
const { runAutoFix } = await import("./analyse-auto-VFZGDTTQ.js");
|
|
3466
3489
|
const category = options.bugs ? "bugs" : options.features ? "features" : options.improvements ? "improvements" : options.upgrades ? "upgrades" : void 0;
|
|
3467
3490
|
await runAutoFix({
|
|
3468
3491
|
category,
|
|
@@ -3472,7 +3495,7 @@ function registerAnalyseCommand(program2) {
|
|
|
3472
3495
|
return;
|
|
3473
3496
|
}
|
|
3474
3497
|
if (options.bugs || options.features || options.improvements || options.upgrades) {
|
|
3475
|
-
const { showInteractiveResults } = await import("./analyse-results-
|
|
3498
|
+
const { showInteractiveResults } = await import("./analyse-results-XAVKSCF4.js");
|
|
3476
3499
|
const category = options.bugs ? "bugs" : options.features ? "features" : options.improvements ? "improvements" : "upgrades";
|
|
3477
3500
|
await showInteractiveResults(config, category, options.sort, options.search);
|
|
3478
3501
|
return;
|
|
@@ -10728,10 +10751,10 @@ function renderExecutionEvent(event, agentNames) {
|
|
|
10728
10751
|
}
|
|
10729
10752
|
}
|
|
10730
10753
|
async function renderPostMissionFeedback(mission, cwd) {
|
|
10731
|
-
const
|
|
10732
|
-
const
|
|
10733
|
-
const
|
|
10734
|
-
const
|
|
10754
|
+
const readline12 = await import("readline");
|
|
10755
|
+
const path24 = await import("path");
|
|
10756
|
+
const fs19 = await import("fs");
|
|
10757
|
+
const os9 = await import("os");
|
|
10735
10758
|
console.log("");
|
|
10736
10759
|
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
10760
|
console.log(DIRECTOR_COLOR(" \u2551") + AMBER9(" \u{1F4DD} Mission Feedback \u2014 Help train the agents"));
|
|
@@ -10742,7 +10765,7 @@ async function renderPostMissionFeedback(mission, cwd) {
|
|
|
10742
10765
|
console.log("");
|
|
10743
10766
|
const completedTasks = mission.tasks.filter((t) => t.status === "completed");
|
|
10744
10767
|
const feedback = [];
|
|
10745
|
-
const rl =
|
|
10768
|
+
const rl = readline12.createInterface({ input: process.stdin, output: process.stdout });
|
|
10746
10769
|
for (const task of completedTasks) {
|
|
10747
10770
|
const chip = renderAgentChip(task.assignedTo, mission.tasks.map((t) => t.assignedTo), true);
|
|
10748
10771
|
console.log(` ${chip} ${GRAY8(task.instruction.slice(0, 60))}`);
|
|
@@ -10774,21 +10797,21 @@ async function renderPostMissionFeedback(mission, cwd) {
|
|
|
10774
10797
|
}
|
|
10775
10798
|
rl.close();
|
|
10776
10799
|
if (feedback.length === 0) return;
|
|
10777
|
-
const projectName =
|
|
10778
|
-
const feedbackDir =
|
|
10779
|
-
if (!
|
|
10800
|
+
const projectName = path24.basename(cwd);
|
|
10801
|
+
const feedbackDir = path24.join(os9.homedir(), ".bob", "projects", projectName, "agents", "feedback");
|
|
10802
|
+
if (!fs19.existsSync(feedbackDir)) fs19.mkdirSync(feedbackDir, { recursive: true });
|
|
10780
10803
|
const sessionFeedback = {
|
|
10781
10804
|
missionId: mission.id,
|
|
10782
10805
|
missionDescription: mission.description,
|
|
10783
10806
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10784
10807
|
tasks: feedback
|
|
10785
10808
|
};
|
|
10786
|
-
const feedbackFile =
|
|
10787
|
-
|
|
10788
|
-
const globalDir =
|
|
10789
|
-
if (!
|
|
10790
|
-
const globalFile =
|
|
10791
|
-
|
|
10809
|
+
const feedbackFile = path24.join(feedbackDir, `${mission.id}.json`);
|
|
10810
|
+
fs19.writeFileSync(feedbackFile, JSON.stringify(sessionFeedback, null, 2));
|
|
10811
|
+
const globalDir = path24.join(os9.homedir(), ".bob", "global", "agent-training");
|
|
10812
|
+
if (!fs19.existsSync(globalDir)) fs19.mkdirSync(globalDir, { recursive: true });
|
|
10813
|
+
const globalFile = path24.join(globalDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}_${mission.id}.json`);
|
|
10814
|
+
fs19.writeFileSync(globalFile, JSON.stringify(sessionFeedback, null, 2));
|
|
10792
10815
|
console.log(GREEN9(` \u2705 Feedback saved. Thank you for helping train the agents.`));
|
|
10793
10816
|
console.log(GRAY8(` Saved to: ~/.bob/projects/${projectName}/agents/feedback/`));
|
|
10794
10817
|
console.log(GRAY8(` Global: ~/.bob/global/agent-training/`));
|
|
@@ -10823,7 +10846,7 @@ function renderMissionComplete(mission) {
|
|
|
10823
10846
|
console.log("");
|
|
10824
10847
|
}
|
|
10825
10848
|
async function renderPostMissionCommitPrompt(mission, cwd) {
|
|
10826
|
-
const
|
|
10849
|
+
const readline12 = await import("readline");
|
|
10827
10850
|
const allCreated = [];
|
|
10828
10851
|
const allModified = [];
|
|
10829
10852
|
for (const task of mission.tasks) {
|
|
@@ -10899,7 +10922,7 @@ async function renderPostMissionCommitPrompt(mission, cwd) {
|
|
|
10899
10922
|
console.log(BORDER13(" \u2551") + GRAY8(` ${allCreated.length} created \u2502 ${allModified.length} modified \u2502 ${totalFiles} total`));
|
|
10900
10923
|
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
10924
|
console.log("");
|
|
10902
|
-
const rl =
|
|
10925
|
+
const rl = readline12.createInterface({
|
|
10903
10926
|
input: process.stdin,
|
|
10904
10927
|
output: process.stdout
|
|
10905
10928
|
});
|
|
@@ -11248,26 +11271,574 @@ async function executeMission(mission, agents, cwd, localEndpoint, options) {
|
|
|
11248
11271
|
}
|
|
11249
11272
|
}
|
|
11250
11273
|
|
|
11274
|
+
// src/commands/userbob.ts
|
|
11275
|
+
import chalk31 from "chalk";
|
|
11276
|
+
import * as readline11 from "readline";
|
|
11277
|
+
import * as fs18 from "fs";
|
|
11278
|
+
import * as path22 from "path";
|
|
11279
|
+
import * as os8 from "os";
|
|
11280
|
+
var PURPLE5 = chalk31.hex("#AB47BC");
|
|
11281
|
+
var AMBER11 = chalk31.hex("#FFAB00");
|
|
11282
|
+
var GREEN11 = chalk31.hex("#66BB6A");
|
|
11283
|
+
var CYAN11 = chalk31.hex("#26C6DA");
|
|
11284
|
+
var RED10 = chalk31.hex("#EF5350");
|
|
11285
|
+
var GRAY10 = chalk31.gray;
|
|
11286
|
+
var BLUE5 = chalk31.hex("#42A5F5");
|
|
11287
|
+
var BOB_COLOR = chalk31.hex("#E66F24");
|
|
11288
|
+
var BORDER14 = chalk31.hex("#455A64");
|
|
11289
|
+
var WHITE7 = chalk31.white;
|
|
11290
|
+
var BOB_DIR8 = path22.join(os8.homedir(), ".bob");
|
|
11291
|
+
function getSessionFilePath() {
|
|
11292
|
+
const projectName = path22.basename(process.cwd());
|
|
11293
|
+
return path22.join(BOB_DIR8, "projects", projectName, "userbob-session.json");
|
|
11294
|
+
}
|
|
11295
|
+
function writeSessionFile(data) {
|
|
11296
|
+
const filePath = getSessionFilePath();
|
|
11297
|
+
const dir = path22.dirname(filePath);
|
|
11298
|
+
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
11299
|
+
fs18.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
11300
|
+
}
|
|
11301
|
+
function readSessionFile() {
|
|
11302
|
+
const filePath = getSessionFilePath();
|
|
11303
|
+
if (!fs18.existsSync(filePath)) return null;
|
|
11304
|
+
try {
|
|
11305
|
+
return JSON.parse(fs18.readFileSync(filePath, "utf-8"));
|
|
11306
|
+
} catch {
|
|
11307
|
+
return null;
|
|
11308
|
+
}
|
|
11309
|
+
}
|
|
11310
|
+
function clearSessionFile() {
|
|
11311
|
+
const filePath = getSessionFilePath();
|
|
11312
|
+
if (fs18.existsSync(filePath)) fs18.unlinkSync(filePath);
|
|
11313
|
+
}
|
|
11314
|
+
function renderHUD(sat, target, stag, stagTarget, div, divTarget, grading) {
|
|
11315
|
+
const satBar = sat >= target ? GREEN11(`${sat}%`) : sat >= target * 0.7 ? AMBER11(`${sat}%`) : RED10(`${sat}%`);
|
|
11316
|
+
console.log("");
|
|
11317
|
+
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"));
|
|
11318
|
+
console.log(
|
|
11319
|
+
` SAT: ${satBar} \u2192 ${target}% \u2502 STAG: ${stag}/${stagTarget > 0 ? stagTarget : "\u221E"} \u2502 DIV: ${div}/${divTarget > 0 ? divTarget : "\u221E"} \u2502 GRADE: ${grading}`
|
|
11320
|
+
);
|
|
11321
|
+
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"));
|
|
11322
|
+
console.log("");
|
|
11323
|
+
}
|
|
11324
|
+
function stripMarkdown2(text) {
|
|
11325
|
+
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();
|
|
11326
|
+
}
|
|
11327
|
+
function renderMessage(sender, message, audit) {
|
|
11328
|
+
const cleanMsg = stripMarkdown2(message);
|
|
11329
|
+
const maxWidth = 70;
|
|
11330
|
+
const lines = wrapText3(cleanMsg, maxWidth - 4);
|
|
11331
|
+
if (sender === "userBob") {
|
|
11332
|
+
const topBar = PURPLE5(` \u250C\u2500 UserBob ${"\u2500".repeat(maxWidth - 13)}\u2510`);
|
|
11333
|
+
const bottomBar = PURPLE5(` \u2514${"\u2500".repeat(maxWidth - 2)}\u2518`);
|
|
11334
|
+
console.log("");
|
|
11335
|
+
console.log(topBar);
|
|
11336
|
+
for (const line of lines) {
|
|
11337
|
+
const padded = line.padEnd(maxWidth - 4);
|
|
11338
|
+
console.log(PURPLE5(" \u2502") + ` ${padded}` + PURPLE5(" \u2502"));
|
|
11339
|
+
}
|
|
11340
|
+
console.log(bottomBar);
|
|
11341
|
+
if (audit) {
|
|
11342
|
+
const chips = [];
|
|
11343
|
+
if (audit.satisfactionScore !== void 0) chips.push(CYAN11(`[SAT: ${audit.satisfactionScore}%]`));
|
|
11344
|
+
if (audit.resemblanceScore !== void 0) chips.push(BLUE5(`[RES: ${audit.resemblanceScore}%]`));
|
|
11345
|
+
if (audit.reasoning) chips.push(GRAY10(`[${String(audit.reasoning).slice(0, 50)}...]`));
|
|
11346
|
+
if (chips.length > 0) console.log(" " + chips.join(" "));
|
|
11347
|
+
}
|
|
11348
|
+
} else if (sender === "bob") {
|
|
11349
|
+
const indent = " ";
|
|
11350
|
+
const topBar = BOB_COLOR(`${indent}\u250C${"\u2500".repeat(maxWidth - 12)}\u2500 Bob \u2500\u2510`);
|
|
11351
|
+
const bottomBar = BOB_COLOR(`${indent}\u2514${"\u2500".repeat(maxWidth - 2)}\u2518`);
|
|
11352
|
+
console.log("");
|
|
11353
|
+
console.log(topBar);
|
|
11354
|
+
for (const line of lines) {
|
|
11355
|
+
const padded = line.padEnd(maxWidth - 4);
|
|
11356
|
+
console.log(BOB_COLOR(`${indent}\u2502`) + ` ${padded}` + BOB_COLOR(" \u2502"));
|
|
11357
|
+
}
|
|
11358
|
+
console.log(bottomBar);
|
|
11359
|
+
} else if (sender === "system") {
|
|
11360
|
+
console.log("");
|
|
11361
|
+
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"));
|
|
11362
|
+
console.log(GRAY10(` ${cleanMsg}`));
|
|
11363
|
+
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"));
|
|
11364
|
+
} else {
|
|
11365
|
+
console.log("");
|
|
11366
|
+
console.log(GRAY10(` [${sender.toUpperCase()}] ${cleanMsg}`));
|
|
11367
|
+
}
|
|
11368
|
+
}
|
|
11369
|
+
function wrapText3(text, maxWidth) {
|
|
11370
|
+
const lines = [];
|
|
11371
|
+
const paragraphs = text.split("\n");
|
|
11372
|
+
for (const paragraph of paragraphs) {
|
|
11373
|
+
if (paragraph.trim() === "") {
|
|
11374
|
+
lines.push("");
|
|
11375
|
+
continue;
|
|
11376
|
+
}
|
|
11377
|
+
const words = paragraph.split(" ");
|
|
11378
|
+
let currentLine = "";
|
|
11379
|
+
for (const word of words) {
|
|
11380
|
+
if ((currentLine + " " + word).trim().length > maxWidth) {
|
|
11381
|
+
if (currentLine) lines.push(currentLine.trim());
|
|
11382
|
+
currentLine = word;
|
|
11383
|
+
} else {
|
|
11384
|
+
currentLine = currentLine ? currentLine + " " + word : word;
|
|
11385
|
+
}
|
|
11386
|
+
}
|
|
11387
|
+
if (currentLine.trim()) lines.push(currentLine.trim());
|
|
11388
|
+
}
|
|
11389
|
+
return lines;
|
|
11390
|
+
}
|
|
11391
|
+
async function handleSlashCommand(input, config, conversationId) {
|
|
11392
|
+
const trimmed = input.trim();
|
|
11393
|
+
if (trimmed === "/status") {
|
|
11394
|
+
try {
|
|
11395
|
+
const response = await callCloudFunction("getCLIConversationMessages", { conversationId, since: null });
|
|
11396
|
+
const state = response?.state || {};
|
|
11397
|
+
console.log("");
|
|
11398
|
+
console.log(AMBER11(" \u2500\u2500\u2500 Current Parameters \u2500\u2500\u2500"));
|
|
11399
|
+
console.log(GRAY10(` Target Satisfaction : ${state.targetSatisfaction ?? "N/A"}`));
|
|
11400
|
+
console.log(GRAY10(` Grading Standard : ${state.gradingStandard ?? "N/A"}`));
|
|
11401
|
+
console.log(GRAY10(` Current Satisfaction: ${state.currentSatisfaction ?? "N/A"}`));
|
|
11402
|
+
console.log(GRAY10(` Stalemate : ${state.stalemateState?.current ?? 0}/${state.stalemateState?.target ?? "\u221E"}`));
|
|
11403
|
+
console.log(GRAY10(` Divergence : ${state.divergenceState?.current ?? 0}/${state.divergenceState?.target ?? "\u221E"}`));
|
|
11404
|
+
console.log(GRAY10(` Status : ${state.simulationStatus ?? "UNKNOWN"}`));
|
|
11405
|
+
console.log(GRAY10(` Active : ${state.userBobActive ?? "UNKNOWN"}`));
|
|
11406
|
+
console.log("");
|
|
11407
|
+
} catch {
|
|
11408
|
+
console.log(RED10(" \u274C Could not fetch conversation state."));
|
|
11409
|
+
}
|
|
11410
|
+
return;
|
|
11411
|
+
}
|
|
11412
|
+
const setMatch = trimmed.match(/^\/set\s+(grading|target|stag|div)\s+(\d+)$/i);
|
|
11413
|
+
if (setMatch) {
|
|
11414
|
+
const param = setMatch[1].toLowerCase();
|
|
11415
|
+
const value = parseInt(setMatch[2], 10);
|
|
11416
|
+
const paramMap = {
|
|
11417
|
+
grading: "gradingStandard",
|
|
11418
|
+
target: "targetSatisfaction",
|
|
11419
|
+
stag: "stalemateZone",
|
|
11420
|
+
div: "divergenceThreshold"
|
|
11421
|
+
};
|
|
11422
|
+
try {
|
|
11423
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11424
|
+
action: "updateParameters",
|
|
11425
|
+
conversationId,
|
|
11426
|
+
uid: config.uid,
|
|
11427
|
+
email: config.email,
|
|
11428
|
+
params: { [paramMap[param]]: value }
|
|
11429
|
+
});
|
|
11430
|
+
console.log(GREEN11(` \u2705 ${param} updated to ${value}`));
|
|
11431
|
+
} catch (e) {
|
|
11432
|
+
console.log(RED10(` \u274C Failed to update ${param}: ${e.message}`));
|
|
11433
|
+
}
|
|
11434
|
+
return;
|
|
11435
|
+
}
|
|
11436
|
+
const injectMatch = trimmed.match(/^\/inject\s+"(.+)"$/);
|
|
11437
|
+
if (injectMatch) {
|
|
11438
|
+
const note = injectMatch[1];
|
|
11439
|
+
try {
|
|
11440
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11441
|
+
action: "injectNote",
|
|
11442
|
+
conversationId,
|
|
11443
|
+
uid: config.uid,
|
|
11444
|
+
email: config.email,
|
|
11445
|
+
note
|
|
11446
|
+
});
|
|
11447
|
+
console.log(GREEN11(` \u2705 Director's note injected.`));
|
|
11448
|
+
} catch (e) {
|
|
11449
|
+
console.log(RED10(` \u274C Failed to inject note: ${e.message}`));
|
|
11450
|
+
}
|
|
11451
|
+
return;
|
|
11452
|
+
}
|
|
11453
|
+
console.log(GRAY10(' Commands: /set grading|target|stag|div <n> /inject "note" /status /abort'));
|
|
11454
|
+
}
|
|
11455
|
+
async function runPlatformSimulation(config, conversationId, mission, params) {
|
|
11456
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11457
|
+
action: "updateParameters",
|
|
11458
|
+
conversationId,
|
|
11459
|
+
uid: config.uid,
|
|
11460
|
+
email: config.email,
|
|
11461
|
+
params: {
|
|
11462
|
+
targetSatisfaction: params.target,
|
|
11463
|
+
gradingStandard: params.grading,
|
|
11464
|
+
stalemateZone: params.stag,
|
|
11465
|
+
divergenceThreshold: params.div
|
|
11466
|
+
}
|
|
11467
|
+
});
|
|
11468
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11469
|
+
action: "injectNote",
|
|
11470
|
+
conversationId,
|
|
11471
|
+
uid: config.uid,
|
|
11472
|
+
email: config.email,
|
|
11473
|
+
note: mission
|
|
11474
|
+
});
|
|
11475
|
+
console.log(GREEN11(" \u2705 Mission injected. Simulation is running."));
|
|
11476
|
+
console.log("");
|
|
11477
|
+
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"));
|
|
11478
|
+
console.log(GRAY10(" Messages will stream below as Bob and UserBob interact."));
|
|
11479
|
+
console.log(GRAY10(" You can type commands at any time:"));
|
|
11480
|
+
console.log("");
|
|
11481
|
+
console.log(AMBER11(" /abort") + GRAY10(" \u2014 Stop the simulation immediately"));
|
|
11482
|
+
console.log(AMBER11(" /set target 90") + GRAY10(" \u2014 Update satisfaction target"));
|
|
11483
|
+
console.log(AMBER11(" /set grading 70") + GRAY10(" \u2014 Update Teacher's Curve"));
|
|
11484
|
+
console.log(AMBER11(" /set stag 5") + GRAY10(" \u2014 Update stalemate threshold"));
|
|
11485
|
+
console.log(AMBER11(" /set div 3") + GRAY10(" \u2014 Update divergence threshold"));
|
|
11486
|
+
console.log(AMBER11(' /inject "note"') + GRAY10(" \u2014 Inject a director's note mid-session"));
|
|
11487
|
+
console.log(AMBER11(" /status") + GRAY10(" \u2014 Show current simulation parameters"));
|
|
11488
|
+
console.log("");
|
|
11489
|
+
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"));
|
|
11490
|
+
console.log("");
|
|
11491
|
+
let running = true;
|
|
11492
|
+
let lastMessageTimestamp = 0;
|
|
11493
|
+
let hudState = { sat: 0, target: params.target, stag: 0, stagTarget: params.stag, div: 0, divTarget: params.div, grading: params.grading };
|
|
11494
|
+
const sigintHandler = async () => {
|
|
11495
|
+
if (!running) return;
|
|
11496
|
+
running = false;
|
|
11497
|
+
console.log("\n");
|
|
11498
|
+
console.log(AMBER11(" \u{1F6D1} Aborting simulation..."));
|
|
11499
|
+
try {
|
|
11500
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11501
|
+
action: "abortMission",
|
|
11502
|
+
conversationId,
|
|
11503
|
+
uid: config.uid,
|
|
11504
|
+
email: config.email
|
|
11505
|
+
});
|
|
11506
|
+
console.log(GREEN11(" \u2705 Simulation aborted."));
|
|
11507
|
+
} catch {
|
|
11508
|
+
}
|
|
11509
|
+
process.exit(0);
|
|
11510
|
+
};
|
|
11511
|
+
process.on("SIGINT", sigintHandler);
|
|
11512
|
+
const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
11513
|
+
rl.setPrompt("");
|
|
11514
|
+
rl.on("line", async (line) => {
|
|
11515
|
+
const trimmed = line.trim();
|
|
11516
|
+
if (!trimmed) return;
|
|
11517
|
+
if (trimmed === "/abort" || trimmed === "abort") {
|
|
11518
|
+
running = false;
|
|
11519
|
+
console.log(AMBER11(" \u{1F6D1} Aborting simulation..."));
|
|
11520
|
+
try {
|
|
11521
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11522
|
+
action: "abortMission",
|
|
11523
|
+
conversationId,
|
|
11524
|
+
uid: config.uid,
|
|
11525
|
+
email: config.email
|
|
11526
|
+
});
|
|
11527
|
+
console.log(GREEN11(" \u2705 Simulation aborted."));
|
|
11528
|
+
} catch {
|
|
11529
|
+
}
|
|
11530
|
+
rl.close();
|
|
11531
|
+
process.exit(0);
|
|
11532
|
+
}
|
|
11533
|
+
await handleSlashCommand(trimmed, config, conversationId);
|
|
11534
|
+
});
|
|
11535
|
+
while (running) {
|
|
11536
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
11537
|
+
try {
|
|
11538
|
+
const response = await callCloudFunction("getCLIConversationMessages", {
|
|
11539
|
+
conversationId,
|
|
11540
|
+
since: lastMessageTimestamp || null
|
|
11541
|
+
});
|
|
11542
|
+
const messages = response?.messages || [];
|
|
11543
|
+
const state = response?.state || {};
|
|
11544
|
+
for (const msg of messages) {
|
|
11545
|
+
renderMessage(msg.sender, msg.message, msg.simulationAudit);
|
|
11546
|
+
if (msg.timestamp && msg.timestamp > lastMessageTimestamp) {
|
|
11547
|
+
lastMessageTimestamp = msg.timestamp;
|
|
11548
|
+
}
|
|
11549
|
+
}
|
|
11550
|
+
if (state.currentSatisfaction !== void 0) hudState.sat = state.currentSatisfaction;
|
|
11551
|
+
if (state.targetSatisfaction !== void 0) hudState.target = state.targetSatisfaction;
|
|
11552
|
+
if (state.gradingStandard !== void 0) hudState.grading = state.gradingStandard;
|
|
11553
|
+
if (state.stalemateState) {
|
|
11554
|
+
hudState.stag = state.stalemateState.current ?? hudState.stag;
|
|
11555
|
+
hudState.stagTarget = state.stalemateState.target ?? hudState.stagTarget;
|
|
11556
|
+
}
|
|
11557
|
+
if (state.divergenceState) {
|
|
11558
|
+
hudState.div = state.divergenceState.current ?? hudState.div;
|
|
11559
|
+
hudState.divTarget = state.divergenceState.target ?? hudState.divTarget;
|
|
11560
|
+
}
|
|
11561
|
+
if (state.userBobActive === false || state.simulationStatus && state.simulationStatus !== "RUNNING") {
|
|
11562
|
+
if (messages.length > 0) {
|
|
11563
|
+
renderHUD(hudState.sat, hudState.target, hudState.stag, hudState.stagTarget, hudState.div, hudState.divTarget, hudState.grading);
|
|
11564
|
+
}
|
|
11565
|
+
console.log("");
|
|
11566
|
+
console.log(AMBER11(` \u{1F3C1} Simulation ended: ${state.simulationStatus || "INACTIVE"}`));
|
|
11567
|
+
console.log("");
|
|
11568
|
+
running = false;
|
|
11569
|
+
break;
|
|
11570
|
+
}
|
|
11571
|
+
if (messages.length > 0) {
|
|
11572
|
+
renderHUD(hudState.sat, hudState.target, hudState.stag, hudState.stagTarget, hudState.div, hudState.divTarget, hudState.grading);
|
|
11573
|
+
}
|
|
11574
|
+
} catch (e) {
|
|
11575
|
+
console.log(RED10(` \u274C Poll error: ${e.message}`));
|
|
11576
|
+
}
|
|
11577
|
+
}
|
|
11578
|
+
rl.close();
|
|
11579
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
11580
|
+
}
|
|
11581
|
+
async function runLocalSimulation(config, dnaString, mission, params) {
|
|
11582
|
+
writeSessionFile({ active: true, turns: 0, mission });
|
|
11583
|
+
let running = true;
|
|
11584
|
+
let turns = 0;
|
|
11585
|
+
let conversationHistory = [];
|
|
11586
|
+
let sat = 0;
|
|
11587
|
+
let stalemateCurrent = 0;
|
|
11588
|
+
let divergenceCurrent = 0;
|
|
11589
|
+
let lastStatus = "";
|
|
11590
|
+
const sigintHandler = () => {
|
|
11591
|
+
running = false;
|
|
11592
|
+
writeSessionFile({ active: false });
|
|
11593
|
+
clearSessionFile();
|
|
11594
|
+
console.log("\n" + AMBER11(" \u{1F6D1} Simulation stopped."));
|
|
11595
|
+
process.exit(0);
|
|
11596
|
+
};
|
|
11597
|
+
process.on("SIGINT", sigintHandler);
|
|
11598
|
+
const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
11599
|
+
rl.setPrompt("");
|
|
11600
|
+
rl.on("line", (line) => {
|
|
11601
|
+
const t = line.trim();
|
|
11602
|
+
if (t === "/abort" || t === "abort") {
|
|
11603
|
+
running = false;
|
|
11604
|
+
writeSessionFile({ active: false });
|
|
11605
|
+
clearSessionFile();
|
|
11606
|
+
console.log(AMBER11(" \u{1F6D1} Simulation stopped."));
|
|
11607
|
+
rl.close();
|
|
11608
|
+
process.exit(0);
|
|
11609
|
+
}
|
|
11610
|
+
if (t.startsWith("/set ")) {
|
|
11611
|
+
const m = t.match(/^\/set\s+(grading|target|stag|div)\s+(\d+)$/i);
|
|
11612
|
+
if (m) {
|
|
11613
|
+
const val = parseInt(m[2], 10);
|
|
11614
|
+
if (m[1] === "grading") params.grading = val;
|
|
11615
|
+
if (m[1] === "target") params.target = val;
|
|
11616
|
+
if (m[1] === "stag") params.stag = val;
|
|
11617
|
+
if (m[1] === "div") params.div = val;
|
|
11618
|
+
console.log(GREEN11(` \u2705 ${m[1]} updated to ${val} (local)`));
|
|
11619
|
+
}
|
|
11620
|
+
}
|
|
11621
|
+
if (t === "/status") {
|
|
11622
|
+
console.log("");
|
|
11623
|
+
console.log(AMBER11(" \u2500\u2500\u2500 Local Sim Parameters \u2500\u2500\u2500"));
|
|
11624
|
+
console.log(GRAY10(` Target: ${params.target} \u2502 Grading: ${params.grading} \u2502 Stag Limit: ${params.stag} \u2502 Div Limit: ${params.div}`));
|
|
11625
|
+
console.log(GRAY10(` Current SAT: ${sat} \u2502 Turns: ${turns} \u2502 Stag: ${stalemateCurrent} \u2502 Div: ${divergenceCurrent}`));
|
|
11626
|
+
console.log("");
|
|
11627
|
+
}
|
|
11628
|
+
});
|
|
11629
|
+
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}`;
|
|
11630
|
+
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.
|
|
11631
|
+
|
|
11632
|
+
Mission: ${mission}
|
|
11633
|
+
|
|
11634
|
+
${dnaString}
|
|
11635
|
+
|
|
11636
|
+
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:
|
|
11637
|
+
{"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.
|
|
11638
|
+
|
|
11639
|
+
Mission: ${mission}
|
|
11640
|
+
|
|
11641
|
+
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:
|
|
11642
|
+
{"satisfactionScore": <0-100>, "status": "CONVERGING|STAGNATING|DIVERGING"}`;
|
|
11643
|
+
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"));
|
|
11644
|
+
console.log(GRAY10(" Bob and UserBob will converse autonomously below."));
|
|
11645
|
+
console.log(GRAY10(" Commands:"));
|
|
11646
|
+
console.log(AMBER11(" /abort") + GRAY10(" \u2014 Stop the simulation"));
|
|
11647
|
+
console.log(AMBER11(" /set target 90") + GRAY10(" \u2014 Update satisfaction target"));
|
|
11648
|
+
console.log(AMBER11(" /set grading 70") + GRAY10(" \u2014 Update Teacher's Curve"));
|
|
11649
|
+
console.log(AMBER11(" /set stag 5") + GRAY10(" \u2014 Update stalemate threshold"));
|
|
11650
|
+
console.log(AMBER11(" /set div 3") + GRAY10(" \u2014 Update divergence threshold"));
|
|
11651
|
+
console.log(AMBER11(" /status") + GRAY10(" \u2014 Show current parameters"));
|
|
11652
|
+
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"));
|
|
11653
|
+
console.log("");
|
|
11654
|
+
const kickstart = `Mission received: "${mission}". Bob, what's your first move?`;
|
|
11655
|
+
console.log(PURPLE5(" UserBob > ") + WHITE7(kickstart));
|
|
11656
|
+
conversationHistory.push({ role: "user", content: kickstart });
|
|
11657
|
+
while (running) {
|
|
11658
|
+
const session = readSessionFile();
|
|
11659
|
+
if (!session?.active) {
|
|
11660
|
+
running = false;
|
|
11661
|
+
break;
|
|
11662
|
+
}
|
|
11663
|
+
turns++;
|
|
11664
|
+
try {
|
|
11665
|
+
const bobMessages = [
|
|
11666
|
+
{ role: "system", content: bobSystem },
|
|
11667
|
+
...conversationHistory
|
|
11668
|
+
];
|
|
11669
|
+
const bobResponse = await callLocalModel(config.localEndpoint, bobMessages);
|
|
11670
|
+
console.log(BOB_COLOR(" Bob > ") + WHITE7(bobResponse));
|
|
11671
|
+
conversationHistory.push({ role: "assistant", content: bobResponse });
|
|
11672
|
+
const ubMessages = [
|
|
11673
|
+
{ role: "system", content: userBobSystem },
|
|
11674
|
+
...conversationHistory
|
|
11675
|
+
];
|
|
11676
|
+
const ubResponse = await callLocalModel(config.localEndpoint, ubMessages);
|
|
11677
|
+
const jsonMatch = ubResponse.match(/\{[^}]*"satisfactionScore"[^}]*\}/);
|
|
11678
|
+
const cleanResponse = ubResponse.replace(/\{[^}]*"satisfactionScore"[^}]*\}/, "").trim();
|
|
11679
|
+
console.log(PURPLE5(" UserBob > ") + WHITE7(cleanResponse));
|
|
11680
|
+
let auditChips = [];
|
|
11681
|
+
if (jsonMatch) {
|
|
11682
|
+
try {
|
|
11683
|
+
const audit = JSON.parse(jsonMatch[0]);
|
|
11684
|
+
const rawScore = audit.satisfactionScore || 0;
|
|
11685
|
+
sat = Math.round(rawScore * (params.grading / 100));
|
|
11686
|
+
lastStatus = audit.status || "";
|
|
11687
|
+
auditChips = [CYAN11(`[SAT: ${sat}%]`), BLUE5(`[RAW: ${rawScore}]`), GRAY10(`[${lastStatus}]`)];
|
|
11688
|
+
if (lastStatus === "STAGNATING") {
|
|
11689
|
+
stalemateCurrent++;
|
|
11690
|
+
if (params.stag > 0 && stalemateCurrent >= params.stag) {
|
|
11691
|
+
console.log(" " + auditChips.join(" "));
|
|
11692
|
+
renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
|
|
11693
|
+
console.log(AMBER11(` \u{1F3C1} Stalemate threshold reached (${stalemateCurrent}/${params.stag}). Simulation ended.`));
|
|
11694
|
+
running = false;
|
|
11695
|
+
break;
|
|
11696
|
+
}
|
|
11697
|
+
} else if (lastStatus === "DIVERGING") {
|
|
11698
|
+
divergenceCurrent++;
|
|
11699
|
+
stalemateCurrent = 0;
|
|
11700
|
+
if (params.div > 0 && divergenceCurrent >= params.div) {
|
|
11701
|
+
console.log(" " + auditChips.join(" "));
|
|
11702
|
+
renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
|
|
11703
|
+
console.log(AMBER11(` \u{1F3C1} Divergence threshold reached (${divergenceCurrent}/${params.div}). Simulation ended.`));
|
|
11704
|
+
running = false;
|
|
11705
|
+
break;
|
|
11706
|
+
}
|
|
11707
|
+
} else if (lastStatus === "CONVERGING") {
|
|
11708
|
+
stalemateCurrent = 0;
|
|
11709
|
+
divergenceCurrent = 0;
|
|
11710
|
+
}
|
|
11711
|
+
} catch {
|
|
11712
|
+
}
|
|
11713
|
+
}
|
|
11714
|
+
if (auditChips.length) console.log(" " + auditChips.join(" "));
|
|
11715
|
+
conversationHistory.push({ role: "user", content: ubResponse });
|
|
11716
|
+
writeSessionFile({ active: true, turns, mission, sat });
|
|
11717
|
+
renderHUD(sat, params.target, stalemateCurrent, params.stag, divergenceCurrent, params.div, params.grading);
|
|
11718
|
+
if (sat >= params.target) {
|
|
11719
|
+
console.log(GREEN11(` \u{1F3AF} Target satisfaction ${params.target}% reached! Mission complete.`));
|
|
11720
|
+
running = false;
|
|
11721
|
+
break;
|
|
11722
|
+
}
|
|
11723
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
11724
|
+
} catch (e) {
|
|
11725
|
+
console.log(RED10(` \u274C Local model error: ${e.message}`));
|
|
11726
|
+
console.log(GRAY10(" Retrying in 3 seconds..."));
|
|
11727
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
11728
|
+
}
|
|
11729
|
+
}
|
|
11730
|
+
clearSessionFile();
|
|
11731
|
+
rl.close();
|
|
11732
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
11733
|
+
console.log("");
|
|
11734
|
+
console.log(GRAY10(` Session complete. ${turns} turns processed.`));
|
|
11735
|
+
console.log("");
|
|
11736
|
+
}
|
|
11737
|
+
function registerUserBobCommand(program2) {
|
|
11738
|
+
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) => {
|
|
11739
|
+
const config = getConfig();
|
|
11740
|
+
const params = {
|
|
11741
|
+
target: parseInt(options.target, 10),
|
|
11742
|
+
grading: parseInt(options.grading, 10),
|
|
11743
|
+
stag: parseInt(options.stag, 10),
|
|
11744
|
+
div: parseInt(options.div, 10)
|
|
11745
|
+
};
|
|
11746
|
+
const usePlatform = !options.local && isAuthenticated();
|
|
11747
|
+
console.log("");
|
|
11748
|
+
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"));
|
|
11749
|
+
console.log(BORDER14(" \u2551") + PURPLE5(" \u{1F916} UserBob \u2014 Digital Twin Simulation"));
|
|
11750
|
+
console.log(BORDER14(" \u2551") + GRAY10(` Mode: ${usePlatform ? "Platform (Tier 3)" : "Local Ollama (Tier 1)"}`));
|
|
11751
|
+
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"));
|
|
11752
|
+
console.log("");
|
|
11753
|
+
const dna = buildDNAString();
|
|
11754
|
+
if (dna) {
|
|
11755
|
+
console.log(GREEN11(" \u2705 Behavioral DNA loaded."));
|
|
11756
|
+
} else {
|
|
11757
|
+
console.log(AMBER11(" \u26A0\uFE0F No behavioral profile found."));
|
|
11758
|
+
console.log(GRAY10(" UserBob performs significantly better with your DNA loaded."));
|
|
11759
|
+
console.log("");
|
|
11760
|
+
const rl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
11761
|
+
const answer = await new Promise((resolve4) => rl.question(AMBER11(" Run `bob profile --today` now? (y/n): "), resolve4));
|
|
11762
|
+
rl.close();
|
|
11763
|
+
if (answer.trim().toLowerCase() === "y") {
|
|
11764
|
+
console.log("");
|
|
11765
|
+
console.log(GRAY10(" Run `bob profile --today` in a separate terminal, then re-run `bob userbob`."));
|
|
11766
|
+
process.exit(0);
|
|
11767
|
+
} else {
|
|
11768
|
+
console.log("");
|
|
11769
|
+
console.log(RED10(" \u26A0\uFE0F Running in Generic Mode \u2014 no behavioral profile loaded."));
|
|
11770
|
+
console.log(RED10(" UserBob will respond using project context only."));
|
|
11771
|
+
console.log(RED10(" Responses won't reflect your personal communication style,"));
|
|
11772
|
+
console.log(RED10(" decision patterns, or engineering philosophy."));
|
|
11773
|
+
console.log(GRAY10(" Run `bob profile --today` anytime to unlock full personalization."));
|
|
11774
|
+
console.log("");
|
|
11775
|
+
}
|
|
11776
|
+
}
|
|
11777
|
+
let mission = missionArgs.length > 0 ? missionArgs.join(" ") : "";
|
|
11778
|
+
if (!mission && !options.resume) {
|
|
11779
|
+
const mrl = readline11.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
11780
|
+
mission = await new Promise((resolve4) => mrl.question(AMBER11(" What's the mission? > "), resolve4));
|
|
11781
|
+
mrl.close();
|
|
11782
|
+
if (!mission.trim()) {
|
|
11783
|
+
console.log(RED10(" \u274C Mission cannot be empty. Exiting."));
|
|
11784
|
+
process.exit(1);
|
|
11785
|
+
}
|
|
11786
|
+
mission = mission.trim();
|
|
11787
|
+
}
|
|
11788
|
+
console.log("");
|
|
11789
|
+
console.log(GRAY10(` Target: ${params.target}% \u2502 Grade: ${params.grading} \u2502 Stag: ${params.stag || "\u221E"} \u2502 Div: ${params.div || "\u221E"}`));
|
|
11790
|
+
console.log("");
|
|
11791
|
+
if (usePlatform) {
|
|
11792
|
+
const conversationId = getActiveConversationId(process.cwd()) || config.conversationId;
|
|
11793
|
+
if (!conversationId) {
|
|
11794
|
+
console.log(RED10(" \u274C No active conversation. Run `bob conversations join` first."));
|
|
11795
|
+
process.exit(1);
|
|
11796
|
+
}
|
|
11797
|
+
if (options.resume) {
|
|
11798
|
+
console.log(AMBER11(" \u{1F504} Resuming simulation (no new mission note)..."));
|
|
11799
|
+
await callHTTPFunction("userSimManagerService", {
|
|
11800
|
+
action: "resumeMission",
|
|
11801
|
+
conversationId,
|
|
11802
|
+
uid: config.uid,
|
|
11803
|
+
email: config.email
|
|
11804
|
+
});
|
|
11805
|
+
console.log(GREEN11(" \u2705 Simulation resumed. Entering watch mode..."));
|
|
11806
|
+
console.log("");
|
|
11807
|
+
await runPlatformSimulation(config, conversationId, mission || "Resumed session", params);
|
|
11808
|
+
} else {
|
|
11809
|
+
await runPlatformSimulation(config, conversationId, mission, params);
|
|
11810
|
+
}
|
|
11811
|
+
return;
|
|
11812
|
+
}
|
|
11813
|
+
if (!config.localEndpoint) {
|
|
11814
|
+
console.log(RED10(" \u274C No local model configured."));
|
|
11815
|
+
console.log(GRAY10(" Run: bob config set localEndpoint http://127.0.0.1:11434/api/chat"));
|
|
11816
|
+
process.exit(1);
|
|
11817
|
+
}
|
|
11818
|
+
await runLocalSimulation(config, dna, mission, params);
|
|
11819
|
+
});
|
|
11820
|
+
}
|
|
11821
|
+
|
|
11251
11822
|
// bin/bob.ts
|
|
11252
11823
|
var program = new Command();
|
|
11253
11824
|
program.name("bob").description("Bob's CLI \u2014 AI coding assistant and Forge orchestrator").version("0.8.0");
|
|
11254
11825
|
program.command("whoami").description("Show current authentication status and configuration").action(() => {
|
|
11255
11826
|
const config = getConfig();
|
|
11256
|
-
const projectName =
|
|
11827
|
+
const projectName = path23.basename(process.cwd());
|
|
11257
11828
|
const projectConvoId = getActiveConversationId(process.cwd()) || config.conversationId;
|
|
11258
11829
|
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(` ${
|
|
11830
|
+
console.log(chalk32.bold(" \u{1F916} Bob's CLI"));
|
|
11831
|
+
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"));
|
|
11832
|
+
console.log(` ${chalk32.cyan("Status:")} ${config.loggedIn ? chalk32.green("Logged in as " + config.email) : "Not logged in"}`);
|
|
11833
|
+
console.log(` ${chalk32.cyan("Tier:")} ${config.tier === "platform" ? "Platform (Tier 3)" : "Local-first (Tier 1)"}`);
|
|
11834
|
+
console.log(` ${chalk32.cyan("Provider:")} ${config.provider || "Not configured"}`);
|
|
11835
|
+
console.log(` ${chalk32.cyan("Mode:")} ${config.personalizationMode ? "Personalized" : config.consultantMode ? "Consultant" : "Standard"}`);
|
|
11836
|
+
console.log(` ${chalk32.cyan("IDRP:")} ${config.idrp ? "Enabled" : "Disabled"}`);
|
|
11837
|
+
console.log(` ${chalk32.cyan("Project:")} ${projectName} (${process.cwd()})`);
|
|
11838
|
+
console.log(` ${chalk32.cyan("Session:")} ${projectConvoId ? projectConvoId.slice(0, 20) + "..." : "None"}`);
|
|
11268
11839
|
console.log("");
|
|
11269
11840
|
if (!config.loggedIn) {
|
|
11270
|
-
console.log(
|
|
11841
|
+
console.log(chalk32.gray(" Run `bob login` to authenticate."));
|
|
11271
11842
|
console.log("");
|
|
11272
11843
|
}
|
|
11273
11844
|
});
|
|
@@ -11289,4 +11860,5 @@ registerProfileCommand(program);
|
|
|
11289
11860
|
registerBackupCommand(program);
|
|
11290
11861
|
registerAgentCommand(program);
|
|
11291
11862
|
registerAgentRunCommand(program);
|
|
11863
|
+
registerUserBobCommand(program);
|
|
11292
11864
|
program.parse();
|