@llmtune/cli 0.1.1 → 0.1.3
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/loop.js +4 -2
- package/dist/context/agent-identity.d.ts +6 -0
- package/dist/context/agent-identity.js +33 -0
- package/dist/context/builder.d.ts +1 -0
- package/dist/context/builder.js +24 -12
- package/dist/context/git-context.js +26 -36
- package/dist/index.js +2 -1
- package/dist/repl/repl.js +5 -2
- package/dist/tools/tools/web-fetch.js +2 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.js +9 -0
- package/package.json +1 -1
package/dist/agent/loop.js
CHANGED
|
@@ -19,7 +19,9 @@ async function runAgentLoop(client, conversation, registry, userInput, config, o
|
|
|
19
19
|
parameters: spec.inputSchema,
|
|
20
20
|
},
|
|
21
21
|
}));
|
|
22
|
-
const contextResult = await (0, builder_1.buildContextPrompt)(config.workspaceRoot, config.cwd
|
|
22
|
+
const contextResult = await (0, builder_1.buildContextPrompt)(config.workspaceRoot, config.cwd, {
|
|
23
|
+
model: config.model,
|
|
24
|
+
});
|
|
23
25
|
const contextPrompt = contextResult.prompt;
|
|
24
26
|
let totalToolCalls = 0;
|
|
25
27
|
let totalTokensIn = 0;
|
|
@@ -136,7 +138,7 @@ async function runAgentLoop(client, conversation, registry, userInput, config, o
|
|
|
136
138
|
workspaceRoot: config.workspaceRoot,
|
|
137
139
|
cwd: config.cwd,
|
|
138
140
|
};
|
|
139
|
-
const result = await registry.
|
|
141
|
+
const result = await registry.dispatchAsync(tc.function.name, toolInput, toolCtx);
|
|
140
142
|
if (result.isError) {
|
|
141
143
|
console.log(chalk_1.default.red(` ✗ ${tc.function.name}: ${String(result.output).slice(0, 200)}`));
|
|
142
144
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAgentIdentitySection = buildAgentIdentitySection;
|
|
4
|
+
const version_1 = require("../version");
|
|
5
|
+
/**
|
|
6
|
+
* Core agent identity — prepended to every system prompt so the model
|
|
7
|
+
* identifies as LLMTune Agent, not Claude/ChatGPT/etc.
|
|
8
|
+
*/
|
|
9
|
+
function buildAgentIdentitySection(model) {
|
|
10
|
+
const modelLine = model ? `- Model: ${model} (via llmtune.io)` : "- Models served through llmtune.io (e.g. GLM-5.1)";
|
|
11
|
+
return [
|
|
12
|
+
"# LLMTune Agent",
|
|
13
|
+
"",
|
|
14
|
+
"You are the **LLMTune Agent** — an AI coding assistant from [llmtune.io](https://llmtune.io).",
|
|
15
|
+
"",
|
|
16
|
+
"## Identity (always follow)",
|
|
17
|
+
`- You are **LLMTune Agent**, running in the LLMTune CLI (v${version_1.CLI_VERSION}).`,
|
|
18
|
+
"- You are **not** Claude, ChatGPT, Copilot, Cursor, or any product from Anthropic, OpenAI, or Microsoft.",
|
|
19
|
+
"- When asked who you are, say you are the LLMTune Agent powered by llmtune.io. Never claim another brand or company.",
|
|
20
|
+
modelLine,
|
|
21
|
+
"",
|
|
22
|
+
"## How you work",
|
|
23
|
+
"- You run locally on the user's machine through `llmtune chat`.",
|
|
24
|
+
"- You use tools (read, write, edit, bash, glob, grep, web-fetch) to act on the workspace.",
|
|
25
|
+
"- Follow project instructions in LLMTUNE.md or CLAUDE.md when present.",
|
|
26
|
+
"",
|
|
27
|
+
"## Behavior",
|
|
28
|
+
"- Be concise, direct, and helpful.",
|
|
29
|
+
"- Use tools to investigate and make changes — do not only describe what you would do.",
|
|
30
|
+
"- Stay on the user's task; do not ask them to remind you unless context was explicitly compacted.",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=agent-identity.js.map
|
|
@@ -9,5 +9,6 @@ export declare function readCache(cacheKey: string): ContextResult | null;
|
|
|
9
9
|
export declare function writeCache(cacheKey: string, result: ContextResult): void;
|
|
10
10
|
export declare function buildContextPrompt(workspaceRoot: string, cwd: string, options?: {
|
|
11
11
|
useCache?: boolean;
|
|
12
|
+
model?: string;
|
|
12
13
|
}): Promise<ContextResult>;
|
|
13
14
|
//# sourceMappingURL=builder.d.ts.map
|
package/dist/context/builder.js
CHANGED
|
@@ -43,6 +43,7 @@ const fs = __importStar(require("fs"));
|
|
|
43
43
|
const git_context_1 = require("./git-context");
|
|
44
44
|
const workspace_1 = require("./workspace");
|
|
45
45
|
const llmtune_md_1 = require("./llmtune-md");
|
|
46
|
+
const agent_identity_1 = require("./agent-identity");
|
|
46
47
|
const CACHE_DIR = () => {
|
|
47
48
|
const base = process.env.LLMTUNE_CACHE_DIR || path.join(process.env.HOME || process.env.USERPROFILE || "~", ".llmtune", "cache");
|
|
48
49
|
return base;
|
|
@@ -86,36 +87,47 @@ function writeCache(cacheKey, result) {
|
|
|
86
87
|
}
|
|
87
88
|
async function buildContextPrompt(workspaceRoot, cwd, options) {
|
|
88
89
|
const cacheKey = computeCacheKey(workspaceRoot, cwd);
|
|
90
|
+
const identity = (0, agent_identity_1.buildAgentIdentitySection)(options?.model);
|
|
91
|
+
let workspaceSections = [];
|
|
89
92
|
if (options?.useCache !== false) {
|
|
90
93
|
const cached = readCache(cacheKey);
|
|
91
|
-
if (cached)
|
|
92
|
-
|
|
94
|
+
if (cached) {
|
|
95
|
+
workspaceSections = cached.sections;
|
|
96
|
+
return {
|
|
97
|
+
prompt: [identity, ...workspaceSections].filter(Boolean).join("\n\n"),
|
|
98
|
+
cacheKey,
|
|
99
|
+
cacheHit: true,
|
|
100
|
+
sections: [identity, ...workspaceSections],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
93
103
|
}
|
|
94
|
-
const sections = [];
|
|
95
104
|
// Workspace section (async)
|
|
96
105
|
const workspace = await (0, workspace_1.buildWorkspaceSnapshot)(workspaceRoot, cwd);
|
|
97
106
|
const workspaceSection = (0, workspace_1.renderWorkspaceSection)(workspace);
|
|
98
107
|
if (workspaceSection)
|
|
99
|
-
|
|
108
|
+
workspaceSections.push(workspaceSection);
|
|
100
109
|
// Git section
|
|
101
110
|
const git = (0, git_context_1.collectGitContext)(workspaceRoot);
|
|
102
111
|
const gitSection = renderGitSection(git);
|
|
103
112
|
if (gitSection)
|
|
104
|
-
|
|
113
|
+
workspaceSections.push(gitSection);
|
|
105
114
|
// LLMTUNE.md / CLAUDE.md section
|
|
106
115
|
const mdFiles = (0, llmtune_md_1.loadProjectInstructions)(workspaceRoot, cwd);
|
|
107
116
|
const mdSection = renderMdSection(mdFiles, workspaceRoot);
|
|
108
117
|
if (mdSection)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
workspaceSections.push(mdSection);
|
|
119
|
+
writeCache(cacheKey, {
|
|
120
|
+
prompt: workspaceSections.join("\n\n"),
|
|
121
|
+
cacheKey,
|
|
122
|
+
cacheHit: false,
|
|
123
|
+
sections: workspaceSections,
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
prompt: [identity, ...workspaceSections].filter(Boolean).join("\n\n"),
|
|
113
127
|
cacheKey,
|
|
114
128
|
cacheHit: false,
|
|
115
|
-
sections,
|
|
129
|
+
sections: [identity, ...workspaceSections],
|
|
116
130
|
};
|
|
117
|
-
writeCache(cacheKey, result);
|
|
118
|
-
return result;
|
|
119
131
|
}
|
|
120
132
|
function renderGitSection(git) {
|
|
121
133
|
if (!git.available)
|
|
@@ -2,48 +2,38 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.collectGitContext = collectGitContext;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
|
-
function
|
|
5
|
+
function runGit(args, cwd) {
|
|
6
6
|
try {
|
|
7
|
-
const
|
|
8
|
-
cwd
|
|
9
|
-
encoding: "utf-8",
|
|
10
|
-
timeout: 5000,
|
|
11
|
-
}).trim();
|
|
12
|
-
if (!gitDir) {
|
|
13
|
-
return { available: false, repoRoot: null, branch: null, recentCommit: null, status: null };
|
|
14
|
-
}
|
|
15
|
-
const branch = (0, child_process_1.execSync)("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
|
|
16
|
-
cwd: gitDir,
|
|
7
|
+
const out = (0, child_process_1.execSync)(`git ${args}`, {
|
|
8
|
+
cwd,
|
|
17
9
|
encoding: "utf-8",
|
|
18
10
|
timeout: 5000,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
timeout: 5000,
|
|
24
|
-
}).trim();
|
|
25
|
-
let status = null;
|
|
26
|
-
try {
|
|
27
|
-
const raw = (0, child_process_1.execSync)("git status --short 2>/dev/null", {
|
|
28
|
-
cwd: gitDir,
|
|
29
|
-
encoding: "utf-8",
|
|
30
|
-
timeout: 5000,
|
|
31
|
-
}).trim();
|
|
32
|
-
if (raw) {
|
|
33
|
-
const lines = raw.split("\n").slice(0, 30);
|
|
34
|
-
status = lines.join("\n");
|
|
35
|
-
if (raw.split("\n").length > 30) {
|
|
36
|
-
status += `\n... ${raw.split("\n").length - 30} more files`;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
// status unavailable, non-critical
|
|
42
|
-
}
|
|
43
|
-
return { available: true, repoRoot: gitDir, branch, recentCommit, status };
|
|
11
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
12
|
+
});
|
|
13
|
+
const trimmed = out.trim();
|
|
14
|
+
return trimmed || null;
|
|
44
15
|
}
|
|
45
16
|
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function collectGitContext(workspaceRoot) {
|
|
21
|
+
const gitDir = runGit("rev-parse --show-toplevel", workspaceRoot);
|
|
22
|
+
if (!gitDir) {
|
|
46
23
|
return { available: false, repoRoot: null, branch: null, recentCommit: null, status: null };
|
|
47
24
|
}
|
|
25
|
+
const branch = runGit("rev-parse --abbrev-ref HEAD", gitDir);
|
|
26
|
+
const recentCommit = runGit("log -1 --oneline", gitDir);
|
|
27
|
+
let status = null;
|
|
28
|
+
const raw = runGit("status --short", gitDir);
|
|
29
|
+
if (raw) {
|
|
30
|
+
const lines = raw.split("\n").slice(0, 30);
|
|
31
|
+
status = lines.join("\n");
|
|
32
|
+
const total = raw.split("\n").length;
|
|
33
|
+
if (total > 30) {
|
|
34
|
+
status += `\n... ${total - 30} more files`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { available: true, repoRoot: gitDir, branch, recentCommit, status };
|
|
48
38
|
}
|
|
49
39
|
//# sourceMappingURL=git-context.js.map
|
package/dist/index.js
CHANGED
|
@@ -42,11 +42,12 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
42
42
|
const config_1 = require("./auth/config");
|
|
43
43
|
const client_1 = require("./auth/client");
|
|
44
44
|
const repl_1 = require("./repl/repl");
|
|
45
|
+
const version_1 = require("./version");
|
|
45
46
|
const program = new commander_1.Command();
|
|
46
47
|
program
|
|
47
48
|
.name("llmtune")
|
|
48
49
|
.description("AI CLI Agent powered by llmtune.io")
|
|
49
|
-
.version(
|
|
50
|
+
.version(version_1.CLI_VERSION);
|
|
50
51
|
program
|
|
51
52
|
.command("login")
|
|
52
53
|
.description("Configure API key and settings")
|
package/dist/repl/repl.js
CHANGED
|
@@ -52,11 +52,13 @@ const web_fetch_1 = require("../tools/tools/web-fetch");
|
|
|
52
52
|
const ask_user_1 = require("../tools/tools/ask-user");
|
|
53
53
|
const service_1 = require("../compact/service");
|
|
54
54
|
const analyzer_1 = require("../context/analyzer");
|
|
55
|
+
const builder_1 = require("../context/builder");
|
|
55
56
|
const loader_1 = require("../skills/loader");
|
|
56
57
|
const trust_1 = require("../skills/trust");
|
|
57
58
|
const service_2 = require("../memory/service");
|
|
58
59
|
const logger_1 = require("../telemetry/logger");
|
|
59
60
|
const config_1 = require("../auth/config");
|
|
61
|
+
const version_1 = require("../version");
|
|
60
62
|
const fs = __importStar(require("fs"));
|
|
61
63
|
const path = __importStar(require("path"));
|
|
62
64
|
const HELP_TEXT = `
|
|
@@ -106,7 +108,7 @@ async function startRepl(options) {
|
|
|
106
108
|
let currentModel = options.model;
|
|
107
109
|
let streamMode = options.stream;
|
|
108
110
|
let verbose = false;
|
|
109
|
-
console.log(chalk_1.default.cyan(`\nLLMTune CLI
|
|
111
|
+
console.log(chalk_1.default.cyan(`\nLLMTune CLI v${version_1.CLI_VERSION}`));
|
|
110
112
|
console.log(chalk_1.default.dim(`Model: ${currentModel}`));
|
|
111
113
|
console.log(chalk_1.default.dim(`Tools: ${registry.listSpecs().map((s) => s.name).join(", ")}`));
|
|
112
114
|
if (skillList.length > 0) {
|
|
@@ -255,8 +257,9 @@ async function handleCommand(input, ctx) {
|
|
|
255
257
|
console.log(chalk_1.default.green("Conversation cleared."));
|
|
256
258
|
break;
|
|
257
259
|
case "/context": {
|
|
260
|
+
const ctxResult = await (0, builder_1.buildContextPrompt)(ctx.cwd, ctx.cwd, { model: ctx.getModel() });
|
|
258
261
|
const analysis = (0, analyzer_1.analyzeContextUsage)({
|
|
259
|
-
systemPrompt:
|
|
262
|
+
systemPrompt: ctxResult.prompt,
|
|
260
263
|
toolSpecs: ctx.registry.listSpecs(),
|
|
261
264
|
messages: ctx.conversation.getApiMessages().map((m) => ({
|
|
262
265
|
role: m.role,
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.webFetchTool = void 0;
|
|
7
7
|
const https_1 = __importDefault(require("https"));
|
|
8
8
|
const http_1 = __importDefault(require("http"));
|
|
9
|
+
const version_1 = require("../../version");
|
|
9
10
|
const MAX_RESPONSE_SIZE = 500_000;
|
|
10
11
|
const TIMEOUT_MS = 30_000;
|
|
11
12
|
exports.webFetchTool = {
|
|
@@ -68,7 +69,7 @@ exports.webFetchTool = {
|
|
|
68
69
|
const req = lib.request(url, {
|
|
69
70
|
method,
|
|
70
71
|
headers: {
|
|
71
|
-
"User-Agent":
|
|
72
|
+
"User-Agent": `LLMTune-CLI/${version_1.CLI_VERSION}`,
|
|
72
73
|
Accept: "text/html,application/json,text/plain,*/*",
|
|
73
74
|
...headers,
|
|
74
75
|
},
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CLI_VERSION = void 0;
|
|
7
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
8
|
+
exports.CLI_VERSION = package_json_1.default.version;
|
|
9
|
+
//# sourceMappingURL=version.js.map
|