@sheepbun/yips 0.1.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/agent/commands/command-catalog.js +243 -0
- package/dist/agent/commands/commands.js +418 -0
- package/dist/agent/conductor.js +118 -0
- package/dist/agent/context/code-context.js +68 -0
- package/dist/agent/context/memory-store.js +159 -0
- package/dist/agent/context/session-store.js +211 -0
- package/dist/agent/protocol/tool-protocol.js +160 -0
- package/dist/agent/skills/skills.js +327 -0
- package/dist/agent/tools/tool-executor.js +415 -0
- package/dist/agent/tools/tool-safety.js +52 -0
- package/dist/app/index.js +35 -0
- package/dist/app/repl.js +105 -0
- package/dist/app/update-check.js +132 -0
- package/dist/app/version.js +51 -0
- package/dist/code-context.js +68 -0
- package/dist/colors.js +204 -0
- package/dist/command-catalog.js +242 -0
- package/dist/commands.js +350 -0
- package/dist/conductor.js +94 -0
- package/dist/config/config.js +335 -0
- package/dist/config/hooks.js +187 -0
- package/dist/config.js +335 -0
- package/dist/downloader-state.js +302 -0
- package/dist/downloader-ui.js +289 -0
- package/dist/gateway/adapters/discord.js +108 -0
- package/dist/gateway/adapters/formatting.js +96 -0
- package/dist/gateway/adapters/telegram.js +106 -0
- package/dist/gateway/adapters/types.js +2 -0
- package/dist/gateway/adapters/whatsapp.js +124 -0
- package/dist/gateway/auth-policy.js +66 -0
- package/dist/gateway/core.js +87 -0
- package/dist/gateway/headless-conductor.js +328 -0
- package/dist/gateway/message-router.js +23 -0
- package/dist/gateway/rate-limiter.js +48 -0
- package/dist/gateway/runtime/backend-policy.js +18 -0
- package/dist/gateway/runtime/discord-bot.js +104 -0
- package/dist/gateway/runtime/discord-main.js +69 -0
- package/dist/gateway/session-manager.js +77 -0
- package/dist/gateway/types.js +2 -0
- package/dist/hardware.js +92 -0
- package/dist/hooks.js +187 -0
- package/dist/index.js +34 -0
- package/dist/input-engine.js +250 -0
- package/dist/llama-client.js +227 -0
- package/dist/llama-server.js +620 -0
- package/dist/llm/llama-client.js +227 -0
- package/dist/llm/llama-server.js +620 -0
- package/dist/llm/token-counter.js +47 -0
- package/dist/memory-store.js +159 -0
- package/dist/messages.js +59 -0
- package/dist/model-downloader.js +382 -0
- package/dist/model-manager-state.js +118 -0
- package/dist/model-manager-ui.js +194 -0
- package/dist/model-manager.js +190 -0
- package/dist/models/hardware.js +92 -0
- package/dist/models/model-downloader.js +382 -0
- package/dist/models/model-manager.js +190 -0
- package/dist/prompt-box.js +78 -0
- package/dist/prompt-composer.js +498 -0
- package/dist/repl.js +105 -0
- package/dist/session-store.js +211 -0
- package/dist/spinner.js +76 -0
- package/dist/title-box.js +388 -0
- package/dist/token-counter.js +47 -0
- package/dist/tool-executor.js +415 -0
- package/dist/tool-protocol.js +121 -0
- package/dist/tool-safety.js +52 -0
- package/dist/tui/app.js +2553 -0
- package/dist/tui/startup.js +56 -0
- package/dist/tui-input-routing.js +53 -0
- package/dist/tui.js +51 -0
- package/dist/types/app-types.js +2 -0
- package/dist/types.js +2 -0
- package/dist/ui/colors.js +204 -0
- package/dist/ui/downloader/downloader-state.js +302 -0
- package/dist/ui/downloader/downloader-ui.js +289 -0
- package/dist/ui/input/input-engine.js +250 -0
- package/dist/ui/input/tui-input-routing.js +53 -0
- package/dist/ui/input/vt-session.js +168 -0
- package/dist/ui/messages.js +59 -0
- package/dist/ui/model-manager/model-manager-state.js +118 -0
- package/dist/ui/model-manager/model-manager-ui.js +194 -0
- package/dist/ui/prompt/prompt-box.js +78 -0
- package/dist/ui/prompt/prompt-composer.js +498 -0
- package/dist/ui/spinner.js +76 -0
- package/dist/ui/title-box.js +388 -0
- package/dist/ui/tui/app.js +6 -0
- package/dist/ui/tui/autocomplete.js +85 -0
- package/dist/ui/tui/constants.js +18 -0
- package/dist/ui/tui/history.js +29 -0
- package/dist/ui/tui/layout.js +341 -0
- package/dist/ui/tui/runtime-core.js +2584 -0
- package/dist/ui/tui/runtime-utils.js +53 -0
- package/dist/ui/tui/start-tui.js +54 -0
- package/dist/ui/tui/startup.js +56 -0
- package/dist/version.js +51 -0
- package/dist/vt-session.js +168 -0
- package/install.sh +457 -0
- package/package.json +128 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveModelLoadTarget = resolveModelLoadTarget;
|
|
4
|
+
exports.formatModelLoadingLabel = formatModelLoadingLabel;
|
|
5
|
+
exports.runOnceGuarded = runOnceGuarded;
|
|
6
|
+
exports.computeTokensPerSecond = computeTokensPerSecond;
|
|
7
|
+
exports.formatTokensPerSecond = formatTokensPerSecond;
|
|
8
|
+
exports.formatTitleCwd = formatTitleCwd;
|
|
9
|
+
const model_manager_1 = require("#models/model-manager");
|
|
10
|
+
function resolveLoadedModel(model) {
|
|
11
|
+
const trimmed = model.trim();
|
|
12
|
+
if (trimmed.length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (trimmed.toLowerCase() === "default") {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return trimmed;
|
|
19
|
+
}
|
|
20
|
+
function resolveModelLoadTarget(config) {
|
|
21
|
+
return config.llamaGpuLayers > 0 ? "GPU" : "CPU";
|
|
22
|
+
}
|
|
23
|
+
function formatModelLoadingLabel(config, nicknames) {
|
|
24
|
+
const loadedModel = resolveLoadedModel(config.model);
|
|
25
|
+
const modelLabel = loadedModel ? (0, model_manager_1.getFriendlyModelName)(loadedModel, nicknames) : "model";
|
|
26
|
+
const target = resolveModelLoadTarget(config);
|
|
27
|
+
return `Loading ${modelLabel} into ${target}...`;
|
|
28
|
+
}
|
|
29
|
+
async function runOnceGuarded(guard, operation) {
|
|
30
|
+
if (guard.current) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
guard.current = true;
|
|
34
|
+
await operation();
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
function computeTokensPerSecond(tokens, durationMs) {
|
|
38
|
+
if (!Number.isFinite(tokens) || !Number.isFinite(durationMs)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (tokens <= 0 || durationMs <= 0) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return tokens / (durationMs / 1000);
|
|
45
|
+
}
|
|
46
|
+
function formatTokensPerSecond(tokensPerSecond) {
|
|
47
|
+
const safe = Number.isFinite(tokensPerSecond) && tokensPerSecond > 0 ? tokensPerSecond : 0;
|
|
48
|
+
return `${safe.toFixed(1)} tk/s`;
|
|
49
|
+
}
|
|
50
|
+
function formatTitleCwd(cwd) {
|
|
51
|
+
const trimmed = cwd.trim();
|
|
52
|
+
return trimmed.length > 0 ? trimmed : "/";
|
|
53
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Main TUI entrypoint and compatibility exports. */
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ensureFreshLlamaSessionOnStartup = exports.applyHardwareAwareStartupModelSelection = exports.runOnceGuarded = exports.resolveModelLoadTarget = exports.formatTokensPerSecond = exports.formatTitleCwd = exports.formatModelLoadingLabel = exports.computeTokensPerSecond = exports.computeVisibleLayoutSlices = exports.computeTitleVisibleScrollCap = exports.composeOutputLines = exports.buildPromptStatusText = exports.buildPromptRenderLines = exports.shouldConsumeSubmitForAutocomplete = exports.buildModelAutocompleteCandidates = exports.buildAutocompleteOverlayLines = exports.renderHistoryLines = exports.composeChatRequestMessages = void 0;
|
|
8
|
+
exports.startTui = startTui;
|
|
9
|
+
const react_1 = __importDefault(require("react"));
|
|
10
|
+
const version_1 = require("#app/version");
|
|
11
|
+
const app_1 = require("#ui/tui/app");
|
|
12
|
+
const startup_1 = require("#ui/tui/startup");
|
|
13
|
+
var history_1 = require("#ui/tui/history");
|
|
14
|
+
Object.defineProperty(exports, "composeChatRequestMessages", { enumerable: true, get: function () { return history_1.composeChatRequestMessages; } });
|
|
15
|
+
Object.defineProperty(exports, "renderHistoryLines", { enumerable: true, get: function () { return history_1.renderHistoryLines; } });
|
|
16
|
+
var autocomplete_1 = require("#ui/tui/autocomplete");
|
|
17
|
+
Object.defineProperty(exports, "buildAutocompleteOverlayLines", { enumerable: true, get: function () { return autocomplete_1.buildAutocompleteOverlayLines; } });
|
|
18
|
+
Object.defineProperty(exports, "buildModelAutocompleteCandidates", { enumerable: true, get: function () { return autocomplete_1.buildModelAutocompleteCandidates; } });
|
|
19
|
+
Object.defineProperty(exports, "shouldConsumeSubmitForAutocomplete", { enumerable: true, get: function () { return autocomplete_1.shouldConsumeSubmitForAutocomplete; } });
|
|
20
|
+
var layout_1 = require("#ui/tui/layout");
|
|
21
|
+
Object.defineProperty(exports, "buildPromptRenderLines", { enumerable: true, get: function () { return layout_1.buildPromptRenderLines; } });
|
|
22
|
+
Object.defineProperty(exports, "buildPromptStatusText", { enumerable: true, get: function () { return layout_1.buildPromptStatusText; } });
|
|
23
|
+
Object.defineProperty(exports, "composeOutputLines", { enumerable: true, get: function () { return layout_1.composeOutputLines; } });
|
|
24
|
+
Object.defineProperty(exports, "computeTitleVisibleScrollCap", { enumerable: true, get: function () { return layout_1.computeTitleVisibleScrollCap; } });
|
|
25
|
+
Object.defineProperty(exports, "computeVisibleLayoutSlices", { enumerable: true, get: function () { return layout_1.computeVisibleLayoutSlices; } });
|
|
26
|
+
var runtime_utils_1 = require("#ui/tui/runtime-utils");
|
|
27
|
+
Object.defineProperty(exports, "computeTokensPerSecond", { enumerable: true, get: function () { return runtime_utils_1.computeTokensPerSecond; } });
|
|
28
|
+
Object.defineProperty(exports, "formatModelLoadingLabel", { enumerable: true, get: function () { return runtime_utils_1.formatModelLoadingLabel; } });
|
|
29
|
+
Object.defineProperty(exports, "formatTitleCwd", { enumerable: true, get: function () { return runtime_utils_1.formatTitleCwd; } });
|
|
30
|
+
Object.defineProperty(exports, "formatTokensPerSecond", { enumerable: true, get: function () { return runtime_utils_1.formatTokensPerSecond; } });
|
|
31
|
+
Object.defineProperty(exports, "resolveModelLoadTarget", { enumerable: true, get: function () { return runtime_utils_1.resolveModelLoadTarget; } });
|
|
32
|
+
Object.defineProperty(exports, "runOnceGuarded", { enumerable: true, get: function () { return runtime_utils_1.runOnceGuarded; } });
|
|
33
|
+
var startup_2 = require("#ui/tui/startup");
|
|
34
|
+
Object.defineProperty(exports, "applyHardwareAwareStartupModelSelection", { enumerable: true, get: function () { return startup_2.applyHardwareAwareStartupModelSelection; } });
|
|
35
|
+
Object.defineProperty(exports, "ensureFreshLlamaSessionOnStartup", { enumerable: true, get: function () { return startup_2.ensureFreshLlamaSessionOnStartup; } });
|
|
36
|
+
async function startTui(options) {
|
|
37
|
+
let restartRequested = false;
|
|
38
|
+
await (0, startup_1.applyHardwareAwareStartupModelSelection)(options);
|
|
39
|
+
await (0, startup_1.ensureFreshLlamaSessionOnStartup)(options);
|
|
40
|
+
const version = await (0, version_1.getVersion)();
|
|
41
|
+
const ink = (await import("ink"));
|
|
42
|
+
const App = (0, app_1.createInkApp)(ink);
|
|
43
|
+
const instance = ink.render(react_1.default.createElement(App, {
|
|
44
|
+
options,
|
|
45
|
+
version,
|
|
46
|
+
onRestartRequested: () => {
|
|
47
|
+
restartRequested = true;
|
|
48
|
+
}
|
|
49
|
+
}), {
|
|
50
|
+
exitOnCtrlC: false
|
|
51
|
+
});
|
|
52
|
+
await instance.waitUntilExit();
|
|
53
|
+
return restartRequested ? "restart" : "exit";
|
|
54
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyHardwareAwareStartupModelSelection = applyHardwareAwareStartupModelSelection;
|
|
4
|
+
exports.ensureFreshLlamaSessionOnStartup = ensureFreshLlamaSessionOnStartup;
|
|
5
|
+
const config_1 = require("#config/config");
|
|
6
|
+
const hardware_1 = require("#models/hardware");
|
|
7
|
+
const llama_server_1 = require("#llm/llama-server");
|
|
8
|
+
const model_manager_1 = require("#models/model-manager");
|
|
9
|
+
function resolveLoadedModel(model) {
|
|
10
|
+
const trimmed = model.trim();
|
|
11
|
+
if (trimmed.length === 0) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (trimmed.toLowerCase() === "default") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return trimmed;
|
|
18
|
+
}
|
|
19
|
+
async function applyHardwareAwareStartupModelSelection(options, deps = {
|
|
20
|
+
getSpecs: hardware_1.getSystemSpecs,
|
|
21
|
+
listModels: model_manager_1.listLocalModels,
|
|
22
|
+
selectModel: model_manager_1.selectBestModelForHardware,
|
|
23
|
+
save: config_1.saveConfig
|
|
24
|
+
}) {
|
|
25
|
+
if (options.config.backend !== "llamacpp") {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (resolveLoadedModel(options.config.model)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const specs = deps.getSpecs();
|
|
32
|
+
const models = await deps.listModels({
|
|
33
|
+
totalMemoryGb: specs.totalMemoryGb,
|
|
34
|
+
nicknames: options.config.nicknames
|
|
35
|
+
});
|
|
36
|
+
const selected = deps.selectModel(models, specs);
|
|
37
|
+
if (!selected) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
options.config.model = selected.id;
|
|
41
|
+
await deps.save(options.config);
|
|
42
|
+
return selected.id;
|
|
43
|
+
}
|
|
44
|
+
async function ensureFreshLlamaSessionOnStartup(options, deps = { reset: llama_server_1.resetLlamaForFreshSession }) {
|
|
45
|
+
if (options.config.backend !== "llamacpp") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const configuredModel = options.config.model.trim().toLowerCase();
|
|
49
|
+
if (configuredModel.length === 0 || configuredModel === "default") {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const resetResult = await deps.reset(options.config);
|
|
53
|
+
if (resetResult.failure) {
|
|
54
|
+
throw new Error((0, llama_server_1.formatLlamaStartupFailure)(resetResult.failure, options.config));
|
|
55
|
+
}
|
|
56
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Git-derived date-based versioning in the format vYYYY.M.D-SHORTHASH. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getGitInfo = getGitInfo;
|
|
5
|
+
exports.generateVersion = generateVersion;
|
|
6
|
+
exports.getVersion = getVersion;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const node_util_1 = require("node:util");
|
|
10
|
+
const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
11
|
+
const EXEC_TIMEOUT_MS = 5000;
|
|
12
|
+
const SHORT_SHA_LENGTH = 7;
|
|
13
|
+
const FALLBACK_VERSION = "1.0.0";
|
|
14
|
+
const REPO_ROOT = (0, node_path_1.resolve)(__dirname, "..");
|
|
15
|
+
async function getGitInfo() {
|
|
16
|
+
try {
|
|
17
|
+
const [timestampResult, shaResult] = await Promise.all([
|
|
18
|
+
execFile("git", ["-C", REPO_ROOT, "log", "-1", "--format=%ct"], {
|
|
19
|
+
timeout: EXEC_TIMEOUT_MS
|
|
20
|
+
}),
|
|
21
|
+
execFile("git", ["-C", REPO_ROOT, "rev-parse", `--short=${SHORT_SHA_LENGTH}`, "HEAD"], {
|
|
22
|
+
timeout: EXEC_TIMEOUT_MS
|
|
23
|
+
})
|
|
24
|
+
]);
|
|
25
|
+
const timestamp = parseInt(timestampResult.stdout.trim(), 10);
|
|
26
|
+
if (Number.isNaN(timestamp)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const shortSha = shaResult.stdout.trim();
|
|
30
|
+
if (shortSha.length === 0) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return { commitDate: new Date(timestamp * 1000), shortSha };
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function generateVersion(commitDate, shortSha) {
|
|
40
|
+
const year = commitDate.getFullYear();
|
|
41
|
+
const month = commitDate.getMonth() + 1;
|
|
42
|
+
const day = commitDate.getDate();
|
|
43
|
+
return `v${year}.${month}.${day}-${shortSha}`;
|
|
44
|
+
}
|
|
45
|
+
async function getVersion() {
|
|
46
|
+
const info = await getGitInfo();
|
|
47
|
+
if (info === null) {
|
|
48
|
+
return FALLBACK_VERSION;
|
|
49
|
+
}
|
|
50
|
+
return generateVersion(info.commitDate, info.shortSha);
|
|
51
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VirtualTerminalSession = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const node_pty_1 = require("node-pty");
|
|
6
|
+
function escapeForSingleQuotedShell(value) {
|
|
7
|
+
return value.replace(/'/gu, "'\\''");
|
|
8
|
+
}
|
|
9
|
+
function stripAnsi(value) {
|
|
10
|
+
const esc = String.fromCharCode(27);
|
|
11
|
+
let output = "";
|
|
12
|
+
let index = 0;
|
|
13
|
+
while (index < value.length) {
|
|
14
|
+
if (value[index] === esc && value[index + 1] === "[") {
|
|
15
|
+
index += 2;
|
|
16
|
+
while (index < value.length) {
|
|
17
|
+
const code = value.charCodeAt(index);
|
|
18
|
+
const isFinalByte = code >= 0x40 && code <= 0x7e;
|
|
19
|
+
index += 1;
|
|
20
|
+
if (isFinalByte) {
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
output += value[index] ?? "";
|
|
27
|
+
index += 1;
|
|
28
|
+
}
|
|
29
|
+
return output;
|
|
30
|
+
}
|
|
31
|
+
function escapeRegExp(input) {
|
|
32
|
+
return input.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
33
|
+
}
|
|
34
|
+
class VirtualTerminalSession {
|
|
35
|
+
pty = null;
|
|
36
|
+
listeners = new Set();
|
|
37
|
+
lines = [];
|
|
38
|
+
currentLine = "";
|
|
39
|
+
ensureStarted(cols = 100, rows = 30) {
|
|
40
|
+
if (this.pty) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const shell = process.env["SHELL"]?.trim() || "/bin/bash";
|
|
44
|
+
this.pty = (0, node_pty_1.spawn)(shell, ["-i"], {
|
|
45
|
+
name: "xterm-256color",
|
|
46
|
+
cols,
|
|
47
|
+
rows,
|
|
48
|
+
cwd: process.cwd(),
|
|
49
|
+
env: { ...process.env }
|
|
50
|
+
});
|
|
51
|
+
this.pty.onData((chunk) => {
|
|
52
|
+
this.consumeDisplayChunk(chunk);
|
|
53
|
+
for (const listener of this.listeners) {
|
|
54
|
+
listener(chunk);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
onData(listener) {
|
|
59
|
+
this.listeners.add(listener);
|
|
60
|
+
return () => {
|
|
61
|
+
this.listeners.delete(listener);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
resize(cols, rows) {
|
|
65
|
+
this.ensureStarted(cols, rows);
|
|
66
|
+
this.pty?.resize(Math.max(20, cols), Math.max(8, rows));
|
|
67
|
+
}
|
|
68
|
+
write(data) {
|
|
69
|
+
this.ensureStarted();
|
|
70
|
+
this.pty?.write(data);
|
|
71
|
+
}
|
|
72
|
+
getDisplayLines(limit = 200) {
|
|
73
|
+
const all = this.currentLine.length > 0 ? [...this.lines, this.currentLine] : [...this.lines];
|
|
74
|
+
return all.slice(-Math.max(1, limit));
|
|
75
|
+
}
|
|
76
|
+
async runCommand(command, options) {
|
|
77
|
+
this.ensureStarted();
|
|
78
|
+
const cwd = (0, node_path_1.resolve)(options.cwd);
|
|
79
|
+
const commandTimeoutMs = Math.max(1_000, Math.min(120_000, options.timeoutMs));
|
|
80
|
+
const id = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}`;
|
|
81
|
+
const startMarker = `__YIPS_START_${id}__`;
|
|
82
|
+
const endPrefix = `__YIPS_END_${id}__:`;
|
|
83
|
+
const wrapped = [
|
|
84
|
+
`printf '%s\\n' '${startMarker}'`,
|
|
85
|
+
`cd '${escapeForSingleQuotedShell(cwd)}' && (${command})`,
|
|
86
|
+
`printf '%s%s\\n' '${endPrefix}' "$?"`
|
|
87
|
+
].join("; ");
|
|
88
|
+
return await new Promise((resolveResult) => {
|
|
89
|
+
let buffer = "";
|
|
90
|
+
let started = false;
|
|
91
|
+
let settled = false;
|
|
92
|
+
const cleanup = (result) => {
|
|
93
|
+
if (settled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
settled = true;
|
|
97
|
+
off();
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
resolveResult(result);
|
|
100
|
+
};
|
|
101
|
+
const endPattern = new RegExp(`${escapeRegExp(endPrefix)}(\\d+)`, "u");
|
|
102
|
+
const off = this.onData((chunk) => {
|
|
103
|
+
if (settled) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
buffer += chunk;
|
|
107
|
+
if (!started) {
|
|
108
|
+
const startIndex = buffer.indexOf(startMarker);
|
|
109
|
+
if (startIndex < 0) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
started = true;
|
|
113
|
+
buffer = buffer.slice(startIndex + startMarker.length);
|
|
114
|
+
}
|
|
115
|
+
const endMatch = buffer.match(endPattern);
|
|
116
|
+
if (!endMatch || typeof endMatch.index !== "number") {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const outputRaw = buffer.slice(0, endMatch.index);
|
|
120
|
+
const output = stripAnsi(outputRaw).replace(/^\s+|\s+$/gu, "");
|
|
121
|
+
const exitCode = Number.parseInt(endMatch[1] ?? "1", 10);
|
|
122
|
+
cleanup({
|
|
123
|
+
exitCode: Number.isFinite(exitCode) ? exitCode : 1,
|
|
124
|
+
output,
|
|
125
|
+
timedOut: false
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
const timer = setTimeout(() => {
|
|
129
|
+
cleanup({
|
|
130
|
+
exitCode: 124,
|
|
131
|
+
output: "Command timed out.",
|
|
132
|
+
timedOut: true
|
|
133
|
+
});
|
|
134
|
+
}, commandTimeoutMs);
|
|
135
|
+
this.pty?.write(`${wrapped}\r`);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
dispose() {
|
|
139
|
+
this.listeners.clear();
|
|
140
|
+
this.pty?.kill();
|
|
141
|
+
this.pty = null;
|
|
142
|
+
this.lines = [];
|
|
143
|
+
this.currentLine = "";
|
|
144
|
+
}
|
|
145
|
+
consumeDisplayChunk(chunk) {
|
|
146
|
+
const plain = stripAnsi(chunk).replace(/\r\n/gu, "\n");
|
|
147
|
+
for (const char of Array.from(plain)) {
|
|
148
|
+
if (char === "\n") {
|
|
149
|
+
this.lines.push(this.currentLine);
|
|
150
|
+
this.currentLine = "";
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (char === "\r") {
|
|
154
|
+
this.currentLine = "";
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (char === "\b") {
|
|
158
|
+
this.currentLine = this.currentLine.slice(0, -1);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
this.currentLine += char;
|
|
162
|
+
}
|
|
163
|
+
if (this.lines.length > 1000) {
|
|
164
|
+
this.lines = this.lines.slice(-1000);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.VirtualTerminalSession = VirtualTerminalSession;
|