takomi 2.1.13 → 2.1.14
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/.pi/extensions/takomi-context-manager/model-policy-gate.ts +24 -2
- package/.pi/extensions/takomi-runtime/command-text.ts +10 -2
- package/.pi/extensions/takomi-runtime/commands.ts +78 -5
- package/.pi/extensions/takomi-runtime/routing-policy.ts +56 -14
- package/.pi/extensions/takomi-subagents/pi-subagents-internal.ts +4 -1
- package/README.md +2 -4
- package/assets/.agent/skills/git-commit-generation/SKILL.md +195 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
4
5
|
import type { ContextManagerState } from "./state";
|
|
@@ -20,14 +21,35 @@ function asRecord(value: unknown): Record<string, unknown> {
|
|
|
20
21
|
return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
async function
|
|
24
|
+
async function readSettingsFile(filePath: string): Promise<Settings> {
|
|
24
25
|
try {
|
|
25
|
-
return JSON.parse(await readFile(
|
|
26
|
+
return JSON.parse(await readFile(filePath, "utf8")) as Settings;
|
|
26
27
|
} catch {
|
|
27
28
|
return {};
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
function mergeSettings(globalSettings: Settings, projectSettings: Settings): Settings {
|
|
33
|
+
const globalOverrides = asRecord(globalSettings.subagents?.agentOverrides);
|
|
34
|
+
const projectOverrides = asRecord(projectSettings.subagents?.agentOverrides);
|
|
35
|
+
return {
|
|
36
|
+
...globalSettings,
|
|
37
|
+
...projectSettings,
|
|
38
|
+
takomi: { ...(globalSettings.takomi ?? {}), ...(projectSettings.takomi ?? {}) },
|
|
39
|
+
subagents: {
|
|
40
|
+
...(globalSettings.subagents ?? {}),
|
|
41
|
+
...(projectSettings.subagents ?? {}),
|
|
42
|
+
agentOverrides: { ...globalOverrides, ...projectOverrides },
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function readSettings(cwd: string): Promise<Settings> {
|
|
48
|
+
const globalSettings = await readSettingsFile(path.join(os.homedir(), ".pi", "agent", "settings.json"));
|
|
49
|
+
const projectSettings = await readSettingsFile(path.resolve(cwd, ".pi/settings.json"));
|
|
50
|
+
return mergeSettings(globalSettings, projectSettings);
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
function modelFamily(model: string): string {
|
|
32
54
|
return model.split("/").at(-1)?.toLowerCase() ?? model.toLowerCase();
|
|
33
55
|
}
|
|
@@ -16,7 +16,7 @@ const ROOT_COMPLETIONS: TakomiCompletion[] = [
|
|
|
16
16
|
{ value: "mode", label: "mode", description: "Set direct, orchestrate, or review mode" },
|
|
17
17
|
{ value: "gate", label: "gate", description: "Set auto or review-gated execution" },
|
|
18
18
|
{ value: "subagents", label: "subagents", description: "Control subagent usage and view" },
|
|
19
|
-
{ value: "routing", label: "routing", description: "
|
|
19
|
+
{ value: "routing", label: "routing", description: "Show or update Takomi model routing policy" },
|
|
20
20
|
];
|
|
21
21
|
|
|
22
22
|
const SUBCOMMAND_COMPLETIONS: Record<string, TakomiCompletion[]> = {
|
|
@@ -37,6 +37,12 @@ const SUBCOMMAND_COMPLETIONS: Record<string, TakomiCompletion[]> = {
|
|
|
37
37
|
{ value: "collapse", label: "collapse", description: "Collapse native tool results" },
|
|
38
38
|
{ value: "toggle", label: "toggle", description: "Toggle native tool result expansion" },
|
|
39
39
|
],
|
|
40
|
+
routing: [
|
|
41
|
+
{ value: "show", label: "show", description: "Show active routing policy source, path, and contents" },
|
|
42
|
+
{ value: "global", label: "global", description: "Save following policy text globally" },
|
|
43
|
+
{ value: "local", label: "local", description: "Save following policy text as a project override" },
|
|
44
|
+
{ value: "where", label: "where", description: "Show where the active routing policy is loaded from" },
|
|
45
|
+
],
|
|
40
46
|
};
|
|
41
47
|
|
|
42
48
|
const SUBCOMMAND_ALIASES: Record<string, string> = {
|
|
@@ -71,7 +77,9 @@ export function commandHelp(): string {
|
|
|
71
77
|
"/takomi mode <direct|orchestrate|review>",
|
|
72
78
|
"/takomi gate <auto|review>",
|
|
73
79
|
"/takomi subagents <on|off|status|expand|collapse|toggle>",
|
|
74
|
-
"/takomi routing
|
|
80
|
+
"/takomi routing [show|where]",
|
|
81
|
+
"/takomi routing <policy text> # updates global policy",
|
|
82
|
+
"/takomi routing local <policy text> # project override",
|
|
75
83
|
"/takomi-status",
|
|
76
84
|
"/takomi-reset",
|
|
77
85
|
].join("\n");
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
} from "../../../src/pi-takomi-core";
|
|
8
8
|
import { commandHelp, completions, statusText, workflowPrompt } from "./command-text";
|
|
9
9
|
import type { TakomiSubagentController } from "./subagent-types";
|
|
10
|
-
import { installTakomiRoutingPolicy } from "./routing-policy";
|
|
10
|
+
import { installTakomiRoutingPolicy, resolveTakomiRoutingPolicy, type RoutingPolicyInstallScope } from "./routing-policy";
|
|
11
11
|
|
|
12
12
|
export type TakomiRuntimeCommandState = {
|
|
13
13
|
enabled: boolean;
|
|
@@ -82,14 +82,87 @@ export function registerTakomiCommands(pi: ExtensionAPI, options: RegisterTakomi
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
async function handleRouting(ctx: ExtensionCommandContext, body?: string): Promise<void> {
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
const trimmed = body?.trim() ?? "";
|
|
86
|
+
|
|
87
|
+
const usage = [
|
|
88
|
+
"Usage:",
|
|
89
|
+
"/takomi routing show Print the full active policy",
|
|
90
|
+
"/takomi routing where Show source/path only",
|
|
91
|
+
"/takomi routing <policy text> Update the global policy",
|
|
92
|
+
"/takomi routing local <policy text> Create/update this project's override",
|
|
93
|
+
].join("\n");
|
|
94
|
+
|
|
95
|
+
async function showRoutingHelp(): Promise<void> {
|
|
96
|
+
const resolved = await resolveTakomiRoutingPolicy(ctx.cwd);
|
|
97
|
+
ctx.ui.notify([
|
|
98
|
+
"Takomi routing options",
|
|
99
|
+
"",
|
|
100
|
+
`Active source: ${resolved.source}`,
|
|
101
|
+
`Active path: ${resolved.policyPath ?? "not found"}`,
|
|
102
|
+
"",
|
|
103
|
+
usage,
|
|
104
|
+
"",
|
|
105
|
+
"Resolution order: project .pi/takomi/model-routing.md → global ~/.pi/takomi/model-routing.md → bundled fallback.",
|
|
106
|
+
].join("\n"), "warning");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function showRoutingLocation(): Promise<void> {
|
|
110
|
+
const resolved = await resolveTakomiRoutingPolicy(ctx.cwd);
|
|
111
|
+
ctx.ui.notify([
|
|
112
|
+
"Active Takomi routing policy location",
|
|
113
|
+
"",
|
|
114
|
+
`Source: ${resolved.source}`,
|
|
115
|
+
`Path: ${resolved.policyPath ?? "not found"}`,
|
|
116
|
+
"",
|
|
117
|
+
usage,
|
|
118
|
+
].join("\n"), resolved.source === "missing" ? "warning" : "info");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function showActivePolicy(): Promise<void> {
|
|
122
|
+
const resolved = await resolveTakomiRoutingPolicy(ctx.cwd);
|
|
123
|
+
const text = resolved.text ?? "No Takomi routing policy found.";
|
|
124
|
+
const clipped = text.length > 6000 ? `${text.slice(0, 6000)}\n\n…truncated; open the file above for the full policy.` : text;
|
|
125
|
+
ctx.ui.notify([
|
|
126
|
+
"Active Takomi routing policy",
|
|
127
|
+
"",
|
|
128
|
+
`Source: ${resolved.source}`,
|
|
129
|
+
`Path: ${resolved.policyPath ?? "not found"}`,
|
|
130
|
+
"",
|
|
131
|
+
clipped,
|
|
132
|
+
"",
|
|
133
|
+
usage,
|
|
134
|
+
].join("\n"), resolved.source === "missing" ? "warning" : "info");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!trimmed) {
|
|
138
|
+
await showRoutingHelp();
|
|
87
139
|
return;
|
|
88
140
|
}
|
|
141
|
+
if (/^(where|path|status)$/i.test(trimmed)) {
|
|
142
|
+
await showRoutingLocation();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (/^(show|view)$/i.test(trimmed)) {
|
|
146
|
+
await showActivePolicy();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (/^(global|local|project|set)$/i.test(trimmed)) {
|
|
151
|
+
ctx.ui.notify(usage, "warning");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const scopeMatch = trimmed.match(/^(global|local|project)\s+([\s\S]+)$/i);
|
|
156
|
+
const scope: RoutingPolicyInstallScope = scopeMatch?.[1]?.toLowerCase() === "local" || scopeMatch?.[1]?.toLowerCase() === "project" ? "project" : "global";
|
|
157
|
+
const policyText = scopeMatch?.[2] ?? trimmed.replace(/^set\s+/i, "");
|
|
158
|
+
|
|
89
159
|
try {
|
|
90
|
-
const result = await installTakomiRoutingPolicy(ctx.cwd,
|
|
160
|
+
const result = await installTakomiRoutingPolicy(ctx.cwd, policyText, { scope });
|
|
91
161
|
const detected = result.detectedDefaults.length ? `\n\nDetected defaults:\n- ${result.detectedDefaults.join("\n- ")}` : "\n\nNo model names were auto-detected; saved policy only.";
|
|
92
|
-
|
|
162
|
+
const overrideNote = scope === "global"
|
|
163
|
+
? "\n\nThis will be used by every project unless that project has its own .pi/takomi/model-routing.md override."
|
|
164
|
+
: "\n\nThis project-local policy overrides the global policy for the current project.";
|
|
165
|
+
ctx.ui.notify(`Takomi routing policy updated (${scope}).\n\nPolicy: ${result.policyPath}\nSettings: ${result.settingsPath}${detected}${overrideNote}`, "info");
|
|
93
166
|
} catch (error) {
|
|
94
167
|
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
95
168
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
|
|
5
6
|
export const TAKOMI_ROUTING_POLICY_RELATIVE = path.join(".pi", "takomi", "model-routing.md");
|
|
7
|
+
export const GLOBAL_TAKOMI_ROUTING_POLICY_PATH = path.join(os.homedir(), ".pi", "takomi", "model-routing.md");
|
|
8
|
+
export const GLOBAL_PI_SETTINGS_PATH = path.join(os.homedir(), ".pi", "agent", "settings.json");
|
|
9
|
+
export const PROJECT_PI_SETTINGS_RELATIVE = path.join(".pi", "settings.json");
|
|
6
10
|
export const BUNDLED_TAKOMI_ROUTING_POLICY_PATH = path.resolve(
|
|
7
11
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
8
12
|
"..",
|
|
@@ -18,7 +22,8 @@ export type RoutingPolicyInstallResult = {
|
|
|
18
22
|
detectedDefaults: string[];
|
|
19
23
|
};
|
|
20
24
|
|
|
21
|
-
export type
|
|
25
|
+
export type RoutingPolicyInstallScope = "global" | "project";
|
|
26
|
+
export type RoutingPolicySource = "project" | "global" | "bundled" | "missing";
|
|
22
27
|
|
|
23
28
|
export type ResolvedRoutingPolicy = {
|
|
24
29
|
source: RoutingPolicySource;
|
|
@@ -55,6 +60,10 @@ function extractQuotedPolicy(text: string): string {
|
|
|
55
60
|
return raw.replace(/^update\s+(?:takomi\s+)?(?:model\s+)?routing\s+(?:logic|policy|philosophy)\s*:?/i, "").trim();
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
function normalizeForSettings(filePath: string): string {
|
|
64
|
+
return filePath.replaceAll(path.sep, "/");
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
function deriveSubagentDefaults(policy: string): { overrides: JsonObject; detected: string[] } {
|
|
59
68
|
const lower = policy.toLowerCase();
|
|
60
69
|
const has55 = /gpt[- ]?5\.5/.test(lower);
|
|
@@ -89,16 +98,42 @@ function deriveSubagentDefaults(policy: string): { overrides: JsonObject; detect
|
|
|
89
98
|
}
|
|
90
99
|
|
|
91
100
|
export async function resolveTakomiRoutingPolicy(cwd: string): Promise<ResolvedRoutingPolicy> {
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
?
|
|
101
|
+
const projectSettingsPath = path.join(cwd, PROJECT_PI_SETTINGS_RELATIVE);
|
|
102
|
+
const projectSettings = await readJsonObject(projectSettingsPath);
|
|
103
|
+
const projectTakomi = asObject(projectSettings.takomi);
|
|
104
|
+
const configuredProject = typeof projectTakomi.modelRoutingPolicyFile === "string"
|
|
105
|
+
? projectTakomi.modelRoutingPolicyFile
|
|
97
106
|
: TAKOMI_ROUTING_POLICY_RELATIVE;
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
return { source: "project", policyPath:
|
|
107
|
+
const configuredProjectPath = path.isAbsolute(configuredProject) ? configuredProject : path.join(cwd, configuredProject);
|
|
108
|
+
const configuredProjectText = await readPolicyText(configuredProjectPath);
|
|
109
|
+
if (configuredProjectText) {
|
|
110
|
+
return { source: "project", policyPath: configuredProjectPath, text: configuredProjectText };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const defaultProjectPath = path.join(cwd, TAKOMI_ROUTING_POLICY_RELATIVE);
|
|
114
|
+
if (path.resolve(defaultProjectPath) !== path.resolve(configuredProjectPath)) {
|
|
115
|
+
const defaultProjectText = await readPolicyText(defaultProjectPath);
|
|
116
|
+
if (defaultProjectText) {
|
|
117
|
+
return { source: "project", policyPath: defaultProjectPath, text: defaultProjectText };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const globalSettings = await readJsonObject(GLOBAL_PI_SETTINGS_PATH);
|
|
122
|
+
const globalTakomi = asObject(globalSettings.takomi);
|
|
123
|
+
const configuredGlobal = typeof globalTakomi.modelRoutingPolicyFile === "string"
|
|
124
|
+
? globalTakomi.modelRoutingPolicyFile
|
|
125
|
+
: GLOBAL_TAKOMI_ROUTING_POLICY_PATH;
|
|
126
|
+
const configuredGlobalPath = path.isAbsolute(configuredGlobal) ? configuredGlobal : path.join(os.homedir(), configuredGlobal);
|
|
127
|
+
const configuredGlobalText = await readPolicyText(configuredGlobalPath);
|
|
128
|
+
if (configuredGlobalText) {
|
|
129
|
+
return { source: "global", policyPath: configuredGlobalPath, text: configuredGlobalText };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (path.resolve(configuredGlobalPath) !== path.resolve(GLOBAL_TAKOMI_ROUTING_POLICY_PATH)) {
|
|
133
|
+
const globalText = await readPolicyText(GLOBAL_TAKOMI_ROUTING_POLICY_PATH);
|
|
134
|
+
if (globalText) {
|
|
135
|
+
return { source: "global", policyPath: GLOBAL_TAKOMI_ROUTING_POLICY_PATH, text: globalText };
|
|
136
|
+
}
|
|
102
137
|
}
|
|
103
138
|
|
|
104
139
|
const bundledText = await readPolicyText(BUNDLED_TAKOMI_ROUTING_POLICY_PATH);
|
|
@@ -113,19 +148,26 @@ export async function resolveTakomiRoutingPolicy(cwd: string): Promise<ResolvedR
|
|
|
113
148
|
return { source: "missing" };
|
|
114
149
|
}
|
|
115
150
|
|
|
116
|
-
export async function installTakomiRoutingPolicy(cwd: string, input: string): Promise<RoutingPolicyInstallResult> {
|
|
151
|
+
export async function installTakomiRoutingPolicy(cwd: string, input: string, options: { scope?: RoutingPolicyInstallScope } = {}): Promise<RoutingPolicyInstallResult> {
|
|
117
152
|
const policy = extractQuotedPolicy(input);
|
|
118
153
|
if (!policy) throw new Error("No routing policy text found. Paste the policy after /takomi routing or inside triple quotes.");
|
|
119
154
|
|
|
120
|
-
const
|
|
121
|
-
const
|
|
155
|
+
const scope = options.scope ?? "global";
|
|
156
|
+
const policyPath = scope === "project"
|
|
157
|
+
? path.join(cwd, TAKOMI_ROUTING_POLICY_RELATIVE)
|
|
158
|
+
: GLOBAL_TAKOMI_ROUTING_POLICY_PATH;
|
|
159
|
+
const settingsPath = scope === "project"
|
|
160
|
+
? path.join(cwd, PROJECT_PI_SETTINGS_RELATIVE)
|
|
161
|
+
: GLOBAL_PI_SETTINGS_PATH;
|
|
122
162
|
await mkdir(path.dirname(policyPath), { recursive: true });
|
|
123
163
|
await mkdir(path.dirname(settingsPath), { recursive: true });
|
|
124
164
|
await writeFile(policyPath, `# Takomi Model Routing Policy\n\n${policy}\n`, "utf8");
|
|
125
165
|
|
|
126
166
|
const settings = await readJsonObject(settingsPath);
|
|
127
167
|
const takomi = asObject(settings.takomi);
|
|
128
|
-
takomi.modelRoutingPolicyFile =
|
|
168
|
+
takomi.modelRoutingPolicyFile = scope === "project"
|
|
169
|
+
? normalizeForSettings(TAKOMI_ROUTING_POLICY_RELATIVE)
|
|
170
|
+
: normalizeForSettings(GLOBAL_TAKOMI_ROUTING_POLICY_PATH);
|
|
129
171
|
settings.takomi = takomi;
|
|
130
172
|
|
|
131
173
|
const { overrides, detected } = deriveSubagentDefaults(policy);
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
// pi-subagents ships TS internals rather than a stable public JS API. Import them
|
|
3
3
|
// dynamically with computed specifiers so Takomi's own tsc does not type-check
|
|
4
4
|
// dependency source, while Pi's runtime TS loader can still load them.
|
|
5
|
+
// Do not hide import() inside Function/eval: Pi's extension VM does not provide
|
|
6
|
+
// a dynamic import callback for that path and fails with
|
|
7
|
+
// "A dynamic import callback was not specified."
|
|
5
8
|
|
|
6
|
-
const dynamicImport =
|
|
9
|
+
const dynamicImport = async <T = any>(specifier: string): Promise<T> => import(specifier) as Promise<T>;
|
|
7
10
|
const spec = (path: string) => `pi-subagents/${path}.ts`;
|
|
8
11
|
|
|
9
12
|
export async function loadPiSubagentsInternals() {
|
package/README.md
CHANGED
|
@@ -41,10 +41,6 @@ takomi install all
|
|
|
41
41
|
takomi init
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
### Subagent execution credit
|
|
45
|
-
|
|
46
|
-
Takomi's Pi-native subagent execution and terminal UI build on **[`pi-subagents`](https://github.com/nicobailon/pi-subagents)** by **Nico Bailon**. That package provides the underlying Pi extension for delegated subagent runs, including the native subagent result renderer, live progress/status display, single/parallel/chain execution support, session/artifact handling, and related subagent tooling. Takomi adds its own lifecycle orchestration, model-routing policy, workflow metadata, board/checklist context, and agent conventions on top of that foundation.
|
|
47
|
-
|
|
48
44
|
### Context Manager
|
|
49
45
|
|
|
50
46
|
Takomi now ships a Pi-native `takomi-context-manager` extension. It reduces prompt bloat with progressive context loading:
|
|
@@ -480,6 +476,8 @@ Externally sourced skills in this bundle retain credit to their upstream creator
|
|
|
480
476
|
- **Gemini CLI**: Custom VibeCode skill for large-context processing with Gemini 3 Pro.
|
|
481
477
|
- **Google Stitch Skills**: From [google-labs-code/stitch-skills](https://github.com/google-labs-code/stitch-skills) — Design-to-code suite including **design-md**, **enhance-prompt**, **stitch-loop**, **react-components**, and **shadcn-ui**.
|
|
482
478
|
- **Jules**: From [sanjay3290/ai-skills](https://github.com/sanjay3290/ai-skills) — delegate coding tasks to Google Jules AI agent.
|
|
479
|
+
- **Subagent Execution**: Built on **[`pi-subagents`](https://github.com/nicobailon/pi-subagents)** by **Nico Bailon** — providing the underlying Pi extension for delegated subagent runs (result rendering, live progress, single/parallel/chain execution, session/artifact handling, and related subagent tooling), upon which Takomi adds its own lifecycle orchestration, model-routing policy, and workflow metadata.
|
|
480
|
+
- **Git Commit Generation**: From the **[`kilocode`](https://github.com/Kilo-Org/kilocode)** repository by **Kilo-Org** (specifically, [git-commit-generation.md](https://github.com/Kilo-Org/kilocode/blob/main/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md)) — enabling automated, high-quality conventional git commit messages based on staged changes.
|
|
483
481
|
|
|
484
482
|
## 📄 License
|
|
485
483
|
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-commit-generation
|
|
3
|
+
description: "Automatically generate meaningful git commit messages based on staged changes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate Commit Messages
|
|
7
|
+
|
|
8
|
+
> [!NOTE]
|
|
9
|
+
> This skill is based on the **Kilo Code** Git Commit Generation feature.
|
|
10
|
+
> **Attribution**: Originally from the [Kilo Code Repository](https://github.com/Kilo-Org/kilocode/blob/main/packages/kilo-docs/pages/code-with-ai/features/git-commit-generation.md).
|
|
11
|
+
|
|
12
|
+
Generate descriptive commit messages automatically based on your staged git changes. Kilo Code analyzes your staged files and creates conventional commit messages that follow best practices.
|
|
13
|
+
|
|
14
|
+
{% callout type="info" %}
|
|
15
|
+
This feature only analyzes **staged changes**. Make sure to stage your files using `git add` or via `VS Code` interface before generating commit messages.
|
|
16
|
+
{% /callout %}
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
The git commit message generator:
|
|
21
|
+
|
|
22
|
+
- Analyzes only your **staged changes** (not unstaged or untracked files)
|
|
23
|
+
- Uses AI to understand the context and purpose of your changes
|
|
24
|
+
- Creates descriptive commit messages that explain what was changed and why following the [Conventional Commits](https://www.conventionalcommits.org/) (by default, customizable)
|
|
25
|
+
|
|
26
|
+
## Using the Feature
|
|
27
|
+
|
|
28
|
+
### Generating a Commit Message
|
|
29
|
+
|
|
30
|
+
1. Stage your changes using `git add` or the VS Code git interface
|
|
31
|
+
2. In the VS Code Source Control panel, look for the `Kilo Code` logo next to the commit message field)
|
|
32
|
+
3. Click the logo to generate a commit message
|
|
33
|
+
|
|
34
|
+
The generated message will appear in the commit message field, ready for you to review and modify if needed.
|
|
35
|
+
|
|
36
|
+
{% image src="/docs/img/git-commit-generation/git-commit-1.png" alt="Generated commit message example" width="600" /%}
|
|
37
|
+
|
|
38
|
+
### Conventional Commit Format
|
|
39
|
+
|
|
40
|
+
By default, generated messages follow the Conventional Commits specification:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
<type>(<scope>): <description>
|
|
44
|
+
|
|
45
|
+
<body>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Common types include:
|
|
49
|
+
|
|
50
|
+
- `feat`: New features
|
|
51
|
+
- `fix`: Bug fixes
|
|
52
|
+
- `docs`: Documentation changes
|
|
53
|
+
- `style`: Code style changes (formatting, etc.)
|
|
54
|
+
- `refactor`: Code refactoring
|
|
55
|
+
- `test`: Adding or updating tests
|
|
56
|
+
- `chore`: Maintenance tasks
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
{% tabs %}
|
|
61
|
+
{% tab label="VSCode" %}
|
|
62
|
+
|
|
63
|
+
The extension provides the same **SCM button** in the VS Code Source Control panel. Clicking it generates a commit message using the CLI backend's commit message generation API.
|
|
64
|
+
|
|
65
|
+
Configuration is handled through the extension's settings or the shared `kilo.jsonc` config file.
|
|
66
|
+
|
|
67
|
+
Customize the commit prompt from **Settings > Commit Message**. Kilo saves this prompt to the current project's config so each repository can follow its own commit conventions without changing your global settings.
|
|
68
|
+
|
|
69
|
+
You can also set it directly in the project config:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"commit_message": {
|
|
74
|
+
"prompt": "Write concise conventional commits with the package scope when possible."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
{% callout type="info" %}
|
|
80
|
+
Git commit message generation is a **VS Code extension feature**. It is not available in the CLI/TUI.
|
|
81
|
+
{% /callout %}
|
|
82
|
+
|
|
83
|
+
{% /tab %}
|
|
84
|
+
{% tab label="VSCode (Legacy)" %}
|
|
85
|
+
|
|
86
|
+
### Customizing the Commit Template
|
|
87
|
+
|
|
88
|
+
You can customize how commit messages are generated by modifying the prompt template:
|
|
89
|
+
|
|
90
|
+
1. Open Settings by clicking the gear icon {% codicon name="gear" /%} → `Prompts`
|
|
91
|
+
2. Find the "Commit Message Generation" section
|
|
92
|
+
3. Edit the `Prompt` template to match your project's conventions
|
|
93
|
+
|
|
94
|
+
{% image src="/docs/img/git-commit-generation/git-commit-2.png" alt="Commit message generation settings" width="600" /%}
|
|
95
|
+
|
|
96
|
+
The default template creates conventional commit messages, but you can modify it to:
|
|
97
|
+
|
|
98
|
+
- Use different commit message formats
|
|
99
|
+
- Include specific information relevant to your project
|
|
100
|
+
- Follow your team's commit message conventions
|
|
101
|
+
- Add custom instructions for the AI
|
|
102
|
+
|
|
103
|
+
### API Configuration
|
|
104
|
+
|
|
105
|
+
You can configure which API profile to use for commit message generation:
|
|
106
|
+
|
|
107
|
+
1. In the `Prompts` settings, scroll to "API Configuration"
|
|
108
|
+
2. Select a specific profile or use the currently selected one
|
|
109
|
+
|
|
110
|
+
{% callout type="tip" %}
|
|
111
|
+
Consider creating a dedicated [API configuration profile](/docs/ai-providers) with a faster, more cost-effective model specifically for commit message generation.
|
|
112
|
+
{% /callout %}
|
|
113
|
+
|
|
114
|
+
{% /tab %}
|
|
115
|
+
{% /tabs %}
|
|
116
|
+
|
|
117
|
+
## Best Practices
|
|
118
|
+
|
|
119
|
+
### Staging Strategy
|
|
120
|
+
|
|
121
|
+
- Stage related changes together for more coherent commit messages
|
|
122
|
+
- Avoid staging unrelated changes in a single commit
|
|
123
|
+
- Use `git add -p` for partial file staging when needed
|
|
124
|
+
|
|
125
|
+
### Message Review
|
|
126
|
+
|
|
127
|
+
- Always review generated messages before committing
|
|
128
|
+
- Edit messages to add context the AI might have missed
|
|
129
|
+
- Ensure the message accurately describes the changes
|
|
130
|
+
|
|
131
|
+
### Custom Templates
|
|
132
|
+
|
|
133
|
+
- Tailor the prompt template to your project's needs
|
|
134
|
+
- Include project-specific terminology or conventions
|
|
135
|
+
- Add instructions for handling specific types of changes
|
|
136
|
+
|
|
137
|
+
## Example Generated Messages
|
|
138
|
+
|
|
139
|
+
Here are examples of messages the feature might generate:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
feat(auth): add OAuth2 integration with Google
|
|
143
|
+
|
|
144
|
+
Implement Google OAuth2 authentication flow including:
|
|
145
|
+
- OAuth2 client configuration
|
|
146
|
+
- User profile retrieval
|
|
147
|
+
- Token refresh mechanism
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
fix(api): resolve race condition in user data fetching
|
|
152
|
+
|
|
153
|
+
Add proper error handling and retry logic to prevent
|
|
154
|
+
concurrent requests from causing data inconsistency
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
docs(readme): update installation instructions
|
|
159
|
+
|
|
160
|
+
Add missing dependency requirements and clarify
|
|
161
|
+
setup steps for new contributors
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Troubleshooting
|
|
165
|
+
|
|
166
|
+
### No Staged Changes
|
|
167
|
+
|
|
168
|
+
If the button doesn't appear or generation fails, ensure you have staged changes:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
git add <files>
|
|
172
|
+
# or stage all changes
|
|
173
|
+
git add .
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Poor Message Quality
|
|
177
|
+
|
|
178
|
+
If generated messages aren't helpful:
|
|
179
|
+
|
|
180
|
+
- Review your staging strategy - don't stage unrelated changes together
|
|
181
|
+
- Customize the prompt template with more specific instructions
|
|
182
|
+
- Try a different AI model through API configuration
|
|
183
|
+
|
|
184
|
+
### Integration Issues
|
|
185
|
+
|
|
186
|
+
The feature integrates with VS Code's built-in git functionality. If you encounter issues:
|
|
187
|
+
|
|
188
|
+
- Ensure your repository is properly initialized
|
|
189
|
+
- Check that VS Code can access your git repository
|
|
190
|
+
- Verify git is installed and accessible from VS Code
|
|
191
|
+
|
|
192
|
+
## Related Features
|
|
193
|
+
|
|
194
|
+
- [API Configuration Profiles](/docs/ai-providers) - Use different models for commit generation
|
|
195
|
+
- [Settings Management](/docs/getting-started/settings) - Manage all your Kilo Code preferences
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takomi",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.14",
|
|
4
4
|
"description": "🎯 Stop wrestling with AI. Start building with purpose. The artisan's toolkit for agent workflows, Codex skills, and original Takomi capabilities like 21st.dev integration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|