glitool 2.0.2 → 2.0.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.js +21 -6
- package/dist/agents/coder.js +8 -1
- package/dist/agents/explainer.js +10 -6
- package/dist/agents/judge.js +2 -2
- package/dist/agents/planner.js +23 -8
- package/dist/agents/planningAgent.js +19 -4
- package/dist/agents/reviewer-agent.js +12 -16
- package/dist/llm/classifier.js +8 -1
- package/dist/memory.js +8 -1
- package/dist/projectMemory.js +24 -9
- package/dist/ui/App.js +1 -1
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -59,14 +59,29 @@ function buildSystemPrompt() {
|
|
|
59
59
|
summary = loadSummary();
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
let prompt = `You are an
|
|
62
|
+
let prompt = `You are Glitool — an AI coding assistant running in the user's terminal.
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
64
|
+
You can:
|
|
65
|
+
- Have a normal conversation (just respond, no tools needed)
|
|
66
|
+
- Answer programming and general questions
|
|
67
|
+
- Read, write, edit, and search files in the user's project
|
|
68
|
+
- Run shell commands, fetch web pages
|
|
69
|
+
- Plan, review, refactor, debug code, and help with git
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
Be concise. Default to plain conversation. Only call tools when the request clearly needs them.
|
|
72
|
+
|
|
73
|
+
When the user asks to read, show, or display a specific file → call readFile.
|
|
74
|
+
For "read <name>" shorthand, pass the bare name; the tool searches the project automatically.
|
|
75
|
+
Don't claim a file is missing without verifying via listFiles or readFile first.
|
|
76
|
+
|
|
77
|
+
If any tool returns USER_CANCELLED, stop immediately and tell the user. Never retry a cancelled operation.
|
|
78
|
+
|
|
79
|
+
Style:
|
|
80
|
+
- No preamble like "Sure!", "Of course!", "I'd be happy to..."
|
|
81
|
+
- Code blocks use language tags: \`\`\`ts, \`\`\`py, \`\`\`bash
|
|
82
|
+
- File references use backticks: \`src/auth.ts:42\`
|
|
83
|
+
- The user's current working directory IS the project they're working on — file paths are relative to it.
|
|
84
|
+
`;
|
|
70
85
|
if (summary) {
|
|
71
86
|
const capped = summary.length > MAX_SUMMARY_CHARS
|
|
72
87
|
? summary.slice(0, MAX_SUMMARY_CHARS) + '\n…[summary truncated]'
|
package/dist/agents/coder.js
CHANGED
|
@@ -22,7 +22,14 @@ GROUNDING RULES — these are not optional:
|
|
|
22
22
|
6. Maximum 5 file reads per task. If you need more, you're doing it wrong — use searchCode instead.
|
|
23
23
|
7. If you can't safely complete the task, STOP and return a failure message. Do not invent.
|
|
24
24
|
|
|
25
|
-
Be surgical, not exhaustive. Most tasks need 2-4 tool calls, not 15. The validator will catch broken output — you don't need to over-verify
|
|
25
|
+
Be surgical, not exhaustive. Most tasks need 2-4 tool calls, not 15. The validator will catch broken output — you don't need to over-verify.
|
|
26
|
+
|
|
27
|
+
Response style:
|
|
28
|
+
- Your final text should be 1-3 sentences summarizing what files you changed and why.
|
|
29
|
+
- Do NOT paste file contents in the response — the files are on disk; the user can read them.
|
|
30
|
+
- The validator runs tsc + ESLint after you finish — no need to verify those yourself.
|
|
31
|
+
- If a step is impossible (binary file, command blocked, etc.), say so explicitly and stop.
|
|
32
|
+
`)
|
|
26
33
|
});
|
|
27
34
|
const stream = await coderAgent.stream({ messages: [new HumanMessage(`Plan to execute:\n${plan}\n\nOriginal request: ${userMessage}`)] }, { recursionLimit: 60, streamMode: 'updates' });
|
|
28
35
|
let result = '';
|
package/dist/agents/explainer.js
CHANGED
|
@@ -5,12 +5,16 @@ export async function explainResponse(response) {
|
|
|
5
5
|
return '';
|
|
6
6
|
const explainerLlm = makeLlm('meta-llama/Llama-3.3-70B-Instruct-Turbo');
|
|
7
7
|
const result = await explainerLlm.invoke([
|
|
8
|
-
new SystemMessage(`You are a coding teacher.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
new SystemMessage(`You are a friendly coding teacher.
|
|
9
|
+
|
|
10
|
+
Given what an AI coding assistant just did (described below), explain it in 2-4 simple sentences that a beginner would understand.
|
|
11
|
+
|
|
12
|
+
Focus on:
|
|
13
|
+
- WHAT changed and WHY
|
|
14
|
+
- WHICH concept was used (e.g., "promise chaining", "dependency injection")
|
|
15
|
+
- ONE thing to learn next
|
|
16
|
+
|
|
17
|
+
Tone: encouraging, plain language, define any jargon used.`),
|
|
14
18
|
new HumanMessage(`What was just done:\n${response}`)
|
|
15
19
|
]);
|
|
16
20
|
return result.content;
|
package/dist/agents/judge.js
CHANGED
|
@@ -23,7 +23,7 @@ IMPORTANT — how the coder works:
|
|
|
23
23
|
Return JSON only:
|
|
24
24
|
{
|
|
25
25
|
"verdict": "ok" or "fail",
|
|
26
|
-
|
|
26
|
+
"failure_point": "plan" | "workflow" | "execution" | "final_output" | null,
|
|
27
27
|
"failure_step_id": number or null,
|
|
28
28
|
"reason": "short explanation",
|
|
29
29
|
"fix_hint": "specific instruction to fix the problem, empty if ok",
|
|
@@ -34,7 +34,7 @@ Return JSON only:
|
|
|
34
34
|
failure_point meanings:
|
|
35
35
|
- "plan": the plan itself was wrong or incomplete — needs replanning
|
|
36
36
|
- "workflow": wrong execution order caused the failure
|
|
37
|
-
- "
|
|
37
|
+
- "execution": a specific step failed — use failure_step_id
|
|
38
38
|
- "final_output": code runs but doesn't meet the requirement
|
|
39
39
|
- null: everything ok, verdict must be ok`),
|
|
40
40
|
new HumanMessage(`User request: ${input.userMessage}\n\n` +
|
package/dist/agents/planner.js
CHANGED
|
@@ -5,15 +5,30 @@ export async function runPlanner(userMessage, context, model) {
|
|
|
5
5
|
const response = await llm.invoke([
|
|
6
6
|
new SystemMessage(`You are a coding task planner. Output a structured JSON plan.
|
|
7
7
|
|
|
8
|
+
Output exactly one of:
|
|
9
|
+
|
|
10
|
+
A) The literal text: SIMPLE
|
|
11
|
+
(use when the task is just a question, explanation, or chat — no file changes or code execution needed)
|
|
12
|
+
|
|
13
|
+
B) A JSON array of 3-6 steps:
|
|
14
|
+
[
|
|
15
|
+
{ "id": 1, "action": "read", "target": "src/auth.ts", "depends_on": [], "why": "understand current login flow" },
|
|
16
|
+
{ "id": 2, "action": "edit", "target": "src/auth.ts", "depends_on": [1], "why": "add refresh-token check before validate" },
|
|
17
|
+
{ "id": 3, "action": "run", "target": "npx tsc --noEmit","depends_on": [2], "why": "verify it compiles" }
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
Action values:
|
|
21
|
+
- "read": open a file to understand it
|
|
22
|
+
- "edit": modify an existing file
|
|
23
|
+
- "create": make a new file
|
|
24
|
+
- "run": execute a shell command (tsc, npm, git, etc.)
|
|
25
|
+
- "search": grep the codebase
|
|
26
|
+
|
|
8
27
|
Rules:
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
- Be specific about
|
|
13
|
-
- Do NOT write any code — only plan the steps
|
|
14
|
-
- Keep it to 3-6 steps maximum
|
|
15
|
-
- Steps that can run independently should have no shared depends_on
|
|
16
|
-
- depends_on contains the ids of steps that must finish before this one`),
|
|
28
|
+
- Output ONLY the SIMPLE literal OR the JSON array. No prose, no markdown, no code fences.
|
|
29
|
+
- Steps that can run in parallel: leave depends_on empty.
|
|
30
|
+
- Sequential dependencies: list step ids in depends_on.
|
|
31
|
+
- Be specific about file paths and command names — vague targets cause failures.`),
|
|
17
32
|
new HumanMessage(`Context:\n${context}\n\nUser request: ${userMessage}`)
|
|
18
33
|
]);
|
|
19
34
|
const content = response.content.trim();
|
|
@@ -5,10 +5,26 @@ import { join } from "path";
|
|
|
5
5
|
const PLAN_FILE = "plan.md";
|
|
6
6
|
const BLOCKED_EXTENSIONS = ['.ts', '.js', '.tsx', '.jsx', '.py', '.go', '.rs'];
|
|
7
7
|
export async function runPlanningAgent(userMessage, onUsage) {
|
|
8
|
-
const llm = makeLlm('
|
|
8
|
+
const llm = makeLlm('openai/gpt-oss-120b');
|
|
9
9
|
const planPath = join(process.cwd(), PLAN_FILE);
|
|
10
10
|
const existingPlan = existsSync(planPath) ? readFileSync(planPath, 'utf-8') : null;
|
|
11
|
-
const systemPrompt = existingPlan
|
|
11
|
+
const systemPrompt = existingPlan
|
|
12
|
+
? `You are a planning assistant. The user has an existing plan.md and wants to update it.
|
|
13
|
+
|
|
14
|
+
You receive: (1) the current plan, (2) the user's change request.
|
|
15
|
+
|
|
16
|
+
OUTPUT:
|
|
17
|
+
- The FULL updated plan in Markdown — this overwrites plan.md.
|
|
18
|
+
- After the plan, write exactly "---" on its own line.
|
|
19
|
+
- Then 1-3 bullets summarising what changed.
|
|
20
|
+
|
|
21
|
+
RULES:
|
|
22
|
+
- Preserve sections the user didn't ask to change.
|
|
23
|
+
- Apply requested changes precisely; don't expand scope.
|
|
24
|
+
- If the request is ambiguous, ask ONE clarifying question instead of guessing.
|
|
25
|
+
- Never delete existing sections unless the user explicitly says to.
|
|
26
|
+
- Avoid writing implementation code; this is planning, not execution.`
|
|
27
|
+
: `You are a planning assistant. Create a clear structured plan based on user's request.
|
|
12
28
|
|
|
13
29
|
BEFORE writing a plan:
|
|
14
30
|
- Look at the user's request and identify the key feature names, file paths, or concepts mentioned.
|
|
@@ -21,8 +37,7 @@ Rules:
|
|
|
21
37
|
- Use Markdown with clear sections and numbered steps
|
|
22
38
|
- Be specific: name files, components, decisions, trade-offs
|
|
23
39
|
- If the request is vague, prefer asking 1-2 clarifying questions over guessing
|
|
24
|
-
- After the plan, write exactly "---" on its own line, then 1-3 bullet points summarising what you created
|
|
25
|
-
`;
|
|
40
|
+
- After the plan, write exactly "---" on its own line, then 1-3 bullet points summarising what you created`;
|
|
26
41
|
const userContent = existingPlan ? `Current plan:\n\n${existingPlan}\n\nUser request:${userMessage}` : userMessage;
|
|
27
42
|
const response = await llm.invoke([
|
|
28
43
|
new SystemMessage(systemPrompt),
|
|
@@ -27,33 +27,29 @@ Workflow:
|
|
|
27
27
|
2. Run \`npx tsc --noEmit\` via the bash tool and capture type errors.
|
|
28
28
|
3. Run \`npx eslint <changed-files>\` via the bash tool (skip if eslint isn't configured).
|
|
29
29
|
4. Read the files. Combine static-analysis output with your own reading.
|
|
30
|
-
5. Return a
|
|
30
|
+
5. Return a plain-text report (terminal-friendly, NO markdown):
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
SUMMARY
|
|
33
33
|
<one or two sentences — overall health>
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
### CRITICAL
|
|
35
|
+
CRITICAL
|
|
38
36
|
- file.ts:LINE — what is wrong and why it matters
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
WARNING
|
|
41
39
|
- file.ts:LINE — what is wrong and how to think about it
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
SUGGESTION
|
|
44
42
|
- file.ts:LINE — small improvement
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
GOOD
|
|
47
45
|
- one or two things the code does well
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
- Each issue: filename:LINE — one sentence max.
|
|
56
|
-
- Total response: 25 lines maximum. Cut low-value suggestions if needed to stay under.`;
|
|
47
|
+
FORMAT RULES:
|
|
48
|
+
- No ##, ###, **bold**, *italic*. Plain text only.
|
|
49
|
+
- Each issue: one line, exactly "filename:LINE — single sentence".
|
|
50
|
+
- If a section has no items, write "none" under the label.
|
|
51
|
+
- Total response: 25 lines maximum. Cut low-value suggestions to stay under.
|
|
52
|
+
`;
|
|
57
53
|
export async function runReviewer(userMessage, onToolCall, model) {
|
|
58
54
|
const llm = makeLlm(model);
|
|
59
55
|
const tools = [listFilesTool, readFileTool, searchCodeTool, bashTool];
|
package/dist/llm/classifier.js
CHANGED
|
@@ -41,7 +41,14 @@ Tie-breakers:
|
|
|
41
41
|
- starts with the literal word "git" → git
|
|
42
42
|
- short greeting or opinion question → chat
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
Confidence guide:
|
|
45
|
+
- "high": user's intent is unambiguous from this single message; pattern + verb both point one way.
|
|
46
|
+
- "low": message is short or uses pronouns ("this", "it", "that"), or could plausibly fit 2+ domains, or relies on context the history doesn't fully clarify.
|
|
47
|
+
|
|
48
|
+
Return JSON: {"domain":"<domain>","confidence":"high" or "low", "reason":"<one sentence>"}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
`),
|
|
45
52
|
new HumanMessage(history ? `Conversation so far:\n${history}\n\nNew message: ${prompt}` : `Message: ${prompt}`)
|
|
46
53
|
], { timeout: 3000 });
|
|
47
54
|
const raw = typeof response.content === 'string' ? response.content : '';
|
package/dist/memory.js
CHANGED
|
@@ -79,7 +79,14 @@ export async function generateAndSaveSummary(messages, llm) {
|
|
|
79
79
|
if (!readable.trim())
|
|
80
80
|
return;
|
|
81
81
|
const response = await llm.invoke([
|
|
82
|
-
new SystemMessage('
|
|
82
|
+
new SystemMessage(`You're writing a brief for the next coding session. The user will return to this project days or weeks later and need fast context recall.
|
|
83
|
+
|
|
84
|
+
In 2-3 sentences, summarize:
|
|
85
|
+
- What was built or changed (be specific: file paths, function names)
|
|
86
|
+
- Key decisions made (e.g., "chose JWT over sessions", "Postgres over Mongo")
|
|
87
|
+
- Likely next step
|
|
88
|
+
|
|
89
|
+
Avoid generic phrases like "we worked on the project". Cite specifics.`),
|
|
83
90
|
new HumanMessage(readable)
|
|
84
91
|
]);
|
|
85
92
|
const hash = crypto.createHash('md5').update(process.cwd()).digest('hex').slice(0, 8);
|
package/dist/projectMemory.js
CHANGED
|
@@ -29,15 +29,30 @@ export async function extractAndSaveProjectMemory(messages, llm) {
|
|
|
29
29
|
return;
|
|
30
30
|
const existing = loadProjectMemory();
|
|
31
31
|
const response = await llm.invoke([
|
|
32
|
-
new SystemMessage(`Extract structured project facts from this conversation.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
new SystemMessage(`Extract structured project facts from this conversation.
|
|
33
|
+
|
|
34
|
+
OUTPUT REQUIREMENTS:
|
|
35
|
+
- Valid JSON ONLY. No markdown, no code fences, no prose.
|
|
36
|
+
- Exactly this shape:
|
|
37
|
+
{
|
|
38
|
+
"techStack": ["TypeScript", "Express", "MongoDB"],
|
|
39
|
+
"architectureDecisions": ["use JWT not sessions", "Mongo over Postgres for prototyping"],
|
|
40
|
+
"todos": ["add password reset", "wire Stripe webhooks"],
|
|
41
|
+
"lastUpdated": "${new Date().toISOString()}"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
EXTRACTION RULES:
|
|
45
|
+
- techStack: only languages/frameworks/libraries that were USED or CHOSEN — not briefly mentioned and discarded.
|
|
46
|
+
- architectureDecisions: concrete choices ("use JWT for auth"), not vague phrases ("we'll handle auth").
|
|
47
|
+
- todos: actual next steps mentioned, not aspirational tangents.
|
|
48
|
+
|
|
49
|
+
${existing ? `MERGE WITH EXISTING:
|
|
50
|
+
- techStack: union (no duplicates).
|
|
51
|
+
- architectureDecisions: append new, keep old unless contradicted.
|
|
52
|
+
- todos: keep old unless explicitly completed in this conversation.
|
|
53
|
+
|
|
54
|
+
Existing memory:
|
|
55
|
+
${JSON.stringify(existing, null, 2)}` : ''}`),
|
|
41
56
|
new HumanMessage(readable)
|
|
42
57
|
]);
|
|
43
58
|
try {
|
package/dist/ui/App.js
CHANGED
|
@@ -336,7 +336,7 @@ export const App = ({ explainMode = false }) => {
|
|
|
336
336
|
"You've used your 5 free requests.",
|
|
337
337
|
'',
|
|
338
338
|
'Sign in with GitHub — free, 50 requests/month:',
|
|
339
|
-
'
|
|
339
|
+
' → https://glit.in/activate',
|
|
340
340
|
'',
|
|
341
341
|
'Type /signup to start the sign-in flow in your terminal.',
|
|
342
342
|
].join('\n'),
|