@tuned-tensor/cli 0.8.0 → 0.8.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/index.js +241 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { spawn as spawn4 } from "child_process";
|
|
5
5
|
import { constants as osConstants2 } from "os";
|
|
6
6
|
import { Command } from "commander";
|
|
7
|
-
import
|
|
7
|
+
import chalk9 from "chalk";
|
|
8
8
|
|
|
9
9
|
// src/client.ts
|
|
10
10
|
import { readFileSync as readFileSync2, statSync } from "fs";
|
|
@@ -345,7 +345,7 @@ function createAgentClient(opts) {
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
// src/agent.ts
|
|
348
|
-
import
|
|
348
|
+
import chalk3 from "chalk";
|
|
349
349
|
|
|
350
350
|
// src/shell.ts
|
|
351
351
|
import chalk from "chalk";
|
|
@@ -353,6 +353,7 @@ import { stat as stat2 } from "fs/promises";
|
|
|
353
353
|
import { homedir as homedir3 } from "os";
|
|
354
354
|
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
355
355
|
import { createInterface } from "readline";
|
|
356
|
+
import { stripVTControlCharacters } from "util";
|
|
356
357
|
|
|
357
358
|
// src/command-catalog.ts
|
|
358
359
|
var CLOUD = ["cloud"];
|
|
@@ -950,7 +951,9 @@ var errorMark = () => chalk.red("\u2717");
|
|
|
950
951
|
var accent = chalk.hex("#8B5CF6");
|
|
951
952
|
var ANSI_BOLD = "\x1B[1m";
|
|
952
953
|
var ANSI_BOLD_OFF = "\x1B[22m";
|
|
954
|
+
var ANSI_CLEAR_LINE = "\x1B[2K";
|
|
953
955
|
var ANSI_CLEAR_TO_END = "\x1B[K";
|
|
956
|
+
var ANSI_CURSOR_UP = "\x1B[1A";
|
|
954
957
|
var ANSI_RESET = "\x1B[0m";
|
|
955
958
|
function inputColorCodes() {
|
|
956
959
|
if (chalk.level === 0) return null;
|
|
@@ -1055,9 +1058,17 @@ function renderShellBanner(snapshot) {
|
|
|
1055
1058
|
`;
|
|
1056
1059
|
}
|
|
1057
1060
|
function renderShellPrompt() {
|
|
1061
|
+
return `${accent.bold("\u203A")} `;
|
|
1062
|
+
}
|
|
1063
|
+
function renderSubmittedShellInput(input, columns) {
|
|
1058
1064
|
const colors = inputColorCodes();
|
|
1059
|
-
if (!colors) return "
|
|
1065
|
+
if (!colors) return "";
|
|
1066
|
+
const safeInput = stripVTControlCharacters(input).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "");
|
|
1067
|
+
if (columns && Array.from(`\u203A ${safeInput}`).length >= columns) return "";
|
|
1060
1068
|
return [
|
|
1069
|
+
ANSI_CURSOR_UP,
|
|
1070
|
+
"\r",
|
|
1071
|
+
ANSI_CLEAR_LINE,
|
|
1061
1072
|
colors.background,
|
|
1062
1073
|
colors.accent,
|
|
1063
1074
|
ANSI_BOLD,
|
|
@@ -1065,11 +1076,14 @@ function renderShellPrompt() {
|
|
|
1065
1076
|
ANSI_BOLD_OFF,
|
|
1066
1077
|
colors.text,
|
|
1067
1078
|
" ",
|
|
1068
|
-
|
|
1079
|
+
safeInput,
|
|
1080
|
+
ANSI_CLEAR_TO_END,
|
|
1081
|
+
ANSI_RESET,
|
|
1082
|
+
"\r\n"
|
|
1069
1083
|
].join("");
|
|
1070
1084
|
}
|
|
1071
1085
|
function resetShellPromptStyle() {
|
|
1072
|
-
return
|
|
1086
|
+
return "";
|
|
1073
1087
|
}
|
|
1074
1088
|
var TunedTensorShellSession = class _TunedTensorShellSession {
|
|
1075
1089
|
constructor(runner, io, agent, env, contextProvider, version, initialContext) {
|
|
@@ -1360,7 +1374,10 @@ async function startInteractiveShell(options) {
|
|
|
1360
1374
|
readline.prompt();
|
|
1361
1375
|
try {
|
|
1362
1376
|
for await (const line of readline) {
|
|
1363
|
-
output.write(
|
|
1377
|
+
output.write(renderSubmittedShellInput(
|
|
1378
|
+
line,
|
|
1379
|
+
output.columns
|
|
1380
|
+
));
|
|
1364
1381
|
const action = await session.handleLine(line);
|
|
1365
1382
|
if (action === "exit") {
|
|
1366
1383
|
readline.close();
|
|
@@ -1384,10 +1401,127 @@ function shouldStartInteractiveShell(options) {
|
|
|
1384
1401
|
return options.args.length === 0 && options.stdinIsTTY === true && options.stdoutIsTTY === true && !ciEnabled(env.CI) && env.TERM !== "dumb";
|
|
1385
1402
|
}
|
|
1386
1403
|
|
|
1387
|
-
// src/
|
|
1404
|
+
// src/terminal-markdown.ts
|
|
1405
|
+
import chalk2 from "chalk";
|
|
1406
|
+
import { stripVTControlCharacters as stripVTControlCharacters2 } from "util";
|
|
1388
1407
|
var accent2 = chalk2.hex("#8B5CF6");
|
|
1389
|
-
|
|
1390
|
-
|
|
1408
|
+
function sanitizeTerminalText(text2) {
|
|
1409
|
+
return stripVTControlCharacters2(text2).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "");
|
|
1410
|
+
}
|
|
1411
|
+
function closingDelimiter(text2, delimiter, from) {
|
|
1412
|
+
return text2.indexOf(delimiter, from + delimiter.length);
|
|
1413
|
+
}
|
|
1414
|
+
function renderInlineMarkdown(text2) {
|
|
1415
|
+
let rendered = "";
|
|
1416
|
+
let index = 0;
|
|
1417
|
+
while (index < text2.length) {
|
|
1418
|
+
if (text2[index] === "\\" && index + 1 < text2.length) {
|
|
1419
|
+
rendered += text2[index + 1];
|
|
1420
|
+
index += 2;
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
if (text2[index] === "[") {
|
|
1424
|
+
const link = text2.slice(index).match(/^\[([^\]]+)]\(([^)]+)\)/);
|
|
1425
|
+
if (link) {
|
|
1426
|
+
rendered += `${chalk2.underline(renderInlineMarkdown(link[1]))}${chalk2.dim(` (${link[2]})`)}`;
|
|
1427
|
+
index += link[0].length;
|
|
1428
|
+
continue;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
const strong = text2.startsWith("**", index) ? "**" : text2.startsWith("__", index) ? "__" : null;
|
|
1432
|
+
if (strong) {
|
|
1433
|
+
const close = closingDelimiter(text2, strong, index);
|
|
1434
|
+
if (close > index + strong.length) {
|
|
1435
|
+
rendered += chalk2.bold(
|
|
1436
|
+
renderInlineMarkdown(text2.slice(index + strong.length, close))
|
|
1437
|
+
);
|
|
1438
|
+
index = close + strong.length;
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
if (text2[index] === "`") {
|
|
1443
|
+
const close = closingDelimiter(text2, "`", index);
|
|
1444
|
+
if (close > index + 1) {
|
|
1445
|
+
rendered += chalk2.cyan(text2.slice(index + 1, close));
|
|
1446
|
+
index = close + 1;
|
|
1447
|
+
continue;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
const emphasis = text2[index] === "*" || text2[index] === "_" ? text2[index] : null;
|
|
1451
|
+
if (emphasis) {
|
|
1452
|
+
const close = closingDelimiter(text2, emphasis, index);
|
|
1453
|
+
if (close > index + 1) {
|
|
1454
|
+
rendered += chalk2.italic(
|
|
1455
|
+
renderInlineMarkdown(text2.slice(index + 1, close))
|
|
1456
|
+
);
|
|
1457
|
+
index = close + 1;
|
|
1458
|
+
continue;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
rendered += text2[index];
|
|
1462
|
+
index += 1;
|
|
1463
|
+
}
|
|
1464
|
+
return rendered;
|
|
1465
|
+
}
|
|
1466
|
+
function renderMarkdownLine(line, inCodeBlock) {
|
|
1467
|
+
if (inCodeBlock) return chalk2.cyan(` ${line}`);
|
|
1468
|
+
const heading = line.match(/^\s{0,3}#{1,6}\s+(.+)$/);
|
|
1469
|
+
if (heading) return chalk2.bold(renderInlineMarkdown(heading[1]));
|
|
1470
|
+
const bullet = line.match(/^(\s*)[-+*]\s+(.+)$/);
|
|
1471
|
+
if (bullet) {
|
|
1472
|
+
return `${bullet[1]}${accent2("\u2022")} ${renderInlineMarkdown(bullet[2])}`;
|
|
1473
|
+
}
|
|
1474
|
+
const numbered = line.match(/^(\s*)(\d+)[.)]\s+(.+)$/);
|
|
1475
|
+
if (numbered) {
|
|
1476
|
+
return `${numbered[1]}${accent2(`${numbered[2]}.`)} ${renderInlineMarkdown(numbered[3])}`;
|
|
1477
|
+
}
|
|
1478
|
+
const quote = line.match(/^\s*>\s?(.*)$/);
|
|
1479
|
+
if (quote) return `${chalk2.dim("\u2502")} ${chalk2.italic(renderInlineMarkdown(quote[1]))}`;
|
|
1480
|
+
if (/^\s{0,3}([-*_])(?:\s*\1){2,}\s*$/.test(line)) {
|
|
1481
|
+
return chalk2.dim("\u2500".repeat(32));
|
|
1482
|
+
}
|
|
1483
|
+
return renderInlineMarkdown(line);
|
|
1484
|
+
}
|
|
1485
|
+
var StreamingTerminalMarkdown = class {
|
|
1486
|
+
pending = "";
|
|
1487
|
+
inCodeBlock = false;
|
|
1488
|
+
push(delta) {
|
|
1489
|
+
this.pending += delta;
|
|
1490
|
+
let rendered = "";
|
|
1491
|
+
let newline = this.pending.indexOf("\n");
|
|
1492
|
+
while (newline !== -1) {
|
|
1493
|
+
const line = this.pending.slice(0, newline).replace(/\r$/, "");
|
|
1494
|
+
this.pending = this.pending.slice(newline + 1);
|
|
1495
|
+
rendered += `${this.renderLine(line)}
|
|
1496
|
+
`;
|
|
1497
|
+
newline = this.pending.indexOf("\n");
|
|
1498
|
+
}
|
|
1499
|
+
return rendered;
|
|
1500
|
+
}
|
|
1501
|
+
flush() {
|
|
1502
|
+
if (!this.pending) return "";
|
|
1503
|
+
const line = this.pending.replace(/\r$/, "");
|
|
1504
|
+
this.pending = "";
|
|
1505
|
+
return this.renderLine(line);
|
|
1506
|
+
}
|
|
1507
|
+
reset() {
|
|
1508
|
+
this.pending = "";
|
|
1509
|
+
this.inCodeBlock = false;
|
|
1510
|
+
}
|
|
1511
|
+
renderLine(line) {
|
|
1512
|
+
const safeLine = sanitizeTerminalText(line);
|
|
1513
|
+
if (/^\s*```/.test(safeLine)) {
|
|
1514
|
+
this.inCodeBlock = !this.inCodeBlock;
|
|
1515
|
+
return "";
|
|
1516
|
+
}
|
|
1517
|
+
return renderMarkdownLine(safeLine, this.inCodeBlock);
|
|
1518
|
+
}
|
|
1519
|
+
};
|
|
1520
|
+
|
|
1521
|
+
// src/agent.ts
|
|
1522
|
+
var accent3 = chalk3.hex("#8B5CF6");
|
|
1523
|
+
var successMark2 = () => chalk3.green("\u2713");
|
|
1524
|
+
var errorMark2 = () => chalk3.red("\u2717");
|
|
1391
1525
|
function isRecord(value) {
|
|
1392
1526
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1393
1527
|
}
|
|
@@ -1396,25 +1530,25 @@ function stringValue2(value) {
|
|
|
1396
1530
|
}
|
|
1397
1531
|
function helpText2() {
|
|
1398
1532
|
return [
|
|
1399
|
-
|
|
1533
|
+
accent3.bold("Agent commands"),
|
|
1400
1534
|
"",
|
|
1401
|
-
` ${
|
|
1402
|
-
` ${
|
|
1403
|
-
` ${
|
|
1404
|
-
` ${
|
|
1405
|
-
` ${
|
|
1406
|
-
` ${
|
|
1407
|
-
` ${
|
|
1408
|
-
` ${
|
|
1535
|
+
` ${accent3("/new".padEnd(22))} Start a new conversation.`,
|
|
1536
|
+
` ${accent3("/threads".padEnd(22))} List recent conversations.`,
|
|
1537
|
+
` ${accent3("/resume <id>".padEnd(22))} Resume a conversation by ID or prefix.`,
|
|
1538
|
+
` ${accent3("/approve [id]".padEnd(22))} Approve a proposed action.`,
|
|
1539
|
+
` ${accent3("/reject [id]".padEnd(22))} Reject a proposed action.`,
|
|
1540
|
+
` ${accent3("/status".padEnd(22))} Show the active conversation.`,
|
|
1541
|
+
` ${accent3("/clear".padEnd(22))} Clear the terminal.`,
|
|
1542
|
+
` ${accent3("/exit".padEnd(22))} Exit the agent.`,
|
|
1409
1543
|
"",
|
|
1410
|
-
|
|
1544
|
+
chalk3.dim(
|
|
1411
1545
|
"Everything else is sent to the Tuned Tensor agent; known TT commands still run directly in the shell."
|
|
1412
1546
|
),
|
|
1413
1547
|
""
|
|
1414
1548
|
].join("\n");
|
|
1415
1549
|
}
|
|
1416
1550
|
function formatThread(thread, activeId) {
|
|
1417
|
-
const active = thread.id === activeId ?
|
|
1551
|
+
const active = thread.id === activeId ? accent3("\u25CF") : chalk3.dim("\u25CB");
|
|
1418
1552
|
const time = thread.last_message_at ?? thread.updated_at ?? thread.created_at;
|
|
1419
1553
|
const date = new Date(time);
|
|
1420
1554
|
const dateLabel = Number.isNaN(date.getTime()) ? "" : date.toLocaleString([], {
|
|
@@ -1423,7 +1557,7 @@ function formatThread(thread, activeId) {
|
|
|
1423
1557
|
hour: "2-digit",
|
|
1424
1558
|
minute: "2-digit"
|
|
1425
1559
|
});
|
|
1426
|
-
return `${active} ${
|
|
1560
|
+
return `${active} ${chalk3.dim(thread.id.slice(0, 8))} ${thread.title} ${chalk3.dim(dateLabel)}`;
|
|
1427
1561
|
}
|
|
1428
1562
|
function actionFromPayload(payload) {
|
|
1429
1563
|
const value = isRecord(payload.action) ? payload.action : isRecord(payload.approval) ? payload.approval : payload;
|
|
@@ -1463,6 +1597,7 @@ var TunedTensorAgentSession = class {
|
|
|
1463
1597
|
responseStarted = false;
|
|
1464
1598
|
reasoningActive = false;
|
|
1465
1599
|
lineOpen = false;
|
|
1600
|
+
responseMarkdown = new StreamingTerminalMarkdown();
|
|
1466
1601
|
get busy() {
|
|
1467
1602
|
return this.activeRequest !== null;
|
|
1468
1603
|
}
|
|
@@ -1482,14 +1617,27 @@ var TunedTensorAgentSession = class {
|
|
|
1482
1617
|
this.lineOpen = false;
|
|
1483
1618
|
this.reasoningActive = false;
|
|
1484
1619
|
}
|
|
1620
|
+
writeRenderedResponse(rendered) {
|
|
1621
|
+
if (!rendered) return;
|
|
1622
|
+
if (!this.responseStarted) {
|
|
1623
|
+
this.options.io.write(`
|
|
1624
|
+
${accent3.bold("tt")} `);
|
|
1625
|
+
this.responseStarted = true;
|
|
1626
|
+
}
|
|
1627
|
+
this.options.io.write(rendered);
|
|
1628
|
+
this.lineOpen = !rendered.endsWith("\n");
|
|
1629
|
+
}
|
|
1630
|
+
flushResponse() {
|
|
1631
|
+
this.writeRenderedResponse(this.responseMarkdown.flush());
|
|
1632
|
+
}
|
|
1485
1633
|
renderAction(action) {
|
|
1486
1634
|
this.endOpenLine();
|
|
1487
1635
|
this.options.io.write(
|
|
1488
1636
|
`
|
|
1489
|
-
${
|
|
1637
|
+
${chalk3.yellow.bold("Approval required")} ${chalk3.dim(action.id.slice(0, 8))}
|
|
1490
1638
|
`
|
|
1491
1639
|
);
|
|
1492
|
-
this.options.io.write(`${
|
|
1640
|
+
this.options.io.write(`${chalk3.bold(action.title)} ${chalk3.yellow(`[${action.risk} risk]`)}
|
|
1493
1641
|
`);
|
|
1494
1642
|
if (action.summary) this.options.io.write(`${action.summary}
|
|
1495
1643
|
`);
|
|
@@ -1500,12 +1648,12 @@ ${chalk2.yellow.bold("Approval required")} ${chalk2.dim(action.id.slice(0, 8))}
|
|
|
1500
1648
|
arguments: action.arguments ?? null,
|
|
1501
1649
|
preview: action.preview ?? null
|
|
1502
1650
|
};
|
|
1503
|
-
this.options.io.write(`${
|
|
1651
|
+
this.options.io.write(`${chalk3.bold("Proposed action")}
|
|
1504
1652
|
`);
|
|
1505
1653
|
this.options.io.write(`${formatJson(technical)}
|
|
1506
1654
|
`);
|
|
1507
1655
|
this.options.io.write(
|
|
1508
|
-
|
|
1656
|
+
chalk3.dim("Use /approve or /reject. The action will not run without approval.") + "\n"
|
|
1509
1657
|
);
|
|
1510
1658
|
}
|
|
1511
1659
|
renderEvent(event) {
|
|
@@ -1513,49 +1661,46 @@ ${chalk2.yellow.bold("Approval required")} ${chalk2.dim(action.id.slice(0, 8))}
|
|
|
1513
1661
|
if (event.type === "text_delta") {
|
|
1514
1662
|
const delta = stringValue2(payload.delta) ?? stringValue2(payload.text) ?? stringValue2(payload.content);
|
|
1515
1663
|
if (!delta) return;
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
if (!this.responseStarted) {
|
|
1519
|
-
this.options.io.write(`
|
|
1520
|
-
${accent2.bold("tt")} `);
|
|
1521
|
-
this.responseStarted = true;
|
|
1522
|
-
this.lineOpen = true;
|
|
1523
|
-
} else if (followsReasoning) {
|
|
1664
|
+
if (this.reasoningActive) {
|
|
1665
|
+
this.endOpenLine();
|
|
1524
1666
|
this.options.io.write("\n");
|
|
1525
1667
|
}
|
|
1526
|
-
this.
|
|
1527
|
-
this.lineOpen = !delta.endsWith("\n");
|
|
1668
|
+
this.writeRenderedResponse(this.responseMarkdown.push(delta));
|
|
1528
1669
|
return;
|
|
1529
1670
|
}
|
|
1530
1671
|
if (event.type === "reasoning_delta") {
|
|
1531
1672
|
const delta = stringValue2(payload.delta) ?? stringValue2(payload.text) ?? stringValue2(payload.content);
|
|
1532
1673
|
if (!delta) return;
|
|
1533
1674
|
if (!this.reasoningActive) {
|
|
1675
|
+
this.flushResponse();
|
|
1534
1676
|
this.endOpenLine();
|
|
1535
1677
|
this.options.io.write("\n");
|
|
1536
1678
|
this.reasoningActive = true;
|
|
1537
1679
|
}
|
|
1538
|
-
this.options.io.write(
|
|
1680
|
+
this.options.io.write(chalk3.dim.italic(delta));
|
|
1539
1681
|
this.lineOpen = !delta.endsWith("\n");
|
|
1540
1682
|
return;
|
|
1541
1683
|
}
|
|
1542
1684
|
if (event.type === "tool_call") {
|
|
1685
|
+
this.flushResponse();
|
|
1543
1686
|
this.endOpenLine();
|
|
1544
1687
|
const name = stringValue2(payload.name) ?? stringValue2(isRecord(payload.tool_call) ? payload.tool_call.name : null) ?? "tool";
|
|
1545
|
-
this.options.io.write(
|
|
1688
|
+
this.options.io.write(chalk3.dim(` \u25CB ${name}
|
|
1546
1689
|
`));
|
|
1547
1690
|
return;
|
|
1548
1691
|
}
|
|
1549
1692
|
if (event.type === "tool_result") {
|
|
1693
|
+
this.flushResponse();
|
|
1550
1694
|
this.endOpenLine();
|
|
1551
1695
|
const failed = payload.status === "error" || Boolean(payload.error);
|
|
1552
1696
|
this.options.io.write(
|
|
1553
|
-
|
|
1697
|
+
chalk3.dim(` ${failed ? chalk3.red("\u2717") : chalk3.green("\u2713")} Tool ${failed ? "failed" : "complete"}
|
|
1554
1698
|
`)
|
|
1555
1699
|
);
|
|
1556
1700
|
return;
|
|
1557
1701
|
}
|
|
1558
1702
|
if (event.type === "approval_required") {
|
|
1703
|
+
this.flushResponse();
|
|
1559
1704
|
const action = actionFromPayload(payload);
|
|
1560
1705
|
if (!action) return;
|
|
1561
1706
|
this.pendingActions.set(action.id, action);
|
|
@@ -1563,11 +1708,13 @@ ${accent2.bold("tt")} `);
|
|
|
1563
1708
|
return;
|
|
1564
1709
|
}
|
|
1565
1710
|
if (event.type === "action_started") {
|
|
1711
|
+
this.flushResponse();
|
|
1566
1712
|
this.endOpenLine();
|
|
1567
|
-
this.options.io.write(
|
|
1713
|
+
this.options.io.write(chalk3.dim(" \u25CB Running approved action\u2026\n"));
|
|
1568
1714
|
return;
|
|
1569
1715
|
}
|
|
1570
1716
|
if (event.type === "action_result") {
|
|
1717
|
+
this.flushResponse();
|
|
1571
1718
|
this.endOpenLine();
|
|
1572
1719
|
const failed = payload.status === "failed" || Boolean(payload.error);
|
|
1573
1720
|
this.options.io.write(
|
|
@@ -1577,6 +1724,7 @@ ${accent2.bold("tt")} `);
|
|
|
1577
1724
|
return;
|
|
1578
1725
|
}
|
|
1579
1726
|
if (event.type === "error") {
|
|
1727
|
+
this.flushResponse();
|
|
1580
1728
|
this.endOpenLine();
|
|
1581
1729
|
const message = stringValue2(payload.message) ?? stringValue2(payload.error) ?? "The agent could not complete this request.";
|
|
1582
1730
|
this.options.io.writeError(`${errorMark2()} ${message}
|
|
@@ -1598,17 +1746,20 @@ ${accent2.bold("tt")} `);
|
|
|
1598
1746
|
this.responseStarted = false;
|
|
1599
1747
|
this.reasoningActive = false;
|
|
1600
1748
|
this.lineOpen = false;
|
|
1749
|
+
this.responseMarkdown.reset();
|
|
1601
1750
|
try {
|
|
1602
1751
|
const result = await operation(controller.signal);
|
|
1752
|
+
this.flushResponse();
|
|
1603
1753
|
this.endOpenLine();
|
|
1604
1754
|
for (const action of result.actions) {
|
|
1605
1755
|
this.pendingActions.set(action.id, action);
|
|
1606
1756
|
}
|
|
1607
1757
|
return result;
|
|
1608
1758
|
} catch (error) {
|
|
1759
|
+
this.flushResponse();
|
|
1609
1760
|
this.endOpenLine();
|
|
1610
1761
|
if (controller.signal.aborted) {
|
|
1611
|
-
this.options.io.write(
|
|
1762
|
+
this.options.io.write(chalk3.dim("Response stopped.\n"));
|
|
1612
1763
|
return null;
|
|
1613
1764
|
}
|
|
1614
1765
|
throw error;
|
|
@@ -1617,6 +1768,7 @@ ${accent2.bold("tt")} `);
|
|
|
1617
1768
|
this.responseStarted = false;
|
|
1618
1769
|
this.reasoningActive = false;
|
|
1619
1770
|
this.lineOpen = false;
|
|
1771
|
+
this.responseMarkdown.reset();
|
|
1620
1772
|
}
|
|
1621
1773
|
}
|
|
1622
1774
|
async send(prompt) {
|
|
@@ -1694,7 +1846,7 @@ ${accent2.bold("tt")} `);
|
|
|
1694
1846
|
if (args.length > 0) throw new Error("/threads does not accept arguments.");
|
|
1695
1847
|
const threads = await this.options.client.listThreads();
|
|
1696
1848
|
if (threads.length === 0) {
|
|
1697
|
-
this.options.io.write(
|
|
1849
|
+
this.options.io.write(chalk3.dim("No conversations yet.\n"));
|
|
1698
1850
|
return "continue";
|
|
1699
1851
|
}
|
|
1700
1852
|
this.options.io.write(
|
|
@@ -1732,10 +1884,10 @@ ${accent2.bold("tt")} `);
|
|
|
1732
1884
|
if (args.length > 0) throw new Error("/status does not accept arguments.");
|
|
1733
1885
|
this.options.io.write(
|
|
1734
1886
|
this.thread ? `${formatThread(this.thread, this.thread.id)}
|
|
1735
|
-
` :
|
|
1887
|
+
` : chalk3.dim("New conversation; send a message to create it.\n")
|
|
1736
1888
|
);
|
|
1737
1889
|
this.options.io.write(
|
|
1738
|
-
|
|
1890
|
+
chalk3.dim(`${this.pendingActions.size} pending approval(s).
|
|
1739
1891
|
`)
|
|
1740
1892
|
);
|
|
1741
1893
|
return "continue";
|
|
@@ -1920,7 +2072,7 @@ function unknownProjectSpecKeys(raw) {
|
|
|
1920
2072
|
}
|
|
1921
2073
|
|
|
1922
2074
|
// src/output.ts
|
|
1923
|
-
import
|
|
2075
|
+
import chalk4 from "chalk";
|
|
1924
2076
|
import Table from "cli-table3";
|
|
1925
2077
|
var jsonMode = false;
|
|
1926
2078
|
function setJsonMode(enabled) {
|
|
@@ -1934,7 +2086,7 @@ function printJson(data) {
|
|
|
1934
2086
|
}
|
|
1935
2087
|
function printTable(headers, rows2, meta) {
|
|
1936
2088
|
const table = new Table({
|
|
1937
|
-
head: headers.map((h) =>
|
|
2089
|
+
head: headers.map((h) => chalk4.bold.cyan(h)),
|
|
1938
2090
|
style: { head: [], border: [] }
|
|
1939
2091
|
});
|
|
1940
2092
|
for (const row of rows2) {
|
|
@@ -1944,7 +2096,7 @@ function printTable(headers, rows2, meta) {
|
|
|
1944
2096
|
if (meta) {
|
|
1945
2097
|
const totalPages = Math.ceil(meta.total / meta.per_page);
|
|
1946
2098
|
console.log(
|
|
1947
|
-
|
|
2099
|
+
chalk4.dim(
|
|
1948
2100
|
`
|
|
1949
2101
|
Page ${meta.page}/${totalPages} (${meta.total} total)`
|
|
1950
2102
|
)
|
|
@@ -1955,17 +2107,17 @@ function printDetail(fields) {
|
|
|
1955
2107
|
const maxLabel = Math.max(...fields.map(([l]) => l.length));
|
|
1956
2108
|
for (const [label, value] of fields) {
|
|
1957
2109
|
const paddedLabel = label.padEnd(maxLabel);
|
|
1958
|
-
console.log(`${
|
|
2110
|
+
console.log(`${chalk4.bold.cyan(paddedLabel)} ${value ?? chalk4.dim("\u2014")}`);
|
|
1959
2111
|
}
|
|
1960
2112
|
}
|
|
1961
2113
|
function printSuccess(message) {
|
|
1962
|
-
console.log(
|
|
2114
|
+
console.log(chalk4.green("\u2713") + " " + message);
|
|
1963
2115
|
}
|
|
1964
2116
|
function printWarning(message) {
|
|
1965
|
-
console.log(
|
|
2117
|
+
console.log(chalk4.yellow("!") + " " + message);
|
|
1966
2118
|
}
|
|
1967
2119
|
function printError(message) {
|
|
1968
|
-
console.error(
|
|
2120
|
+
console.error(chalk4.red("\u2717") + " " + message);
|
|
1969
2121
|
}
|
|
1970
2122
|
function reportError(err) {
|
|
1971
2123
|
const isApi = err instanceof ApiError;
|
|
@@ -1990,19 +2142,19 @@ function formatDate(iso) {
|
|
|
1990
2142
|
}
|
|
1991
2143
|
function formatStatus(status2) {
|
|
1992
2144
|
const map = {
|
|
1993
|
-
completed:
|
|
1994
|
-
running:
|
|
1995
|
-
training:
|
|
1996
|
-
evaluating:
|
|
1997
|
-
preparing:
|
|
1998
|
-
pending:
|
|
1999
|
-
uploading:
|
|
2000
|
-
failed:
|
|
2001
|
-
cancelled:
|
|
2002
|
-
validated:
|
|
2003
|
-
invalid:
|
|
2145
|
+
completed: chalk4.green,
|
|
2146
|
+
running: chalk4.blue,
|
|
2147
|
+
training: chalk4.blue,
|
|
2148
|
+
evaluating: chalk4.blue,
|
|
2149
|
+
preparing: chalk4.yellow,
|
|
2150
|
+
pending: chalk4.yellow,
|
|
2151
|
+
uploading: chalk4.yellow,
|
|
2152
|
+
failed: chalk4.red,
|
|
2153
|
+
cancelled: chalk4.dim,
|
|
2154
|
+
validated: chalk4.green,
|
|
2155
|
+
invalid: chalk4.red
|
|
2004
2156
|
};
|
|
2005
|
-
const colorFn = map[status2] ||
|
|
2157
|
+
const colorFn = map[status2] || chalk4.white;
|
|
2006
2158
|
return colorFn(status2);
|
|
2007
2159
|
}
|
|
2008
2160
|
function truncate(str, max) {
|
|
@@ -2845,7 +2997,7 @@ async function executeLocalCommand(args, options = {}) {
|
|
|
2845
2997
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
2846
2998
|
import { stdin, stdout } from "process";
|
|
2847
2999
|
import { Writable } from "stream";
|
|
2848
|
-
import
|
|
3000
|
+
import chalk5 from "chalk";
|
|
2849
3001
|
async function promptForApiKey(input = stdin, output = stdout) {
|
|
2850
3002
|
if (input.isTTY !== true || output.isTTY !== true) {
|
|
2851
3003
|
throw new Error(
|
|
@@ -2887,9 +3039,9 @@ function registerAuthCommands(parent) {
|
|
|
2887
3039
|
const settingsUrl = `${DEFAULT_BASE_URL}/dashboard/settings`;
|
|
2888
3040
|
console.log();
|
|
2889
3041
|
console.log(
|
|
2890
|
-
` To get your API key, go to ${
|
|
3042
|
+
` To get your API key, go to ${chalk5.bold("Settings \u2192 API Keys")} in the Tuned Tensor dashboard:`
|
|
2891
3043
|
);
|
|
2892
|
-
console.log(` ${
|
|
3044
|
+
console.log(` ${chalk5.cyan.underline(settingsUrl)}`);
|
|
2893
3045
|
console.log();
|
|
2894
3046
|
apiKey = await promptForApiKey();
|
|
2895
3047
|
}
|
|
@@ -6353,7 +6505,7 @@ function registerModelsCommands(parent) {
|
|
|
6353
6505
|
}
|
|
6354
6506
|
|
|
6355
6507
|
// src/commands/balance.ts
|
|
6356
|
-
import
|
|
6508
|
+
import chalk6 from "chalk";
|
|
6357
6509
|
var KIND_LABELS = {
|
|
6358
6510
|
signup_bonus: "Signup bonus",
|
|
6359
6511
|
topup: "Top-up",
|
|
@@ -6368,8 +6520,8 @@ function formatCents3(cents) {
|
|
|
6368
6520
|
return `${sign}$${(abs / 100).toFixed(2)}`;
|
|
6369
6521
|
}
|
|
6370
6522
|
function formatSigned(cents) {
|
|
6371
|
-
if (cents > 0) return
|
|
6372
|
-
if (cents < 0) return
|
|
6523
|
+
if (cents > 0) return chalk6.green(`+${formatCents3(cents)}`);
|
|
6524
|
+
if (cents < 0) return chalk6.red(formatCents3(cents));
|
|
6373
6525
|
return formatCents3(cents);
|
|
6374
6526
|
}
|
|
6375
6527
|
function registerBalanceCommands(parent) {
|
|
@@ -6384,7 +6536,7 @@ function registerBalanceCommands(parent) {
|
|
|
6384
6536
|
return printJson({ balance, transactions });
|
|
6385
6537
|
}
|
|
6386
6538
|
const lowBalance = balance.balance_cents < 100;
|
|
6387
|
-
const balanceLine = lowBalance ?
|
|
6539
|
+
const balanceLine = lowBalance ? chalk6.red(formatCents3(balance.balance_cents)) + chalk6.dim(" (low)") : chalk6.bold.green(formatCents3(balance.balance_cents));
|
|
6388
6540
|
printDetail([
|
|
6389
6541
|
["Credits", balanceLine],
|
|
6390
6542
|
[
|
|
@@ -6399,7 +6551,7 @@ function registerBalanceCommands(parent) {
|
|
|
6399
6551
|
]);
|
|
6400
6552
|
if (transactions && transactions.length > 0) {
|
|
6401
6553
|
console.log(`
|
|
6402
|
-
${
|
|
6554
|
+
${chalk6.bold("Recent transactions")}`);
|
|
6403
6555
|
printTable(
|
|
6404
6556
|
["Date", "Type", "Amount", "Balance", "Reference"],
|
|
6405
6557
|
transactions.map((row) => [
|
|
@@ -6407,19 +6559,19 @@ ${chalk5.bold("Recent transactions")}`);
|
|
|
6407
6559
|
KIND_LABELS[row.kind] ?? row.kind,
|
|
6408
6560
|
formatSigned(row.amount_cents),
|
|
6409
6561
|
formatCents3(row.balance_after_cents),
|
|
6410
|
-
row.reference_id ? shortId(row.reference_id) :
|
|
6562
|
+
row.reference_id ? shortId(row.reference_id) : chalk6.dim("\u2014")
|
|
6411
6563
|
])
|
|
6412
6564
|
);
|
|
6413
6565
|
} else {
|
|
6414
6566
|
console.log(
|
|
6415
6567
|
`
|
|
6416
|
-
${
|
|
6568
|
+
${chalk6.dim("No transactions yet \u2014 run `tt topup` to add credits.")}`
|
|
6417
6569
|
);
|
|
6418
6570
|
}
|
|
6419
6571
|
if (lowBalance) {
|
|
6420
6572
|
console.log(
|
|
6421
6573
|
`
|
|
6422
|
-
${formatStatus("preparing")} ${
|
|
6574
|
+
${formatStatus("preparing")} ${chalk6.yellow(
|
|
6423
6575
|
"Run `tt topup` to add more credits before starting a run."
|
|
6424
6576
|
)}`
|
|
6425
6577
|
);
|
|
@@ -6428,7 +6580,7 @@ ${formatStatus("preparing")} ${chalk5.yellow(
|
|
|
6428
6580
|
}
|
|
6429
6581
|
|
|
6430
6582
|
// src/commands/topup.ts
|
|
6431
|
-
import
|
|
6583
|
+
import chalk7 from "chalk";
|
|
6432
6584
|
import open from "open";
|
|
6433
6585
|
var PRESETS_USD = [10, 25, 50, 100];
|
|
6434
6586
|
var MIN_USD = 5;
|
|
@@ -6467,9 +6619,9 @@ function registerTopupCommands(parent) {
|
|
|
6467
6619
|
"amount is required in --json mode (use --amount <usd>)"
|
|
6468
6620
|
);
|
|
6469
6621
|
}
|
|
6470
|
-
console.log(
|
|
6622
|
+
console.log(chalk7.bold("Add credits via Stripe Checkout"));
|
|
6471
6623
|
console.log(
|
|
6472
|
-
|
|
6624
|
+
chalk7.dim(
|
|
6473
6625
|
`Quick picks: ${PRESETS_USD.map((n) => `$${n}`).join(", ")}`
|
|
6474
6626
|
)
|
|
6475
6627
|
);
|
|
@@ -6496,8 +6648,8 @@ function registerTopupCommands(parent) {
|
|
|
6496
6648
|
}
|
|
6497
6649
|
const url = data.checkout_url;
|
|
6498
6650
|
console.log(
|
|
6499
|
-
`${
|
|
6500
|
-
` +
|
|
6651
|
+
`${chalk7.bold("Checkout URL:")} ${chalk7.cyan(url)}
|
|
6652
|
+
` + chalk7.dim("Complete the payment to credit your account.")
|
|
6501
6653
|
);
|
|
6502
6654
|
if (options.open !== false) {
|
|
6503
6655
|
try {
|
|
@@ -6505,7 +6657,7 @@ function registerTopupCommands(parent) {
|
|
|
6505
6657
|
printSuccess("Opened Stripe Checkout in your browser.");
|
|
6506
6658
|
} catch {
|
|
6507
6659
|
console.log(
|
|
6508
|
-
|
|
6660
|
+
chalk7.yellow(
|
|
6509
6661
|
"Could not open browser automatically \u2014 copy the URL above."
|
|
6510
6662
|
)
|
|
6511
6663
|
);
|
|
@@ -6515,7 +6667,7 @@ function registerTopupCommands(parent) {
|
|
|
6515
6667
|
}
|
|
6516
6668
|
|
|
6517
6669
|
// src/commands/eval.ts
|
|
6518
|
-
import
|
|
6670
|
+
import chalk8 from "chalk";
|
|
6519
6671
|
|
|
6520
6672
|
// src/eval/rules.ts
|
|
6521
6673
|
function validateSpec(spec) {
|
|
@@ -6680,7 +6832,7 @@ function registerEvalCommand(parent) {
|
|
|
6680
6832
|
const spec = loadSpec(cmdOpts.file);
|
|
6681
6833
|
const validation = validateSpec(spec);
|
|
6682
6834
|
if (!isJsonMode()) {
|
|
6683
|
-
console.log(
|
|
6835
|
+
console.log(chalk8.dim(`
|
|
6684
6836
|
Spec: ${cmdOpts.file}
|
|
6685
6837
|
`));
|
|
6686
6838
|
}
|
|
@@ -6695,10 +6847,10 @@ Spec: ${cmdOpts.file}
|
|
|
6695
6847
|
});
|
|
6696
6848
|
}
|
|
6697
6849
|
function printValidation(checks) {
|
|
6698
|
-
console.log(
|
|
6850
|
+
console.log(chalk8.bold("Spec Validation"));
|
|
6699
6851
|
for (const check of checks) {
|
|
6700
|
-
const icon = check.passed ?
|
|
6701
|
-
const msg = check.message ?
|
|
6852
|
+
const icon = check.passed ? chalk8.green("\u2713") : chalk8.red("\u2717");
|
|
6853
|
+
const msg = check.message ? chalk8.dim(` \u2014 ${check.message}`) : "";
|
|
6702
6854
|
console.log(` ${icon} ${check.name}${msg}`);
|
|
6703
6855
|
}
|
|
6704
6856
|
}
|
|
@@ -6883,7 +7035,7 @@ function createProgram(version, runtime = {}) {
|
|
|
6883
7035
|
if (root.json) setJsonMode(true);
|
|
6884
7036
|
if (root.color === false) {
|
|
6885
7037
|
process.env.FORCE_COLOR = "0";
|
|
6886
|
-
|
|
7038
|
+
chalk9.level = 0;
|
|
6887
7039
|
}
|
|
6888
7040
|
});
|
|
6889
7041
|
registerAuthCommands(program);
|
|
@@ -6916,12 +7068,12 @@ function createProgram(version, runtime = {}) {
|
|
|
6916
7068
|
`);
|
|
6917
7069
|
return;
|
|
6918
7070
|
}
|
|
6919
|
-
output.write(`${
|
|
7071
|
+
output.write(`${chalk9.bold.cyan("Tuned Tensor status")}
|
|
6920
7072
|
`);
|
|
6921
7073
|
output.write(`${formatShellStatus(context, target).join("\n")}
|
|
6922
7074
|
|
|
6923
7075
|
`);
|
|
6924
|
-
output.write(`${
|
|
7076
|
+
output.write(`${chalk9.bold("Context")}
|
|
6925
7077
|
`);
|
|
6926
7078
|
output.write(
|
|
6927
7079
|
`${formatShellContext(
|
|
@@ -6935,7 +7087,7 @@ function createProgram(version, runtime = {}) {
|
|
|
6935
7087
|
program.command("local").description("Run the local CUDA training and model workflow").helpOption(false).allowUnknownOption().argument("[args...]", "TT Local command and arguments").action(async (args) => {
|
|
6936
7088
|
const root = program.opts();
|
|
6937
7089
|
const passthrough = extractPassthroughOptions(args, root);
|
|
6938
|
-
if (!passthrough.color)
|
|
7090
|
+
if (!passthrough.color) chalk9.level = 0;
|
|
6939
7091
|
const result = await invokeLocal(
|
|
6940
7092
|
passthrough.args.length > 0 ? passthrough.args : ["--help"],
|
|
6941
7093
|
{
|
|
@@ -7049,7 +7201,7 @@ async function runCli(version, runtime = {}) {
|
|
|
7049
7201
|
}
|
|
7050
7202
|
|
|
7051
7203
|
// src/index.ts
|
|
7052
|
-
runCli("0.8.
|
|
7204
|
+
runCli("0.8.1").catch((err) => {
|
|
7053
7205
|
reportError(err);
|
|
7054
7206
|
process.exit(1);
|
|
7055
7207
|
});
|