@ikyyofc/gemini-cli 4.0.8 → 4.0.9

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/agent.js +51 -41
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikyyofc/gemini-cli",
3
- "version": "4.0.8",
3
+ "version": "4.0.9",
4
4
  "description": "AI Agent CLI — native function calling · GEMINI.md context · extensions",
5
5
  "type": "module",
6
6
  "bin": { "gemini": "./index.js" },
package/src/agent.js CHANGED
@@ -1,9 +1,9 @@
1
- // src/agent.js — ReAct agent loop
1
+ // src/agent.js — ReAct agent loop with auto skill injection
2
2
  import chalk from "chalk";
3
3
  import { callGemini } from "./gemini.js";
4
4
  import { GEMINI_TOOLS, FUNCTION_DECLARATIONS, executeTool } from "./tools.js";
5
5
  import { Spinner } from "./utils/spinner.js";
6
- import { loadSkills, SKILLS_DIR } from "./skills.js";
6
+ import { loadSkills } from "./skills.js";
7
7
  import {
8
8
  printAssistant, printError, printWarning,
9
9
  printToolCall, printToolResult,
@@ -13,55 +13,61 @@ import {
13
13
  const TIMEOUT_MS = 10 * 60 * 1000;
14
14
 
15
15
  // ─────────────────────────────────────────────────────────────────
16
- // System prompt
16
+ // Auto-inject relevant skill content into conversation
17
+ // This happens BEFORE the first LLM call — model has no choice
18
+ // but to see and follow the skill instructions.
19
+ // ─────────────────────────────────────────────────────────────────
20
+ function injectSkills(userMessage, messages) {
21
+ const skills = loadSkills();
22
+ if (!skills.length) return messages;
23
+
24
+ const query = userMessage.toLowerCase();
25
+ const words = query.split(/\s+/).filter(w => w.length > 3);
26
+
27
+ // Score each skill by keyword match
28
+ const scored = skills.map(skill => {
29
+ const hay = (skill.name + " " + skill.slug + " " + skill.content.slice(0, 400)).toLowerCase();
30
+ const hits = words.filter(w => hay.includes(w)).length;
31
+ return { skill, hits };
32
+ });
33
+
34
+ // Use matched skills, or ALL skills if none matched (task is ambiguous)
35
+ const matched = scored.filter(s => s.hits > 0).map(s => s.skill);
36
+ const toInject = matched.length > 0 ? matched : skills;
37
+
38
+ const block = toInject.map(s =>
39
+ `=== SKILL: ${s.name} ===\n${s.content.trim()}`
40
+ ).join("\n\n---\n\n");
41
+
42
+ // Replace the last user message with skill context prepended
43
+ const last = messages[messages.length - 1];
44
+ const newLast = {
45
+ role: "user",
46
+ content: `[SKILLS TO APPLY FOR THIS TASK]\n\n${block}\n\n[END SKILLS]\n\nTask: ${last.content ?? userMessage}`
47
+ };
48
+
49
+ return [...messages.slice(0, -1), newLast];
50
+ }
51
+
52
+ // ─────────────────────────────────────────────────────────────────
53
+ // System prompt — clean, no skill listing
17
54
  // ─────────────────────────────────────────────────────────────────
18
55
  function buildSystemPrompt(extra = "") {
19
56
  const toolList = FUNCTION_DECLARATIONS.map(t => `- ${t.name}: ${t.description}`).join("\n");
20
- const skills = loadSkills();
21
-
22
57
  const now = new Date();
23
58
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
24
59
  const datetime = now.toLocaleString("id-ID", { timeZone: tz, dateStyle: "full", timeStyle: "long" });
25
60
 
26
- // Build skill section
27
- let skillSection = "";
28
- if (skills.length) {
29
- const index = skills.map(s => {
30
- const desc = s.content.split("\n").find(l => l.trim() && !l.startsWith("#")) ?? "";
31
- return ` - ${s.slug}: ${desc.slice(0, 80)}`;
32
- }).join("\n");
33
-
34
- skillSection = `
35
- ## SKILLS — MANDATORY
36
- You have skills installed. Skills contain expert instructions for specific tasks.
37
-
38
- **RULE: You MUST read the relevant skill file BEFORE starting any task.**
39
- Do NOT proceed with a task until you have read the applicable skill(s).
40
-
41
- Steps:
42
- 1. Look at the installed skills below
43
- 2. Identify which skill(s) apply to the current task
44
- 3. Use read_file to load the skill: read_file("${SKILLS_DIR}/<slug>/SKILL.md")
45
- 4. Follow the skill's instructions exactly
46
- 5. Only then proceed with the task
47
-
48
- Installed skills:
49
- ${index}
50
-
51
- Skills directory: ${SKILLS_DIR}`;
52
- }
53
-
54
61
  return `You are an autonomous AI coding agent running in the user's terminal.
55
62
 
56
63
  ## CURRENT TIME
57
64
  ${datetime} (${tz})
58
- ${skillSection}
59
65
 
60
66
  ## CORE RULE — NEVER ASK, ALWAYS ACT
61
67
  Use tools to complete every task. Never instruct the user to do anything themselves.
62
68
 
63
69
  ## WORKFLOW
64
- ${skills.length ? "0. READ SKILL — load the relevant SKILL.md first if applicable\n" : ""}1. EXPLORE — understand the project structure
70
+ 1. EXPLORE — understand the project structure
65
71
  2. ACT — complete the task fully using tools
66
72
  3. VERIFY — test after changes
67
73
  4. REPORT — brief summary
@@ -71,7 +77,7 @@ ${toolList}
71
77
 
72
78
  ## RULES
73
79
  - Always read files before editing them
74
- - Use patch_file for targeted edits (safer than full rewrite)
80
+ - Use patch_file for targeted edits
75
81
  - Verify code works after changes
76
82
  - If a command fails, diagnose and retry
77
83
  - Platform: ${process.platform} | CWD: ${process.cwd()}
@@ -101,10 +107,14 @@ export async function runAgentLoop(userMessage, history, {
101
107
  } = {}) {
102
108
 
103
109
  const fullSystem = buildSystemPrompt(systemInstruction ?? "");
104
- const messages = [...history, { role: "user", content: userMessage }];
105
- const spinner = new Spinner();
106
- const deadline = Date.now() + TIMEOUT_MS;
107
- let iteration = 0;
110
+
111
+ // Build messages and auto-inject relevant skills
112
+ let messages = [...history, { role: "user", content: userMessage }];
113
+ messages = injectSkills(userMessage, messages);
114
+
115
+ const spinner = new Spinner();
116
+ const deadline = Date.now() + TIMEOUT_MS;
117
+ let iteration = 0;
108
118
 
109
119
  while (true) {
110
120
  if (Date.now() > deadline) {
@@ -156,7 +166,7 @@ export async function runAgentLoop(userMessage, history, {
156
166
  }
157
167
 
158
168
  // ── Tool calls ─────────────────────────────────────────────
159
- // Push ALL parts (including thinking) into history for context continuity
169
+ // Push ALL parts including thinking into history maintains context continuity
160
170
  messages.push({ role: "model", parts });
161
171
 
162
172
  printStepHeader(iteration);