codemaxxing 1.0.0 → 1.0.2
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/README.md +18 -12
- package/dist/agent.d.ts +4 -0
- package/dist/agent.js +91 -16
- package/dist/commands/git.d.ts +2 -0
- package/dist/commands/git.js +50 -0
- package/dist/commands/ollama.d.ts +27 -0
- package/dist/commands/ollama.js +171 -0
- package/dist/commands/output.d.ts +2 -0
- package/dist/commands/output.js +18 -0
- package/dist/commands/registry.d.ts +2 -0
- package/dist/commands/registry.js +8 -0
- package/dist/commands/skills.d.ts +18 -0
- package/dist/commands/skills.js +121 -0
- package/dist/commands/types.d.ts +5 -0
- package/dist/commands/types.js +1 -0
- package/dist/commands/ui.d.ts +16 -0
- package/dist/commands/ui.js +79 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +13 -3
- package/dist/exec.js +4 -1
- package/dist/index.js +75 -401
- package/dist/tools/files.js +58 -3
- package/dist/utils/context.js +6 -0
- package/dist/utils/mcp.d.ts +7 -2
- package/dist/utils/mcp.js +34 -6
- package/package.json +8 -5
- package/src/agent.ts +0 -894
- package/src/auth-cli.ts +0 -287
- package/src/cli.ts +0 -37
- package/src/config.ts +0 -352
- package/src/exec.ts +0 -183
- package/src/index.tsx +0 -2647
- package/src/skills/registry.ts +0 -1436
- package/src/themes.ts +0 -335
- package/src/tools/files.ts +0 -374
- package/src/utils/auth.ts +0 -606
- package/src/utils/context.ts +0 -174
- package/src/utils/git.ts +0 -117
- package/src/utils/hardware.ts +0 -131
- package/src/utils/lint.ts +0 -116
- package/src/utils/mcp.ts +0 -307
- package/src/utils/models.ts +0 -218
- package/src/utils/ollama.ts +0 -352
- package/src/utils/repomap.ts +0 -220
- package/src/utils/sessions.ts +0 -254
- package/src/utils/skills.ts +0 -241
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { listInstalledSkills, installSkill, removeSkill, searchRegistry, createSkillScaffold, getActiveSkills, } from "../utils/skills.js";
|
|
2
|
+
export function tryHandleSkillsCommand(options) {
|
|
3
|
+
const { trimmed, cwd, addMsg, agent, sessionDisabledSkills, setSkillsPicker, setSkillsPickerIndex, setSessionDisabledSkills, setInput, setInputKey, } = options;
|
|
4
|
+
if (trimmed === "/skills") {
|
|
5
|
+
setSkillsPicker("menu");
|
|
6
|
+
setSkillsPickerIndex(0);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (trimmed.startsWith("/skills install ")) {
|
|
10
|
+
const name = trimmed.replace("/skills install ", "").trim();
|
|
11
|
+
const result = installSkill(name);
|
|
12
|
+
addMsg(result.ok ? "info" : "error", result.ok ? `✅ ${result.message}` : `✗ ${result.message}`);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (trimmed.startsWith("/skills remove ")) {
|
|
16
|
+
const name = trimmed.replace("/skills remove ", "").trim();
|
|
17
|
+
const result = removeSkill(name);
|
|
18
|
+
addMsg(result.ok ? "info" : "error", result.ok ? `✅ ${result.message}` : `✗ ${result.message}`);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (trimmed === "/skills list") {
|
|
22
|
+
const installed = listInstalledSkills();
|
|
23
|
+
if (installed.length === 0) {
|
|
24
|
+
addMsg("info", "No skills installed. Use /skills to browse & install.");
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const active = getActiveSkills(cwd, sessionDisabledSkills);
|
|
28
|
+
const lines = installed.map((skill) => {
|
|
29
|
+
const isActive = active.includes(skill.name);
|
|
30
|
+
const disabledBySession = sessionDisabledSkills.has(skill.name);
|
|
31
|
+
const status = disabledBySession ? " (off)" : isActive ? " (on)" : "";
|
|
32
|
+
return ` ${isActive ? "●" : "○"} ${skill.name} — ${skill.description}${status}`;
|
|
33
|
+
});
|
|
34
|
+
addMsg("info", `Installed skills:\n${lines.join("\n")}`);
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (trimmed === "/skills search") {
|
|
39
|
+
addMsg("info", "Usage: /skills search <query>");
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (trimmed.startsWith("/skills search ")) {
|
|
43
|
+
const query = trimmed.replace("/skills search ", "").trim();
|
|
44
|
+
if (!query) {
|
|
45
|
+
addMsg("info", "Usage: /skills search <query>");
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
const results = searchRegistry(query);
|
|
49
|
+
if (results.length === 0) {
|
|
50
|
+
addMsg("info", `No skills found matching "${query}".`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const installed = listInstalledSkills().map((skill) => skill.name);
|
|
54
|
+
const lines = results.map((skill) => {
|
|
55
|
+
const mark = installed.includes(skill.name) ? " ✓" : "";
|
|
56
|
+
return ` ${skill.name} — ${skill.description}${mark}`;
|
|
57
|
+
});
|
|
58
|
+
addMsg("info", `Registry matches:\n${lines.join("\n")}`);
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (trimmed.startsWith("/skills create ")) {
|
|
63
|
+
const name = trimmed.replace("/skills create ", "").trim();
|
|
64
|
+
if (!name) {
|
|
65
|
+
addMsg("info", "Usage: /skills create <name>");
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
const result = createSkillScaffold(name);
|
|
69
|
+
addMsg(result.ok ? "info" : "error", result.ok ? `✅ ${result.message}\n Edit: ${result.path}/prompt.md` : `✗ ${result.message}`);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (trimmed === "/skills on") {
|
|
73
|
+
addMsg("info", "Usage: /skills on <name>");
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (trimmed.startsWith("/skills on ")) {
|
|
77
|
+
const name = trimmed.replace("/skills on ", "").trim();
|
|
78
|
+
const installed = listInstalledSkills().map((skill) => skill.name);
|
|
79
|
+
if (!installed.includes(name)) {
|
|
80
|
+
addMsg("error", `Skill "${name}" is not installed.`);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
setSessionDisabledSkills((prev) => {
|
|
84
|
+
const next = new Set(prev);
|
|
85
|
+
next.delete(name);
|
|
86
|
+
return next;
|
|
87
|
+
});
|
|
88
|
+
if (agent)
|
|
89
|
+
agent.enableSkill(name);
|
|
90
|
+
addMsg("info", `✅ Enabled skill: ${name}`);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (trimmed === "/skills off") {
|
|
94
|
+
addMsg("info", "Usage: /skills off <name>");
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (trimmed.startsWith("/skills off ")) {
|
|
98
|
+
const name = trimmed.replace("/skills off ", "").trim();
|
|
99
|
+
const installed = listInstalledSkills().map((skill) => skill.name);
|
|
100
|
+
if (!installed.includes(name)) {
|
|
101
|
+
addMsg("error", `Skill "${name}" is not installed.`);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
setSessionDisabledSkills((prev) => {
|
|
105
|
+
const next = new Set(prev);
|
|
106
|
+
next.add(name);
|
|
107
|
+
return next;
|
|
108
|
+
});
|
|
109
|
+
if (agent)
|
|
110
|
+
agent.disableSkill(name);
|
|
111
|
+
addMsg("info", `✅ Disabled skill: ${name} (session only)`);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
if (trimmed.startsWith("/skills create")) {
|
|
115
|
+
setSkillsPicker(null);
|
|
116
|
+
setInput("/skills create ");
|
|
117
|
+
setInputKey((key) => key + 1);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type AddMsg = (type: "user" | "response" | "tool" | "tool-result" | "error" | "info", text: string) => void;
|
|
2
|
+
export interface CommandRegistryContext {
|
|
3
|
+
trimmed: string;
|
|
4
|
+
}
|
|
5
|
+
export type CommandRegistryHandler<TContext extends CommandRegistryContext = CommandRegistryContext> = (context: TContext) => boolean | Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Dispatch, type SetStateAction } from "react";
|
|
2
|
+
import type { CodingAgent } from "../agent.js";
|
|
3
|
+
import { type Theme } from "../themes.js";
|
|
4
|
+
import type { AddMsg } from "./types.js";
|
|
5
|
+
interface HandleUiCommandOptions {
|
|
6
|
+
trimmed: string;
|
|
7
|
+
cwd: string;
|
|
8
|
+
addMsg: AddMsg;
|
|
9
|
+
agent: CodingAgent | null;
|
|
10
|
+
theme: Theme;
|
|
11
|
+
setTheme: Dispatch<SetStateAction<Theme>>;
|
|
12
|
+
setThemePicker: Dispatch<SetStateAction<boolean>>;
|
|
13
|
+
setThemePickerIndex: Dispatch<SetStateAction<number>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function tryHandleUiCommand(options: HandleUiCommandOptions): Promise<boolean>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { loadConfig } from "../config.js";
|
|
2
|
+
import { THEMES, getTheme, listThemes } from "../themes.js";
|
|
3
|
+
export async function tryHandleUiCommand(options) {
|
|
4
|
+
const { trimmed, cwd, addMsg, agent, theme, setTheme, setThemePicker, setThemePickerIndex, } = options;
|
|
5
|
+
if (trimmed.startsWith("/theme")) {
|
|
6
|
+
const themeName = trimmed.replace("/theme", "").trim();
|
|
7
|
+
if (!themeName) {
|
|
8
|
+
const themeKeys = listThemes();
|
|
9
|
+
const currentIdx = themeKeys.indexOf(theme.name.toLowerCase());
|
|
10
|
+
setThemePicker(true);
|
|
11
|
+
setThemePickerIndex(currentIdx >= 0 ? currentIdx : 0);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (!THEMES[themeName]) {
|
|
15
|
+
addMsg("error", `Theme "${themeName}" not found. Use /theme to see available themes.`);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
setTheme(getTheme(themeName));
|
|
19
|
+
addMsg("info", `✅ Switched to theme: ${THEMES[themeName].name}`);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (trimmed === "/architect") {
|
|
23
|
+
if (!agent) {
|
|
24
|
+
addMsg("info", "🏗️ Architect mode: no agent connected. Connect first with /login or /connect.");
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const current = agent.getArchitectModel();
|
|
28
|
+
if (current) {
|
|
29
|
+
agent.setArchitectModel(null);
|
|
30
|
+
addMsg("info", "🏗️ Architect mode OFF");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const defaultModel = loadConfig().defaults.architectModel || agent.getModel();
|
|
34
|
+
agent.setArchitectModel(defaultModel);
|
|
35
|
+
addMsg("info", `🏗️ Architect mode ON (planner: ${defaultModel})`);
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (trimmed.startsWith("/architect ")) {
|
|
40
|
+
const model = trimmed.replace("/architect ", "").trim();
|
|
41
|
+
if (!model) {
|
|
42
|
+
addMsg("info", "Usage: /architect <model> or /architect to toggle");
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (agent) {
|
|
46
|
+
agent.setArchitectModel(model);
|
|
47
|
+
addMsg("info", `🏗️ Architect mode ON (planner: ${model})`);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
addMsg("info", "⚠ No agent connected. Connect first.");
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (trimmed === "/lint") {
|
|
55
|
+
const { detectLinter } = await import("../utils/lint.js");
|
|
56
|
+
const linter = detectLinter(cwd);
|
|
57
|
+
const enabled = agent ? agent.isAutoLintEnabled() : true;
|
|
58
|
+
if (linter) {
|
|
59
|
+
addMsg("info", `🔍 Auto-lint: ${enabled ? "ON" : "OFF"}\n Detected: ${linter.name}\n Command: ${linter.command} <file>`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
addMsg("info", `🔍 Auto-lint: ${enabled ? "ON" : "OFF"}\n No linter detected in this project.`);
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (trimmed === "/lint on") {
|
|
67
|
+
if (agent)
|
|
68
|
+
agent.setAutoLint(true);
|
|
69
|
+
addMsg("info", "🔍 Auto-lint ON");
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (trimmed === "/lint off") {
|
|
73
|
+
if (agent)
|
|
74
|
+
agent.setAutoLint(false);
|
|
75
|
+
addMsg("info", "🔍 Auto-lint OFF");
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -62,3 +62,12 @@ export declare function listModels(baseUrl: string, apiKey: string): Promise<str
|
|
|
62
62
|
* Priority: CLI args > auth store > config file > auto-detect
|
|
63
63
|
*/
|
|
64
64
|
export declare function resolveProvider(providerId: string, cliArgs: CLIArgs): ProviderConfig | null;
|
|
65
|
+
/**
|
|
66
|
+
* Detect provider transport type.
|
|
67
|
+
*
|
|
68
|
+
* Important: model family does NOT decide this. OpenRouter, Gemini-compatible,
|
|
69
|
+
* Qwen-compatible, Copilot, LM Studio, Ollama, and custom OpenAI-compatible
|
|
70
|
+
* endpoints should all stay on the OpenAI-compatible transport even when the
|
|
71
|
+
* selected model is Claude.
|
|
72
|
+
*/
|
|
73
|
+
export declare function detectProviderType(providerId: string, baseUrl: string): "openai" | "anthropic";
|
package/dist/config.js
CHANGED
|
@@ -280,10 +280,20 @@ export function resolveProvider(providerId, cliArgs) {
|
|
|
280
280
|
return null;
|
|
281
281
|
}
|
|
282
282
|
/**
|
|
283
|
-
* Detect provider type
|
|
283
|
+
* Detect provider transport type.
|
|
284
|
+
*
|
|
285
|
+
* Important: model family does NOT decide this. OpenRouter, Gemini-compatible,
|
|
286
|
+
* Qwen-compatible, Copilot, LM Studio, Ollama, and custom OpenAI-compatible
|
|
287
|
+
* endpoints should all stay on the OpenAI-compatible transport even when the
|
|
288
|
+
* selected model is Claude.
|
|
284
289
|
*/
|
|
285
|
-
function detectProviderType(providerId, baseUrl) {
|
|
286
|
-
|
|
290
|
+
export function detectProviderType(providerId, baseUrl) {
|
|
291
|
+
const id = providerId.toLowerCase();
|
|
292
|
+
const url = baseUrl.toLowerCase();
|
|
293
|
+
if (id === "anthropic")
|
|
294
|
+
return "anthropic";
|
|
295
|
+
// Only treat Anthropic's native API as anthropic transport.
|
|
296
|
+
if (url.includes("api.anthropic.com") || url.includes("api.us.anthropic.com")) {
|
|
287
297
|
return "anthropic";
|
|
288
298
|
}
|
|
289
299
|
return "openai";
|
package/dist/exec.js
CHANGED
|
@@ -151,7 +151,10 @@ export async function runExec(argv) {
|
|
|
151
151
|
process.stdout.write(JSON.stringify(output, null, 2) + "\n");
|
|
152
152
|
}
|
|
153
153
|
await disconnectAll();
|
|
154
|
-
|
|
154
|
+
// Exit 0 = success (always, with or without file changes)
|
|
155
|
+
// Exit 2 = no file changes were made (useful for CI scripts that check if work was done)
|
|
156
|
+
// Only exit(1) is reserved for actual errors (see catch block below)
|
|
157
|
+
process.exit(0);
|
|
155
158
|
}
|
|
156
159
|
catch (err) {
|
|
157
160
|
await disconnectAll();
|