@sheepbun/yips 0.1.1 → 0.1.46
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/LICENSE +21 -0
- package/README.md +52 -0
- package/bin/yips.js +15 -0
- package/package.json +21 -128
- package/postinstall.js +50 -0
- package/dist/agent/commands/command-catalog.js +0 -243
- package/dist/agent/commands/commands.js +0 -418
- package/dist/agent/conductor.js +0 -118
- package/dist/agent/context/code-context.js +0 -68
- package/dist/agent/context/memory-store.js +0 -159
- package/dist/agent/context/session-store.js +0 -211
- package/dist/agent/protocol/tool-protocol.js +0 -160
- package/dist/agent/skills/skills.js +0 -327
- package/dist/agent/tools/tool-executor.js +0 -415
- package/dist/agent/tools/tool-safety.js +0 -52
- package/dist/app/index.js +0 -35
- package/dist/app/repl.js +0 -105
- package/dist/app/update-check.js +0 -132
- package/dist/app/version.js +0 -51
- package/dist/code-context.js +0 -68
- package/dist/colors.js +0 -204
- package/dist/command-catalog.js +0 -242
- package/dist/commands.js +0 -350
- package/dist/conductor.js +0 -94
- package/dist/config/config.js +0 -335
- package/dist/config/hooks.js +0 -187
- package/dist/config.js +0 -335
- package/dist/downloader-state.js +0 -302
- package/dist/downloader-ui.js +0 -289
- package/dist/gateway/adapters/discord.js +0 -108
- package/dist/gateway/adapters/formatting.js +0 -96
- package/dist/gateway/adapters/telegram.js +0 -106
- package/dist/gateway/adapters/types.js +0 -2
- package/dist/gateway/adapters/whatsapp.js +0 -124
- package/dist/gateway/auth-policy.js +0 -66
- package/dist/gateway/core.js +0 -87
- package/dist/gateway/headless-conductor.js +0 -328
- package/dist/gateway/message-router.js +0 -23
- package/dist/gateway/rate-limiter.js +0 -48
- package/dist/gateway/runtime/backend-policy.js +0 -18
- package/dist/gateway/runtime/discord-bot.js +0 -104
- package/dist/gateway/runtime/discord-main.js +0 -69
- package/dist/gateway/session-manager.js +0 -77
- package/dist/gateway/types.js +0 -2
- package/dist/hardware.js +0 -92
- package/dist/hooks.js +0 -187
- package/dist/index.js +0 -34
- package/dist/input-engine.js +0 -250
- package/dist/llama-client.js +0 -227
- package/dist/llama-server.js +0 -620
- package/dist/llm/llama-client.js +0 -227
- package/dist/llm/llama-server.js +0 -620
- package/dist/llm/token-counter.js +0 -47
- package/dist/memory-store.js +0 -159
- package/dist/messages.js +0 -59
- package/dist/model-downloader.js +0 -382
- package/dist/model-manager-state.js +0 -118
- package/dist/model-manager-ui.js +0 -194
- package/dist/model-manager.js +0 -190
- package/dist/models/hardware.js +0 -92
- package/dist/models/model-downloader.js +0 -382
- package/dist/models/model-manager.js +0 -190
- package/dist/prompt-box.js +0 -78
- package/dist/prompt-composer.js +0 -498
- package/dist/repl.js +0 -105
- package/dist/session-store.js +0 -211
- package/dist/spinner.js +0 -76
- package/dist/title-box.js +0 -388
- package/dist/token-counter.js +0 -47
- package/dist/tool-executor.js +0 -415
- package/dist/tool-protocol.js +0 -121
- package/dist/tool-safety.js +0 -52
- package/dist/tui/app.js +0 -2553
- package/dist/tui/startup.js +0 -56
- package/dist/tui-input-routing.js +0 -53
- package/dist/tui.js +0 -51
- package/dist/types/app-types.js +0 -2
- package/dist/types.js +0 -2
- package/dist/ui/colors.js +0 -204
- package/dist/ui/downloader/downloader-state.js +0 -302
- package/dist/ui/downloader/downloader-ui.js +0 -289
- package/dist/ui/input/input-engine.js +0 -250
- package/dist/ui/input/tui-input-routing.js +0 -53
- package/dist/ui/input/vt-session.js +0 -168
- package/dist/ui/messages.js +0 -59
- package/dist/ui/model-manager/model-manager-state.js +0 -118
- package/dist/ui/model-manager/model-manager-ui.js +0 -194
- package/dist/ui/prompt/prompt-box.js +0 -78
- package/dist/ui/prompt/prompt-composer.js +0 -498
- package/dist/ui/spinner.js +0 -76
- package/dist/ui/title-box.js +0 -388
- package/dist/ui/tui/app.js +0 -6
- package/dist/ui/tui/autocomplete.js +0 -85
- package/dist/ui/tui/constants.js +0 -18
- package/dist/ui/tui/history.js +0 -29
- package/dist/ui/tui/layout.js +0 -341
- package/dist/ui/tui/runtime-core.js +0 -2584
- package/dist/ui/tui/runtime-utils.js +0 -53
- package/dist/ui/tui/start-tui.js +0 -54
- package/dist/ui/tui/startup.js +0 -56
- package/dist/version.js +0 -51
- package/dist/vt-session.js +0 -168
- package/install.sh +0 -457
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GATEWAY_BACKEND_ENV_VAR = exports.DEFAULT_GATEWAY_BACKEND = void 0;
|
|
4
|
-
exports.resolveGatewayBackendFromEnv = resolveGatewayBackendFromEnv;
|
|
5
|
-
exports.DEFAULT_GATEWAY_BACKEND = "llamacpp";
|
|
6
|
-
exports.GATEWAY_BACKEND_ENV_VAR = "YIPS_GATEWAY_BACKEND";
|
|
7
|
-
function resolveGatewayBackendFromEnv(rawValue) {
|
|
8
|
-
const trimmed = rawValue?.trim();
|
|
9
|
-
if (!trimmed) {
|
|
10
|
-
return exports.DEFAULT_GATEWAY_BACKEND;
|
|
11
|
-
}
|
|
12
|
-
const normalized = trimmed.toLowerCase();
|
|
13
|
-
if (normalized === "llamacpp") {
|
|
14
|
-
return "llamacpp";
|
|
15
|
-
}
|
|
16
|
-
throw new Error(`Unsupported ${exports.GATEWAY_BACKEND_ENV_VAR} value '${trimmed}'. ` +
|
|
17
|
-
"Gateway headless mode currently supports backend 'llamacpp' only.");
|
|
18
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DiscordGatewayRuntime = void 0;
|
|
4
|
-
exports.createDiscordGatewayRuntime = createDiscordGatewayRuntime;
|
|
5
|
-
const discord_1 = require("#gateway/adapters/discord");
|
|
6
|
-
function defaultLoadDiscordModule() {
|
|
7
|
-
return import("discord.js");
|
|
8
|
-
}
|
|
9
|
-
function toRequestList(request) {
|
|
10
|
-
if (!request) {
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
return Array.isArray(request) ? request : [request];
|
|
14
|
-
}
|
|
15
|
-
function defaultFetchImpl(input, init) {
|
|
16
|
-
return fetch(input, init);
|
|
17
|
-
}
|
|
18
|
-
class DiscordGatewayRuntime {
|
|
19
|
-
botToken;
|
|
20
|
-
gateway;
|
|
21
|
-
adapter;
|
|
22
|
-
fetchImpl;
|
|
23
|
-
loadDiscordModule;
|
|
24
|
-
onError;
|
|
25
|
-
client = null;
|
|
26
|
-
constructor(options) {
|
|
27
|
-
this.botToken = options.botToken.trim();
|
|
28
|
-
this.gateway = options.gateway;
|
|
29
|
-
this.adapter = options.adapter ?? new discord_1.DiscordAdapter({ botToken: this.botToken });
|
|
30
|
-
this.fetchImpl = options.fetchImpl ?? defaultFetchImpl;
|
|
31
|
-
this.loadDiscordModule = options.loadDiscordModule ?? defaultLoadDiscordModule;
|
|
32
|
-
this.onError = options.onError ?? ((error) => console.error("[gateway/discord]", error));
|
|
33
|
-
}
|
|
34
|
-
async start() {
|
|
35
|
-
if (this.client) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const discord = await this.loadDiscordModule();
|
|
39
|
-
const intents = discord.GatewayIntentBits ?? {};
|
|
40
|
-
const partials = discord.Partials ?? {};
|
|
41
|
-
const client = new discord.Client({
|
|
42
|
-
intents: [
|
|
43
|
-
intents.Guilds,
|
|
44
|
-
intents.GuildMessages,
|
|
45
|
-
intents.DirectMessages,
|
|
46
|
-
intents.MessageContent
|
|
47
|
-
].filter((value) => typeof value === "number"),
|
|
48
|
-
partials: [partials.Channel].filter((value) => typeof value === "number")
|
|
49
|
-
});
|
|
50
|
-
client.on("messageCreate", (message) => {
|
|
51
|
-
void this.handleDiscordMessage(message);
|
|
52
|
-
});
|
|
53
|
-
await client.login(this.botToken);
|
|
54
|
-
this.client = client;
|
|
55
|
-
}
|
|
56
|
-
async stop() {
|
|
57
|
-
if (!this.client) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
this.client.destroy();
|
|
61
|
-
this.client = null;
|
|
62
|
-
}
|
|
63
|
-
async handleDiscordMessage(payload) {
|
|
64
|
-
try {
|
|
65
|
-
const inboundMessages = this.adapter.parseInbound(payload);
|
|
66
|
-
for (const inbound of inboundMessages) {
|
|
67
|
-
const result = await this.gateway.dispatch(inbound);
|
|
68
|
-
if (!result.response) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const context = {
|
|
72
|
-
session: {
|
|
73
|
-
id: result.sessionId ?? `discord.${inbound.senderId}.${inbound.channelId ?? "direct"}`,
|
|
74
|
-
platform: "discord",
|
|
75
|
-
senderId: inbound.senderId,
|
|
76
|
-
channelId: inbound.channelId ?? "direct",
|
|
77
|
-
createdAt: new Date(),
|
|
78
|
-
updatedAt: new Date(),
|
|
79
|
-
messageCount: 1
|
|
80
|
-
},
|
|
81
|
-
message: inbound
|
|
82
|
-
};
|
|
83
|
-
const requests = toRequestList(this.adapter.formatOutbound(context, result.response));
|
|
84
|
-
for (const request of requests) {
|
|
85
|
-
const response = await this.fetchImpl(request.endpoint, {
|
|
86
|
-
method: request.method,
|
|
87
|
-
headers: request.headers,
|
|
88
|
-
body: request.body ? JSON.stringify(request.body) : undefined
|
|
89
|
-
});
|
|
90
|
-
if (!response.ok) {
|
|
91
|
-
throw new Error(`discord send failed (${response.status})`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
this.onError(error);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
exports.DiscordGatewayRuntime = DiscordGatewayRuntime;
|
|
102
|
-
function createDiscordGatewayRuntime(options) {
|
|
103
|
-
return new DiscordGatewayRuntime(options);
|
|
104
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const core_1 = require("#gateway/core");
|
|
4
|
-
const discord_bot_1 = require("#gateway/runtime/discord-bot");
|
|
5
|
-
const config_1 = require("#config/config");
|
|
6
|
-
const headless_conductor_1 = require("#gateway/headless-conductor");
|
|
7
|
-
const backend_policy_1 = require("#gateway/runtime/backend-policy");
|
|
8
|
-
function readRequiredEnv(name) {
|
|
9
|
-
const value = process.env[name]?.trim();
|
|
10
|
-
if (!value) {
|
|
11
|
-
throw new Error(`Missing required environment variable: ${name}`);
|
|
12
|
-
}
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
function readAllowedSenders() {
|
|
16
|
-
const raw = process.env.YIPS_GATEWAY_ALLOWED_SENDERS;
|
|
17
|
-
if (!raw) {
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
return raw
|
|
21
|
-
.split(",")
|
|
22
|
-
.map((value) => value.trim())
|
|
23
|
-
.filter((value) => value.length > 0);
|
|
24
|
-
}
|
|
25
|
-
function readOptionalEnv(name) {
|
|
26
|
-
const value = process.env[name]?.trim();
|
|
27
|
-
return value && value.length > 0 ? value : undefined;
|
|
28
|
-
}
|
|
29
|
-
async function main() {
|
|
30
|
-
const botToken = readRequiredEnv("YIPS_DISCORD_BOT_TOKEN");
|
|
31
|
-
const allowedSenderIds = readAllowedSenders();
|
|
32
|
-
const passphrase = readOptionalEnv("YIPS_GATEWAY_PASSPHRASE");
|
|
33
|
-
const gatewayBackend = (0, backend_policy_1.resolveGatewayBackendFromEnv)(process.env.YIPS_GATEWAY_BACKEND);
|
|
34
|
-
const configResult = await (0, config_1.loadConfig)();
|
|
35
|
-
if (configResult.warning) {
|
|
36
|
-
console.error(`[warning] ${configResult.warning}`);
|
|
37
|
-
}
|
|
38
|
-
const headless = await (0, headless_conductor_1.createGatewayHeadlessMessageHandler)({
|
|
39
|
-
config: configResult.config,
|
|
40
|
-
username: "Gateway User",
|
|
41
|
-
gatewayBackend
|
|
42
|
-
});
|
|
43
|
-
const gateway = new core_1.GatewayCore({
|
|
44
|
-
allowedSenderIds: allowedSenderIds.length > 0 ? allowedSenderIds : undefined,
|
|
45
|
-
passphrase,
|
|
46
|
-
handleMessage: headless.handleMessage
|
|
47
|
-
});
|
|
48
|
-
const runtime = (0, discord_bot_1.createDiscordGatewayRuntime)({
|
|
49
|
-
botToken,
|
|
50
|
-
gateway
|
|
51
|
-
});
|
|
52
|
-
await runtime.start();
|
|
53
|
-
const shutdown = async () => {
|
|
54
|
-
await runtime.stop();
|
|
55
|
-
headless.dispose();
|
|
56
|
-
process.exit(0);
|
|
57
|
-
};
|
|
58
|
-
process.once("SIGINT", () => {
|
|
59
|
-
void shutdown();
|
|
60
|
-
});
|
|
61
|
-
process.once("SIGTERM", () => {
|
|
62
|
-
void shutdown();
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
void main().catch((error) => {
|
|
66
|
-
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
67
|
-
console.error(`[fatal] ${message}`);
|
|
68
|
-
process.exitCode = 1;
|
|
69
|
-
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GatewaySessionManager = void 0;
|
|
4
|
-
exports.toConversationKey = toConversationKey;
|
|
5
|
-
exports.toSessionId = toSessionId;
|
|
6
|
-
const DIRECT_CHANNEL = "direct";
|
|
7
|
-
function sanitizeIdPart(value) {
|
|
8
|
-
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9._-]/g, "-");
|
|
9
|
-
return normalized.length > 0 ? normalized : "unknown";
|
|
10
|
-
}
|
|
11
|
-
function toConversationKey(message) {
|
|
12
|
-
const channelId = message.channelId ?? DIRECT_CHANNEL;
|
|
13
|
-
return `${message.platform}:${message.senderId}:${channelId}`;
|
|
14
|
-
}
|
|
15
|
-
function toSessionId(message) {
|
|
16
|
-
const channelId = message.channelId ?? DIRECT_CHANNEL;
|
|
17
|
-
return [
|
|
18
|
-
sanitizeIdPart(message.platform),
|
|
19
|
-
sanitizeIdPart(message.senderId),
|
|
20
|
-
sanitizeIdPart(channelId)
|
|
21
|
-
].join(".");
|
|
22
|
-
}
|
|
23
|
-
class GatewaySessionManager {
|
|
24
|
-
sessionsByKey = new Map();
|
|
25
|
-
now;
|
|
26
|
-
constructor(now = () => new Date()) {
|
|
27
|
-
this.now = now;
|
|
28
|
-
}
|
|
29
|
-
getOrCreateSession(message) {
|
|
30
|
-
const key = toConversationKey(message);
|
|
31
|
-
const existing = this.sessionsByKey.get(key);
|
|
32
|
-
if (existing) {
|
|
33
|
-
existing.messageCount += 1;
|
|
34
|
-
existing.updatedAt = this.now();
|
|
35
|
-
return existing;
|
|
36
|
-
}
|
|
37
|
-
const now = this.now();
|
|
38
|
-
const created = {
|
|
39
|
-
id: toSessionId(message),
|
|
40
|
-
platform: message.platform,
|
|
41
|
-
senderId: message.senderId,
|
|
42
|
-
channelId: message.channelId ?? DIRECT_CHANNEL,
|
|
43
|
-
createdAt: now,
|
|
44
|
-
updatedAt: now,
|
|
45
|
-
messageCount: 1
|
|
46
|
-
};
|
|
47
|
-
this.sessionsByKey.set(key, created);
|
|
48
|
-
return created;
|
|
49
|
-
}
|
|
50
|
-
listSessions() {
|
|
51
|
-
return Array.from(this.sessionsByKey.values()).sort((a, b) => b.updatedAt.valueOf() - a.updatedAt.valueOf());
|
|
52
|
-
}
|
|
53
|
-
removeSession(sessionId) {
|
|
54
|
-
for (const [key, session] of this.sessionsByKey) {
|
|
55
|
-
if (session.id === sessionId) {
|
|
56
|
-
this.sessionsByKey.delete(key);
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
pruneIdleSessions(maxIdleMs) {
|
|
63
|
-
if (maxIdleMs <= 0) {
|
|
64
|
-
return 0;
|
|
65
|
-
}
|
|
66
|
-
const cutoff = this.now().valueOf() - maxIdleMs;
|
|
67
|
-
let removed = 0;
|
|
68
|
-
for (const [key, session] of this.sessionsByKey) {
|
|
69
|
-
if (session.updatedAt.valueOf() < cutoff) {
|
|
70
|
-
this.sessionsByKey.delete(key);
|
|
71
|
-
removed += 1;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return removed;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.GatewaySessionManager = GatewaySessionManager;
|
package/dist/gateway/types.js
DELETED
package/dist/hardware.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSystemSpecs = getSystemSpecs;
|
|
4
|
-
exports.clearSystemSpecsCache = clearSystemSpecsCache;
|
|
5
|
-
const node_child_process_1 = require("node:child_process");
|
|
6
|
-
const node_fs_1 = require("node:fs");
|
|
7
|
-
const node_fs_2 = require("node:fs");
|
|
8
|
-
const node_os_1 = require("node:os");
|
|
9
|
-
const node_path_1 = require("node:path");
|
|
10
|
-
const node_fs_3 = require("node:fs");
|
|
11
|
-
function roundOne(value) {
|
|
12
|
-
return Math.round(value * 10) / 10;
|
|
13
|
-
}
|
|
14
|
-
function getRamGb() {
|
|
15
|
-
return roundOne((0, node_os_1.totalmem)() / (1024 ** 3));
|
|
16
|
-
}
|
|
17
|
-
function getNvidiaVramGb() {
|
|
18
|
-
try {
|
|
19
|
-
const result = (0, node_child_process_1.execFileSync)("nvidia-smi", ["--query-gpu=memory.total", "--format=csv,noheader,nounits"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
20
|
-
const totalMb = result
|
|
21
|
-
.split(/\r?\n/u)
|
|
22
|
-
.map((line) => line.trim())
|
|
23
|
-
.filter((line) => line.length > 0)
|
|
24
|
-
.map((line) => Number(line))
|
|
25
|
-
.filter((value) => Number.isFinite(value) && value > 0)
|
|
26
|
-
.reduce((sum, value) => sum + value, 0);
|
|
27
|
-
return totalMb > 0 ? roundOne(totalMb / 1024) : 0;
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return 0;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function getAmdVramGb() {
|
|
34
|
-
try {
|
|
35
|
-
const paths = (0, node_fs_2.globSync)("/sys/class/drm/card*/device/mem_info_vram_total");
|
|
36
|
-
if (paths.length === 0) {
|
|
37
|
-
return 0;
|
|
38
|
-
}
|
|
39
|
-
const totalBytes = paths
|
|
40
|
-
.map((path) => (0, node_fs_1.readFileSync)(path, "utf8").trim())
|
|
41
|
-
.map((value) => Number(value))
|
|
42
|
-
.filter((value) => Number.isFinite(value) && value > 0)
|
|
43
|
-
.reduce((sum, value) => sum + value, 0);
|
|
44
|
-
return totalBytes > 0 ? roundOne(totalBytes / (1024 ** 3)) : 0;
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return 0;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function getModelsDir() {
|
|
51
|
-
const override = process.env["YIPS_MODELS_DIR"]?.trim();
|
|
52
|
-
if (override && override.length > 0) {
|
|
53
|
-
return override;
|
|
54
|
-
}
|
|
55
|
-
return (0, node_path_1.join)((0, node_os_1.homedir)(), ".yips", "models");
|
|
56
|
-
}
|
|
57
|
-
function getDiskFreeGb(path) {
|
|
58
|
-
try {
|
|
59
|
-
const fsStats = (0, node_fs_3.statfsSync)(path);
|
|
60
|
-
const blockSize = Number(fsStats.bsize);
|
|
61
|
-
const available = Number(fsStats.bavail);
|
|
62
|
-
if (!Number.isFinite(blockSize) || !Number.isFinite(available) || blockSize <= 0 || available < 0) {
|
|
63
|
-
return 0;
|
|
64
|
-
}
|
|
65
|
-
return roundOne((blockSize * available) / (1024 ** 3));
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return 0;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
let cachedSpecs = null;
|
|
72
|
-
function getSystemSpecs() {
|
|
73
|
-
if (cachedSpecs) {
|
|
74
|
-
return cachedSpecs;
|
|
75
|
-
}
|
|
76
|
-
const ramGb = getRamGb();
|
|
77
|
-
const nvidiaVramGb = getNvidiaVramGb();
|
|
78
|
-
const amdVramGb = nvidiaVramGb > 0 ? 0 : getAmdVramGb();
|
|
79
|
-
const vramGb = nvidiaVramGb > 0 ? nvidiaVramGb : amdVramGb;
|
|
80
|
-
const gpuType = nvidiaVramGb > 0 ? "nvidia" : amdVramGb > 0 ? "amd" : "unknown";
|
|
81
|
-
cachedSpecs = {
|
|
82
|
-
ramGb,
|
|
83
|
-
vramGb,
|
|
84
|
-
totalMemoryGb: roundOne(ramGb + vramGb),
|
|
85
|
-
diskFreeGb: getDiskFreeGb(getModelsDir()),
|
|
86
|
-
gpuType
|
|
87
|
-
};
|
|
88
|
-
return cachedSpecs;
|
|
89
|
-
}
|
|
90
|
-
function clearSystemSpecsCache() {
|
|
91
|
-
cachedSpecs = null;
|
|
92
|
-
}
|
package/dist/hooks.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatHookFailure = formatHookFailure;
|
|
4
|
-
exports.runHook = runHook;
|
|
5
|
-
const node_child_process_1 = require("node:child_process");
|
|
6
|
-
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
7
|
-
const MAX_TIMEOUT_MS = 120_000;
|
|
8
|
-
const SHUTDOWN_GRACE_MS = 500;
|
|
9
|
-
function resolveHookCommand(config, hook) {
|
|
10
|
-
const configured = config.hooks[hook]?.command;
|
|
11
|
-
if (typeof configured !== "string") {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
const trimmed = configured.trim();
|
|
15
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
16
|
-
}
|
|
17
|
-
function resolveHookTimeoutMs(config, hook) {
|
|
18
|
-
const configured = config.hooks[hook]?.timeoutMs;
|
|
19
|
-
if (typeof configured !== "number" || !Number.isInteger(configured) || configured <= 0) {
|
|
20
|
-
return DEFAULT_TIMEOUT_MS;
|
|
21
|
-
}
|
|
22
|
-
return Math.min(configured, MAX_TIMEOUT_MS);
|
|
23
|
-
}
|
|
24
|
-
function createEventId() {
|
|
25
|
-
return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
26
|
-
}
|
|
27
|
-
function toErrorMessage(error) {
|
|
28
|
-
return error instanceof Error ? error.message : String(error);
|
|
29
|
-
}
|
|
30
|
-
function extractFilePath(payload) {
|
|
31
|
-
const path = payload["path"];
|
|
32
|
-
if (typeof path === "string" && path.trim().length > 0) {
|
|
33
|
-
return path.trim();
|
|
34
|
-
}
|
|
35
|
-
const filePath = payload["filePath"];
|
|
36
|
-
if (typeof filePath === "string" && filePath.trim().length > 0) {
|
|
37
|
-
return filePath.trim();
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
function formatHookFailure(result) {
|
|
42
|
-
const base = `[hook:${result.hook}] ${result.message}`;
|
|
43
|
-
if (result.status === "timeout") {
|
|
44
|
-
return base;
|
|
45
|
-
}
|
|
46
|
-
if (result.exitCode !== null) {
|
|
47
|
-
return `${base} (exit ${result.exitCode})`;
|
|
48
|
-
}
|
|
49
|
-
return base;
|
|
50
|
-
}
|
|
51
|
-
async function runHook(config, hook, payload, context = {}) {
|
|
52
|
-
const cwd = context.cwd ?? process.cwd();
|
|
53
|
-
const eventId = createEventId();
|
|
54
|
-
const timestamp = new Date().toISOString();
|
|
55
|
-
const command = resolveHookCommand(config, hook);
|
|
56
|
-
if (!command) {
|
|
57
|
-
return {
|
|
58
|
-
hook,
|
|
59
|
-
status: "skipped",
|
|
60
|
-
command: null,
|
|
61
|
-
cwd,
|
|
62
|
-
message: `No hook configured for ${hook}.`,
|
|
63
|
-
durationMs: 0,
|
|
64
|
-
eventId,
|
|
65
|
-
timestamp,
|
|
66
|
-
stdout: "",
|
|
67
|
-
stderr: "",
|
|
68
|
-
exitCode: null,
|
|
69
|
-
signal: null,
|
|
70
|
-
timedOut: false
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
const timeoutMs = resolveHookTimeoutMs(config, hook);
|
|
74
|
-
const filePath = extractFilePath(payload);
|
|
75
|
-
const startedAt = Date.now();
|
|
76
|
-
const envelope = {
|
|
77
|
-
hook,
|
|
78
|
-
eventId,
|
|
79
|
-
timestamp,
|
|
80
|
-
cwd,
|
|
81
|
-
sessionName: context.sessionName ?? null,
|
|
82
|
-
data: payload
|
|
83
|
-
};
|
|
84
|
-
return await new Promise((resolveResult) => {
|
|
85
|
-
let stdout = "";
|
|
86
|
-
let stderr = "";
|
|
87
|
-
let settled = false;
|
|
88
|
-
let timedOut = false;
|
|
89
|
-
let killTimer = null;
|
|
90
|
-
const child = (0, node_child_process_1.spawn)("sh", ["-lc", command], {
|
|
91
|
-
cwd,
|
|
92
|
-
env: {
|
|
93
|
-
...process.env,
|
|
94
|
-
...context.env,
|
|
95
|
-
YIPS_HOOK_NAME: hook,
|
|
96
|
-
YIPS_HOOK_EVENT_ID: eventId,
|
|
97
|
-
YIPS_HOOK_TIMESTAMP: timestamp,
|
|
98
|
-
YIPS_HOOK_CWD: cwd,
|
|
99
|
-
YIPS_HOOK_SESSION_NAME: context.sessionName ?? "",
|
|
100
|
-
YIPS_HOOK_FILE_PATH: filePath ?? ""
|
|
101
|
-
},
|
|
102
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
103
|
-
});
|
|
104
|
-
const settle = (result) => {
|
|
105
|
-
if (settled) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
settled = true;
|
|
109
|
-
if (killTimer) {
|
|
110
|
-
clearTimeout(killTimer);
|
|
111
|
-
}
|
|
112
|
-
resolveResult({
|
|
113
|
-
hook,
|
|
114
|
-
eventId,
|
|
115
|
-
timestamp,
|
|
116
|
-
cwd,
|
|
117
|
-
...result
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
child.stdout.on("data", (chunk) => {
|
|
121
|
-
stdout += chunk.toString("utf8");
|
|
122
|
-
});
|
|
123
|
-
child.stderr.on("data", (chunk) => {
|
|
124
|
-
stderr += chunk.toString("utf8");
|
|
125
|
-
});
|
|
126
|
-
child.on("error", (error) => {
|
|
127
|
-
settle({
|
|
128
|
-
status: "error",
|
|
129
|
-
command,
|
|
130
|
-
message: `Hook execution failed: ${toErrorMessage(error)}`,
|
|
131
|
-
durationMs: Math.max(0, Date.now() - startedAt),
|
|
132
|
-
stdout,
|
|
133
|
-
stderr,
|
|
134
|
-
exitCode: null,
|
|
135
|
-
signal: null,
|
|
136
|
-
timedOut
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
child.on("close", (code, signal) => {
|
|
140
|
-
if (timedOut) {
|
|
141
|
-
settle({
|
|
142
|
-
status: "timeout",
|
|
143
|
-
command,
|
|
144
|
-
message: `Hook timed out after ${timeoutMs}ms.`,
|
|
145
|
-
durationMs: Math.max(0, Date.now() - startedAt),
|
|
146
|
-
stdout,
|
|
147
|
-
stderr,
|
|
148
|
-
exitCode: code,
|
|
149
|
-
signal,
|
|
150
|
-
timedOut: true
|
|
151
|
-
});
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const success = code === 0;
|
|
155
|
-
settle({
|
|
156
|
-
status: success ? "ok" : "error",
|
|
157
|
-
command,
|
|
158
|
-
message: success ? "Hook completed successfully." : "Hook exited with a non-zero status.",
|
|
159
|
-
durationMs: Math.max(0, Date.now() - startedAt),
|
|
160
|
-
stdout,
|
|
161
|
-
stderr,
|
|
162
|
-
exitCode: code,
|
|
163
|
-
signal,
|
|
164
|
-
timedOut: false
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
killTimer = setTimeout(() => {
|
|
168
|
-
if (settled) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
timedOut = true;
|
|
172
|
-
child.kill("SIGTERM");
|
|
173
|
-
setTimeout(() => {
|
|
174
|
-
if (!settled) {
|
|
175
|
-
child.kill("SIGKILL");
|
|
176
|
-
}
|
|
177
|
-
}, SHUTDOWN_GRACE_MS);
|
|
178
|
-
}, timeoutMs);
|
|
179
|
-
const stdinPayload = `${JSON.stringify(envelope)}\n`;
|
|
180
|
-
child.stdin.write(stdinPayload, "utf8", (error) => {
|
|
181
|
-
if (error) {
|
|
182
|
-
stderr += `stdin write failed: ${toErrorMessage(error)}\n`;
|
|
183
|
-
}
|
|
184
|
-
child.stdin.end();
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
}
|
package/dist/index.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.main = main;
|
|
4
|
-
const node_process_1 = require("node:process");
|
|
5
|
-
const config_1 = require("./config");
|
|
6
|
-
const repl_1 = require("./repl");
|
|
7
|
-
const tui_1 = require("./tui");
|
|
8
|
-
function isTTY() {
|
|
9
|
-
return Boolean(node_process_1.stdin.isTTY && node_process_1.stdout.isTTY);
|
|
10
|
-
}
|
|
11
|
-
function hasFlag(flag) {
|
|
12
|
-
return process.argv.includes(flag);
|
|
13
|
-
}
|
|
14
|
-
async function main() {
|
|
15
|
-
for (;;) {
|
|
16
|
-
const configResult = await (0, config_1.loadConfig)();
|
|
17
|
-
if (configResult.warning) {
|
|
18
|
-
console.error(`[warning] ${configResult.warning}`);
|
|
19
|
-
}
|
|
20
|
-
const result = hasFlag("--no-tui") || !isTTY()
|
|
21
|
-
? await (0, repl_1.startRepl)({ config: configResult.config })
|
|
22
|
-
: await (0, tui_1.startTui)({ config: configResult.config });
|
|
23
|
-
if (result !== "restart") {
|
|
24
|
-
break;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (require.main === module) {
|
|
29
|
-
void main().catch((error) => {
|
|
30
|
-
const message = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
31
|
-
console.error(`[fatal] ${message}`);
|
|
32
|
-
process.exitCode = 1;
|
|
33
|
-
});
|
|
34
|
-
}
|