@truss-harness/tui 0.1.3 → 0.1.5
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/bin.js +16 -14
- package/package.json +53 -53
package/dist/bin.js
CHANGED
|
@@ -9,23 +9,23 @@ import { promisify } from "node:util";
|
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { Box, render, Text, useApp, useInput } from "ink";
|
|
11
11
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
12
|
-
import { detectLocalEndpoints, listLocalModels } from "@truss-harness/provider-openai-compatible";
|
|
12
|
+
import { cloudProviderDefinition, detectLocalEndpoints, isCloudProviderId, isLocalEndpointKind, listLocalModels } from "@truss-harness/provider-openai-compatible";
|
|
13
13
|
import { brand } from "@truss-harness/branding";
|
|
14
14
|
import { resolveConfiguration } from "@truss-harness/cli/config";
|
|
15
15
|
import { createClientRuntime } from "@truss-harness/cli/runtime";
|
|
16
16
|
import { executeWorkspaceCommand, FileWorkspacePlanStore, workspaceCommandHelp } from "@truss-harness/runtime";
|
|
17
17
|
import { buildFileTree, fuzzyFiles, syntaxTokens, wrapSyntaxTokens } from "./file-browser.js";
|
|
18
18
|
import { tuiTheme, tuiThemeNames } from "./theme.js";
|
|
19
|
-
const tuiHelp = `${brand.productName} TUI
|
|
20
|
-
|
|
21
|
-
Full-screen terminal workspace for local coding models.
|
|
22
|
-
|
|
23
|
-
Usage:
|
|
24
|
-
${brand.tuiCommand}
|
|
25
|
-
|
|
26
|
-
The TUI starts in the current workspace and reads the same configuration
|
|
27
|
-
profiles as ${brand.cliCommand}. Press ? inside the TUI for its complete
|
|
28
|
-
keyboard-control reference.
|
|
19
|
+
const tuiHelp = `${brand.productName} TUI
|
|
20
|
+
|
|
21
|
+
Full-screen terminal workspace for local coding models.
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
${brand.tuiCommand}
|
|
25
|
+
|
|
26
|
+
The TUI starts in the current workspace and reads the same configuration
|
|
27
|
+
profiles as ${brand.cliCommand}. Press ? inside the TUI for its complete
|
|
28
|
+
keyboard-control reference.
|
|
29
29
|
`;
|
|
30
30
|
const tuiControlHelp = [
|
|
31
31
|
["NAVIGATION", "Tab / Shift+Tab move focus; Ctrl+Left / Ctrl+Right move to an adjacent pane."],
|
|
@@ -327,7 +327,7 @@ function App({ initialConfiguration }) {
|
|
|
327
327
|
return () => { process.stdout.off("resize", refreshViewport); };
|
|
328
328
|
}, []);
|
|
329
329
|
useEffect(() => {
|
|
330
|
-
if (!selectedEndpoint || !endpointInput)
|
|
330
|
+
if (!selectedEndpoint || !endpointInput || !isLocalEndpointKind(providerKind))
|
|
331
331
|
return;
|
|
332
332
|
const endpoint = { ...selectedEndpoint, kind: providerKind, baseUrl: endpointInput };
|
|
333
333
|
void listLocalModels(endpoint).then((available) => {
|
|
@@ -444,7 +444,9 @@ function App({ initialConfiguration }) {
|
|
|
444
444
|
provider: providerKind,
|
|
445
445
|
baseUrl: endpointInput.trim(),
|
|
446
446
|
model: modelInput.trim(),
|
|
447
|
-
apiKey:
|
|
447
|
+
apiKey: initialConfiguration?.provider === providerKind
|
|
448
|
+
? initialConfiguration.apiKey
|
|
449
|
+
: process.env.TRUSS_HARNESS_API_KEY ?? (isCloudProviderId(providerKind) ? process.env[cloudProviderDefinition(providerKind).apiKeyEnvironmentVariable] : undefined),
|
|
448
450
|
systemPrompt: process.env.TRUSS_HARNESS_SYSTEM_PROMPT,
|
|
449
451
|
mode: agentMode,
|
|
450
452
|
internetAccess,
|
|
@@ -824,7 +826,7 @@ function App({ initialConfiguration }) {
|
|
|
824
826
|
const selected = index === Math.min(fileSearchIndex, Math.max(0, fileSearchResults.length - 1));
|
|
825
827
|
const fileName = entry.path.split("/").at(-1) ?? entry.path;
|
|
826
828
|
return _jsxs(Text, { color: selected ? theme.focus : theme.text, bold: selected, children: [selected ? "> " : " ", fileName, _jsxs(Text, { color: theme.muted, children: [" ", truncate(entry.path, Math.max(12, overlayWidth - fileName.length - 10))] })] }, entry.path);
|
|
827
|
-
}), !fileSearchResults.length && _jsx(Text, { color: theme.warning, children: "No matching files." })] })] }), screen === "settings" && _jsxs(Box, { position: "absolute", flexDirection: "column", borderStyle: "double", borderColor: theme.focus, paddingX: 2, paddingY: 1, width: overlayWidth, marginLeft: 2, marginTop: 3, backgroundColor: theme.overlay, children: [_jsx(Text, { bold: true, color: theme.accent, children: "LOCAL MODEL CONFIGURATION" }), _jsx(Text, { color: theme.muted, children: "Tab changes fields. Enter selects an item or saves when endpoint and model are set." }), _jsxs(Text, { color: settingsField === "server" ? theme.focus : theme.text, children: ["SERVER: ", selectedEndpoint?.label ?? "Scanning local servers..."] }), _jsxs(Text, { color: settingsField === "endpoint" ? theme.focus : theme.text, children: ["ENDPOINT: ", endpointInput] }), _jsxs(Text, { color: settingsField === "model" ? theme.focus : theme.text, children: ["MODEL: ", modelInput || models[modelIndex] || "Choose or type a model"] }), _jsxs(Text, { color: settingsField === "internet" ? theme.focus : theme.text, children: ["INTERNET RESEARCH: ", internetAccess ? "enabled" : "disabled", " ", settingsField === "internet" ? "[Space toggles]" : ""] }), _jsxs(Text, { color: settingsField === "theme" ? theme.focus : theme.text, children: ["THEME: ", themeName, " ", settingsField === "theme" ? "[Left/Right changes]" : ""] }), _jsxs(Text, { color: theme.muted, children: ["Detected models: ", models.slice(0, 5).join(", ") || "none; type one manually"] }), _jsxs(Text, { color: theme.warning, children: ["Provider: ", providerKind, ".
|
|
829
|
+
}), !fileSearchResults.length && _jsx(Text, { color: theme.warning, children: "No matching files." })] })] }), screen === "settings" && _jsxs(Box, { position: "absolute", flexDirection: "column", borderStyle: "double", borderColor: theme.focus, paddingX: 2, paddingY: 1, width: overlayWidth, marginLeft: 2, marginTop: 3, backgroundColor: theme.overlay, children: [_jsx(Text, { bold: true, color: theme.accent, children: "LOCAL MODEL CONFIGURATION" }), _jsx(Text, { color: theme.muted, children: "Tab changes fields. Enter selects an item or saves when endpoint and model are set." }), _jsxs(Text, { color: settingsField === "server" ? theme.focus : theme.text, children: ["SERVER: ", selectedEndpoint?.label ?? "Scanning local servers..."] }), _jsxs(Text, { color: settingsField === "endpoint" ? theme.focus : theme.text, children: ["ENDPOINT: ", endpointInput] }), _jsxs(Text, { color: settingsField === "model" ? theme.focus : theme.text, children: ["MODEL: ", modelInput || models[modelIndex] || "Choose or type a model"] }), _jsxs(Text, { color: settingsField === "internet" ? theme.focus : theme.text, children: ["INTERNET RESEARCH: ", internetAccess ? "enabled" : "disabled", " ", settingsField === "internet" ? "[Space toggles]" : ""] }), _jsxs(Text, { color: settingsField === "theme" ? theme.focus : theme.text, children: ["THEME: ", themeName, " ", settingsField === "theme" ? "[Left/Right changes]" : ""] }), _jsxs(Text, { color: theme.muted, children: ["Detected models: ", models.slice(0, 5).join(", ") || "none; type one manually"] }), _jsxs(Text, { color: theme.warning, children: ["Provider: ", providerKind, ". Local endpoints use the server selector. Configure cloud BYOK profiles with truss-cli setup, then relaunch the TUI."] })] }), screen === "approval" && _jsxs(Box, { position: "absolute", flexDirection: "column", borderStyle: "double", borderColor: theme.warning, paddingX: 2, paddingY: 1, width: overlayWidth, marginLeft: 2, marginTop: 8, backgroundColor: theme.overlay, children: [_jsx(Text, { bold: true, color: theme.warning, children: "TOOL APPROVAL REQUIRED" }), _jsxs(Text, { color: theme.text, children: [pendingTool?.name, " ", JSON.stringify(pendingTool?.input)] }), _jsx(Text, { color: theme.muted, children: "Press Y or Enter to allow. Press N or Escape to deny." })] }), screen === "help" && _jsxs(Box, { position: "absolute", flexDirection: "column", borderStyle: "double", borderColor: theme.focus, paddingX: 2, paddingY: 1, width: overlayWidth, marginLeft: 2, marginTop: 7, backgroundColor: theme.overlay, children: [_jsx(Text, { bold: true, color: theme.accent, children: "TUI CONTROLS" }), tuiControlHelp.map(([label, detail]) => _jsxs(Text, { color: theme.text, wrap: "wrap", children: [_jsxs(Text, { bold: true, color: theme.focus, children: [label, ": "] }), detail] }, label)), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: theme.accent, children: "WORKSPACE COMMANDS" }) }), workspaceCommandHelp().split("\n").slice(1).map((line) => _jsx(Text, { color: theme.text, children: line }, line)), _jsx(Text, { color: theme.muted, children: "Press any key to close this reference." })] })] });
|
|
828
830
|
}
|
|
829
831
|
const initialConfiguration = await resolveConfiguration({ workspaceRoot: cwd() }).catch((error) => {
|
|
830
832
|
const message = error instanceof Error ? error.message : String(error);
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@truss-harness/tui",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Interactive terminal client for Truss.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"truss-tui": "dist/bin.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "tsc -b",
|
|
11
|
-
"prepack": "node ../../scripts/clean-publish-tests.mjs",
|
|
12
|
-
"prepublishOnly": "npm run build"
|
|
13
|
-
},
|
|
14
|
-
"files": [
|
|
15
|
-
"dist",
|
|
16
|
-
"README.md",
|
|
17
|
-
"logo.png"
|
|
18
|
-
],
|
|
19
|
-
"engines": {
|
|
20
|
-
"node": ">=20"
|
|
21
|
-
},
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"repository": {
|
|
24
|
-
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/truss-agent/truss-harness.git"
|
|
26
|
-
},
|
|
27
|
-
"bugs": {
|
|
28
|
-
"url": "https://github.com/truss-agent/truss-harness/issues"
|
|
29
|
-
},
|
|
30
|
-
"homepage": "https://github.com/truss-agent/truss-harness#readme",
|
|
31
|
-
"publishConfig": {
|
|
32
|
-
"access": "public"
|
|
33
|
-
},
|
|
34
|
-
"keywords": [
|
|
35
|
-
"ai",
|
|
36
|
-
"coding-agent",
|
|
37
|
-
"tui",
|
|
38
|
-
"terminal",
|
|
39
|
-
"ollama",
|
|
40
|
-
"local-first"
|
|
41
|
-
],
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"ink": "^6.8.0",
|
|
44
|
-
"react": "^19.2.0",
|
|
45
|
-
"@truss-harness/branding": "0.1.0",
|
|
46
|
-
"@truss-harness/cli": "0.1.
|
|
47
|
-
"@truss-harness/provider-openai-compatible": "0.1.
|
|
48
|
-
"@truss-harness/runtime": "0.1.
|
|
49
|
-
},
|
|
50
|
-
"devDependencies": {
|
|
51
|
-
"@types/react": "^19.2.0"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@truss-harness/tui",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Interactive terminal client for Truss.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"truss-tui": "dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -b",
|
|
11
|
+
"prepack": "node ../../scripts/clean-publish-tests.mjs",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"logo.png"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/truss-agent/truss-harness.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/truss-agent/truss-harness/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/truss-agent/truss-harness#readme",
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"ai",
|
|
36
|
+
"coding-agent",
|
|
37
|
+
"tui",
|
|
38
|
+
"terminal",
|
|
39
|
+
"ollama",
|
|
40
|
+
"local-first"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"ink": "^6.8.0",
|
|
44
|
+
"react": "^19.2.0",
|
|
45
|
+
"@truss-harness/branding": "0.1.0",
|
|
46
|
+
"@truss-harness/cli": "0.1.5",
|
|
47
|
+
"@truss-harness/provider-openai-compatible": "0.1.2",
|
|
48
|
+
"@truss-harness/runtime": "0.1.2"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/react": "^19.2.0"
|
|
52
|
+
}
|
|
53
|
+
}
|