@kkelly-offical/kkcode 0.1.7 → 0.2.3-preview.1
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/LICENSE +674 -674
- package/README.md +474 -387
- package/package.json +50 -46
- package/src/agent/agent.mjs +228 -220
- package/src/agent/custom-agent-loader.mjs +6 -3
- package/src/agent/generator.mjs +2 -2
- package/src/agent/prompt/assistant.txt +12 -0
- package/src/agent/prompt/bug-hunter.txt +89 -89
- package/src/agent/prompt/frontend-designer.txt +58 -58
- package/src/agent/prompt/guide.txt +1 -1
- package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
- package/src/agent/prompt/longagent-coding-agent.txt +37 -37
- package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
- package/src/agent/prompt/longagent-preview-agent.txt +63 -63
- package/src/command/custom-commands.mjs +2 -2
- package/src/commands/agent.mjs +1 -1
- package/src/commands/background.mjs +145 -4
- package/src/commands/chat.mjs +117 -76
- package/src/commands/config.mjs +148 -1
- package/src/commands/doctor.mjs +30 -6
- package/src/commands/init.mjs +32 -6
- package/src/commands/longagent.mjs +117 -0
- package/src/commands/mcp.mjs +275 -43
- package/src/commands/permission.mjs +1 -1
- package/src/commands/session.mjs +195 -140
- package/src/commands/skill.mjs +63 -0
- package/src/commands/theme.mjs +1 -1
- package/src/commands/update.mjs +32 -0
- package/src/config/defaults.mjs +289 -260
- package/src/config/import-config.mjs +1 -1
- package/src/config/load-config.mjs +61 -4
- package/src/config/schema.mjs +604 -574
- package/src/context.mjs +4 -1
- package/src/core/constants.mjs +97 -91
- package/src/core/types.mjs +1 -1
- package/src/github/api.mjs +78 -78
- package/src/github/auth.mjs +294 -286
- package/src/github/flow.mjs +298 -298
- package/src/github/workspace.mjs +225 -212
- package/src/index.mjs +87 -82
- package/src/knowledge/frontend-aesthetics.txt +38 -38
- package/src/mcp/client-http.mjs +139 -141
- package/src/mcp/client-sse.mjs +297 -288
- package/src/mcp/client-stdio.mjs +534 -533
- package/src/mcp/constants.mjs +4 -2
- package/src/mcp/registry.mjs +498 -479
- package/src/mcp/stdio-framing.mjs +135 -133
- package/src/mcp/tool-result.mjs +24 -24
- package/src/observability/edit-diagnostics.mjs +449 -0
- package/src/observability/index.mjs +42 -42
- package/src/observability/metrics.mjs +165 -137
- package/src/observability/tracer.mjs +137 -137
- package/src/onboarding.mjs +209 -0
- package/src/orchestration/background-manager.mjs +567 -372
- package/src/orchestration/background-worker.mjs +419 -305
- package/src/orchestration/interruption-reason.mjs +21 -0
- package/src/orchestration/longagent-manager.mjs +197 -171
- package/src/orchestration/stage-scheduler.mjs +733 -728
- package/src/orchestration/subagent-router.mjs +7 -1
- package/src/orchestration/task-scheduler.mjs +219 -7
- package/src/permission/engine.mjs +1 -1
- package/src/permission/exec-policy.mjs +370 -370
- package/src/permission/file-edit-policy.mjs +108 -0
- package/src/permission/prompt.mjs +1 -1
- package/src/permission/rules.mjs +116 -7
- package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
- package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
- package/src/plugin/hook-bus.mjs +19 -5
- package/src/plugin/manifest-loader.mjs +222 -0
- package/src/provider/anthropic.mjs +396 -390
- package/src/provider/ollama.mjs +7 -1
- package/src/provider/openai.mjs +382 -340
- package/src/provider/retry-policy.mjs +74 -68
- package/src/provider/router.mjs +242 -241
- package/src/provider/sse.mjs +104 -104
- package/src/provider/wizard.mjs +556 -0
- package/src/repl/capability-facade.mjs +30 -0
- package/src/repl/command-surface.mjs +23 -0
- package/src/repl/controller-entry.mjs +40 -0
- package/src/repl/core-shell.mjs +208 -0
- package/src/repl/dialog-router.mjs +87 -0
- package/src/repl/input-engine.mjs +76 -0
- package/src/repl/keymap.mjs +7 -0
- package/src/repl/operator-surface.mjs +15 -0
- package/src/repl/permission-flow.mjs +49 -0
- package/src/repl/runtime-facade.mjs +36 -0
- package/src/repl/slash-router.mjs +62 -0
- package/src/repl/state-store.mjs +29 -0
- package/src/repl/turn-controller.mjs +58 -0
- package/src/repl/verification.mjs +23 -0
- package/src/repl.mjs +3371 -2981
- package/src/rules/load-rules.mjs +3 -3
- package/src/runtime.mjs +1 -1
- package/src/session/agent-transaction.mjs +86 -0
- package/src/session/checkpoint.mjs +302 -302
- package/src/session/compaction.mjs +298 -298
- package/src/session/engine.mjs +417 -232
- package/src/session/longagent-4stage.mjs +467 -460
- package/src/session/longagent-hybrid.mjs +1344 -1097
- package/src/session/longagent-plan.mjs +376 -365
- package/src/session/longagent-project-memory.mjs +53 -53
- package/src/session/longagent-scaffold.mjs +291 -291
- package/src/session/longagent-task-bus.mjs +138 -54
- package/src/session/longagent-utils.mjs +828 -472
- package/src/session/longagent.mjs +911 -900
- package/src/session/loop.mjs +1005 -930
- package/src/session/prompt/agent.txt +25 -25
- package/src/session/prompt/anthropic.txt +150 -150
- package/src/session/prompt/beast.txt +1 -1
- package/src/session/prompt/plan.txt +31 -31
- package/src/session/prompt/qwen.txt +46 -46
- package/src/session/recovery.mjs +21 -0
- package/src/session/rollback.mjs +196 -195
- package/src/session/routing-observability.mjs +72 -0
- package/src/session/runtime-state.mjs +47 -0
- package/src/session/store.mjs +523 -519
- package/src/session/system-prompt.mjs +308 -273
- package/src/session/task-validator.mjs +267 -267
- package/src/session/usability-gates.mjs +2 -2
- package/src/skill/builtin/commit.mjs +64 -64
- package/src/skill/builtin/design.mjs +76 -76
- package/src/skill/generator.mjs +18 -2
- package/src/skill/registry.mjs +642 -390
- package/src/storage/audit-store.mjs +18 -11
- package/src/storage/event-log.mjs +7 -1
- package/src/storage/ghost-commit-store.mjs +243 -245
- package/src/storage/paths.mjs +17 -0
- package/src/theme/default-theme.mjs +1 -1
- package/src/theme/markdown.mjs +4 -0
- package/src/theme/schema.mjs +1 -1
- package/src/theme/status-bar.mjs +162 -158
- package/src/tool/audit-wrapper.mjs +18 -2
- package/src/tool/edit-transaction.mjs +23 -0
- package/src/tool/executor.mjs +26 -1
- package/src/tool/file-read-state.mjs +65 -0
- package/src/tool/git-auto.mjs +526 -526
- package/src/tool/git-full-auto.mjs +487 -478
- package/src/tool/mutation-guard.mjs +54 -0
- package/src/tool/prompt/edit.txt +3 -3
- package/src/tool/prompt/multiedit.txt +1 -0
- package/src/tool/prompt/notebookedit.txt +2 -1
- package/src/tool/prompt/patch.txt +25 -24
- package/src/tool/prompt/read.txt +3 -3
- package/src/tool/prompt/sysinfo.txt +29 -0
- package/src/tool/prompt/task.txt +66 -4
- package/src/tool/prompt/write.txt +2 -2
- package/src/tool/question-prompt.mjs +99 -93
- package/src/tool/registry.mjs +1701 -1343
- package/src/tool/task-tool.mjs +14 -6
- package/src/ui/activity-renderer.mjs +667 -664
- package/src/ui/repl-background-panel.mjs +7 -0
- package/src/ui/repl-capability-panel.mjs +9 -0
- package/src/ui/repl-dashboard.mjs +54 -4
- package/src/ui/repl-help.mjs +110 -0
- package/src/ui/repl-operator-panel.mjs +12 -0
- package/src/ui/repl-route-feedback.mjs +35 -0
- package/src/ui/repl-status-view.mjs +76 -0
- package/src/ui/repl-task-panel.mjs +5 -0
- package/src/ui/repl-transcript-panel.mjs +56 -0
- package/src/ui/repl-turn-summary.mjs +135 -0
- package/src/update/checker.mjs +184 -0
- package/src/usage/pricing.mjs +122 -121
- package/src/usage/usage-meter.mjs +1 -0
- package/src/util/git.mjs +562 -519
- package/src/util/template.mjs +6 -1
- package/src/version.mjs +3 -0
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
export const name = "commit"
|
|
2
|
-
export const description = "Stage changes and create a git commit with a descriptive message using AI-powered git automation"
|
|
3
|
-
|
|
4
|
-
export async function run(args, context = {}) {
|
|
5
|
-
const hasGitAuto = context.config?.git_auto?.enabled !== false
|
|
6
|
-
|
|
7
|
-
return `Review the current git status and create a well-structured commit.
|
|
8
|
-
|
|
9
|
-
${hasGitAuto ? `🚀 Git Auto Mode Enabled
|
|
10
|
-
The AI can now use ghost commits (temporary snapshots) to safely manage changes before you finalize them.
|
|
11
|
-
` : `⚙️ Standard Mode
|
|
12
|
-
Consider enabling git_auto in your config for enhanced safety features.
|
|
13
|
-
`}
|
|
14
|
-
|
|
15
|
-
Steps:
|
|
16
|
-
1. Run \`git_info\` to understand the repository context.
|
|
17
|
-
2. Run \`git_status\` to see all changed, staged, and untracked files.
|
|
18
|
-
3. Review the changes to understand what needs to be committed.
|
|
19
|
-
|
|
20
|
-
${hasGitAuto ? `4. **IMPORTANT**: Before making any edits, create a ghost commit snapshot:
|
|
21
|
-
\`git_snapshot\` - Creates a temporary snapshot you can restore later
|
|
22
|
-
|
|
23
|
-
5. After reviewing, if you need to make changes, the AI will:
|
|
24
|
-
- First create an automatic snapshot (if git_auto.auto_snapshot is enabled)
|
|
25
|
-
- Apply changes using \`edit\`, \`write\`, or \`git_apply_patch\`
|
|
26
|
-
|
|
27
|
-
6. If you're not satisfied with the changes:
|
|
28
|
-
- Use \`git_list_snapshots\` to see available snapshots
|
|
29
|
-
- Use \`git_restore\` with the snapshot_id to revert
|
|
30
|
-
|
|
31
|
-
7. When satisfied with the changes, guide the user to manually run:
|
|
32
|
-
\`bash: git add <files> && git commit -m "<message>"\`
|
|
33
|
-
Note: AI is forbidden from running git commit directly for security.`
|
|
34
|
-
|
|
35
|
-
: `4. Stage the relevant files with manual git commands (AI cannot run git commit):
|
|
36
|
-
- AI can suggest: \`bash: git add <files>\`
|
|
37
|
-
- But user must manually run: \`git commit -m "<message>"\`
|
|
38
|
-
|
|
39
|
-
5. Note: AI is forbidden from executing git commit/push for security reasons.`}
|
|
40
|
-
|
|
41
|
-
Commit Message Format (Conventional Commits):
|
|
42
|
-
- feat: new feature or capability
|
|
43
|
-
- fix: bug fix
|
|
44
|
-
- refactor: code restructuring without behavior change
|
|
45
|
-
- docs: documentation changes
|
|
46
|
-
- style: formatting, whitespace, semicolons
|
|
47
|
-
- test: adding or updating tests
|
|
48
|
-
- chore: build process, dependencies, tooling
|
|
49
|
-
|
|
50
|
-
Format: <type>(<optional scope>): <short description>
|
|
51
|
-
Example: feat(auth): add JWT token refresh logic
|
|
52
|
-
|
|
53
|
-
Important:
|
|
54
|
-
- Keep the commit focused on a single logical change.
|
|
55
|
-
- If there are unrelated changes, create separate commits.
|
|
56
|
-
- The commit message subject should be under 72 characters.
|
|
57
|
-
- Use imperative mood: "add feature" not "added feature".
|
|
58
|
-
|
|
59
|
-
${hasGitAuto ? `Safety Features:
|
|
60
|
-
- Ghost commits are stored for 7 days then auto-cleaned
|
|
61
|
-
- Maximum 50 snapshots per repository
|
|
62
|
-
- Snapshots don't interfere with your normal git workflow
|
|
63
|
-
- Use \`git_cleanup\` to manually clean up expired snapshots` : ""}`
|
|
64
|
-
}
|
|
1
|
+
export const name = "commit"
|
|
2
|
+
export const description = "Stage changes and create a git commit with a descriptive message using AI-powered git automation"
|
|
3
|
+
|
|
4
|
+
export async function run(args, context = {}) {
|
|
5
|
+
const hasGitAuto = context.config?.git_auto?.enabled !== false
|
|
6
|
+
|
|
7
|
+
return `Review the current git status and create a well-structured commit.
|
|
8
|
+
|
|
9
|
+
${hasGitAuto ? `🚀 Git Auto Mode Enabled
|
|
10
|
+
The AI can now use ghost commits (temporary snapshots) to safely manage changes before you finalize them.
|
|
11
|
+
` : `⚙️ Standard Mode
|
|
12
|
+
Consider enabling git_auto in your config for enhanced safety features.
|
|
13
|
+
`}
|
|
14
|
+
|
|
15
|
+
Steps:
|
|
16
|
+
1. Run \`git_info\` to understand the repository context.
|
|
17
|
+
2. Run \`git_status\` to see all changed, staged, and untracked files.
|
|
18
|
+
3. Review the changes to understand what needs to be committed.
|
|
19
|
+
|
|
20
|
+
${hasGitAuto ? `4. **IMPORTANT**: Before making any edits, create a ghost commit snapshot:
|
|
21
|
+
\`git_snapshot\` - Creates a temporary snapshot you can restore later
|
|
22
|
+
|
|
23
|
+
5. After reviewing, if you need to make changes, the AI will:
|
|
24
|
+
- First create an automatic snapshot (if git_auto.auto_snapshot is enabled)
|
|
25
|
+
- Apply changes using \`edit\`, \`write\`, or \`git_apply_patch\`
|
|
26
|
+
|
|
27
|
+
6. If you're not satisfied with the changes:
|
|
28
|
+
- Use \`git_list_snapshots\` to see available snapshots
|
|
29
|
+
- Use \`git_restore\` with the snapshot_id to revert
|
|
30
|
+
|
|
31
|
+
7. When satisfied with the changes, guide the user to manually run:
|
|
32
|
+
\`bash: git add <files> && git commit -m "<message>"\`
|
|
33
|
+
Note: AI is forbidden from running git commit directly for security.`
|
|
34
|
+
|
|
35
|
+
: `4. Stage the relevant files with manual git commands (AI cannot run git commit):
|
|
36
|
+
- AI can suggest: \`bash: git add <files>\`
|
|
37
|
+
- But user must manually run: \`git commit -m "<message>"\`
|
|
38
|
+
|
|
39
|
+
5. Note: AI is forbidden from executing git commit/push for security reasons.`}
|
|
40
|
+
|
|
41
|
+
Commit Message Format (Conventional Commits):
|
|
42
|
+
- feat: new feature or capability
|
|
43
|
+
- fix: bug fix
|
|
44
|
+
- refactor: code restructuring without behavior change
|
|
45
|
+
- docs: documentation changes
|
|
46
|
+
- style: formatting, whitespace, semicolons
|
|
47
|
+
- test: adding or updating tests
|
|
48
|
+
- chore: build process, dependencies, tooling
|
|
49
|
+
|
|
50
|
+
Format: <type>(<optional scope>): <short description>
|
|
51
|
+
Example: feat(auth): add JWT token refresh logic
|
|
52
|
+
|
|
53
|
+
Important:
|
|
54
|
+
- Keep the commit focused on a single logical change.
|
|
55
|
+
- If there are unrelated changes, create separate commits.
|
|
56
|
+
- The commit message subject should be under 72 characters.
|
|
57
|
+
- Use imperative mood: "add feature" not "added feature".
|
|
58
|
+
|
|
59
|
+
${hasGitAuto ? `Safety Features:
|
|
60
|
+
- Ghost commits are stored for 7 days then auto-cleaned
|
|
61
|
+
- Maximum 50 snapshots per repository
|
|
62
|
+
- Snapshots don't interfere with your normal git workflow
|
|
63
|
+
- Use \`git_cleanup\` to manually clean up expired snapshots` : ""}`
|
|
64
|
+
}
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
|
|
4
|
-
export const name = "design"
|
|
5
|
-
export const description = "Frontend design mode — generates polished, distinctive UI with strong aesthetics (usage: /design <task>)"
|
|
6
|
-
|
|
7
|
-
async function detectDesignContext(cwd) {
|
|
8
|
-
try {
|
|
9
|
-
const pkg = JSON.parse(await readFile(path.join(cwd, "package.json"), "utf8"))
|
|
10
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
11
|
-
const ctx = {}
|
|
12
|
-
// Framework
|
|
13
|
-
if (deps.next) ctx.framework = "next"
|
|
14
|
-
else if (deps.nuxt) ctx.framework = "nuxt"
|
|
15
|
-
else if (deps.vue) ctx.framework = "vue"
|
|
16
|
-
else if (deps.react) ctx.framework = "react"
|
|
17
|
-
else if (deps.svelte || deps["@sveltejs/kit"]) ctx.framework = "svelte"
|
|
18
|
-
// CSS
|
|
19
|
-
if (deps.tailwindcss) ctx.css = "tailwind"
|
|
20
|
-
else if (deps.unocss) ctx.css = "unocss"
|
|
21
|
-
else if (deps["styled-components"]) ctx.css = "styled-components"
|
|
22
|
-
// Component lib
|
|
23
|
-
if (deps.antd) ctx.lib = "antd"
|
|
24
|
-
else if (deps["element-plus"]) ctx.lib = "element-plus"
|
|
25
|
-
else if (deps["@mui/material"]) ctx.lib = "mui"
|
|
26
|
-
else if (deps["@chakra-ui/react"]) ctx.lib = "chakra-ui"
|
|
27
|
-
else if (deps["@mantine/core"]) ctx.lib = "mantine"
|
|
28
|
-
else if (deps["naive-ui"]) ctx.lib = "naive-ui"
|
|
29
|
-
return ctx
|
|
30
|
-
} catch { return {} }
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const AESTHETICS_PROMPT = `<frontend_aesthetics>
|
|
34
|
-
You are in DESIGN MODE. Create polished, distinctive frontends — NOT generic AI output.
|
|
35
|
-
|
|
36
|
-
Typography: Avoid Inter/Roboto/Arial. Use distinctive fonts (Space Grotesk, Playfair Display, Satoshi, IBM Plex). Extreme weight contrast (200 vs 800), 3x+ size jumps.
|
|
37
|
-
|
|
38
|
-
Color: CSS variables for ALL colors. Dominant color + sharp accent. Draw from IDE themes (Nord, Catppuccin), cultural aesthetics. AVOID purple-gradient-on-white.
|
|
39
|
-
|
|
40
|
-
Motion: One high-impact staggered reveal per page. Micro-interactions on hover/focus/press. CSS transitions + animation-delay.
|
|
41
|
-
|
|
42
|
-
Layout: CSS Grid for pages, Flexbox for components. Generous whitespace. Consistent 4px spacing scale. Mobile-first.
|
|
43
|
-
|
|
44
|
-
Depth: Layered gradients, backdrop-filter glass, box-shadow elevation hierarchy.
|
|
45
|
-
|
|
46
|
-
NEVER: cookie-cutter card grids, generic hero sections, border-radius:9999px everywhere, gray wireframe text, no visual rhythm.
|
|
47
|
-
</frontend_aesthetics>`
|
|
48
|
-
|
|
49
|
-
export async function run(ctx) {
|
|
50
|
-
const task = (ctx.args || "").trim()
|
|
51
|
-
const cwd = ctx.cwd || process.cwd()
|
|
52
|
-
const design = await detectDesignContext(cwd)
|
|
53
|
-
|
|
54
|
-
const parts = [AESTHETICS_PROMPT, ""]
|
|
55
|
-
|
|
56
|
-
if (Object.keys(design).length) {
|
|
57
|
-
parts.push("## Project Design Context")
|
|
58
|
-
if (design.framework) parts.push(`- Framework: ${design.framework}`)
|
|
59
|
-
if (design.css) parts.push(`- CSS: ${design.css}`)
|
|
60
|
-
if (design.lib) parts.push(`- Component Library: ${design.lib}`)
|
|
61
|
-
parts.push("")
|
|
62
|
-
parts.push("Read the project's existing styles/theme before writing new code. Extend, don't replace.")
|
|
63
|
-
parts.push("")
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (task) {
|
|
67
|
-
parts.push(`## Task`)
|
|
68
|
-
parts.push(task)
|
|
69
|
-
parts.push("")
|
|
70
|
-
parts.push("Implement this with production-grade design quality. Make it look like a professional designer built it.")
|
|
71
|
-
} else {
|
|
72
|
-
parts.push("No task specified. Usage: /design <description of what to build>")
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return parts.join("\n")
|
|
76
|
-
}
|
|
1
|
+
import { readFile } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
|
|
4
|
+
export const name = "design"
|
|
5
|
+
export const description = "Frontend design mode — generates polished, distinctive UI with strong aesthetics (usage: /design <task>)"
|
|
6
|
+
|
|
7
|
+
async function detectDesignContext(cwd) {
|
|
8
|
+
try {
|
|
9
|
+
const pkg = JSON.parse(await readFile(path.join(cwd, "package.json"), "utf8"))
|
|
10
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
11
|
+
const ctx = {}
|
|
12
|
+
// Framework
|
|
13
|
+
if (deps.next) ctx.framework = "next"
|
|
14
|
+
else if (deps.nuxt) ctx.framework = "nuxt"
|
|
15
|
+
else if (deps.vue) ctx.framework = "vue"
|
|
16
|
+
else if (deps.react) ctx.framework = "react"
|
|
17
|
+
else if (deps.svelte || deps["@sveltejs/kit"]) ctx.framework = "svelte"
|
|
18
|
+
// CSS
|
|
19
|
+
if (deps.tailwindcss) ctx.css = "tailwind"
|
|
20
|
+
else if (deps.unocss) ctx.css = "unocss"
|
|
21
|
+
else if (deps["styled-components"]) ctx.css = "styled-components"
|
|
22
|
+
// Component lib
|
|
23
|
+
if (deps.antd) ctx.lib = "antd"
|
|
24
|
+
else if (deps["element-plus"]) ctx.lib = "element-plus"
|
|
25
|
+
else if (deps["@mui/material"]) ctx.lib = "mui"
|
|
26
|
+
else if (deps["@chakra-ui/react"]) ctx.lib = "chakra-ui"
|
|
27
|
+
else if (deps["@mantine/core"]) ctx.lib = "mantine"
|
|
28
|
+
else if (deps["naive-ui"]) ctx.lib = "naive-ui"
|
|
29
|
+
return ctx
|
|
30
|
+
} catch { return {} }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const AESTHETICS_PROMPT = `<frontend_aesthetics>
|
|
34
|
+
You are in DESIGN MODE. Create polished, distinctive frontends — NOT generic AI output.
|
|
35
|
+
|
|
36
|
+
Typography: Avoid Inter/Roboto/Arial. Use distinctive fonts (Space Grotesk, Playfair Display, Satoshi, IBM Plex). Extreme weight contrast (200 vs 800), 3x+ size jumps.
|
|
37
|
+
|
|
38
|
+
Color: CSS variables for ALL colors. Dominant color + sharp accent. Draw from IDE themes (Nord, Catppuccin), cultural aesthetics. AVOID purple-gradient-on-white.
|
|
39
|
+
|
|
40
|
+
Motion: One high-impact staggered reveal per page. Micro-interactions on hover/focus/press. CSS transitions + animation-delay.
|
|
41
|
+
|
|
42
|
+
Layout: CSS Grid for pages, Flexbox for components. Generous whitespace. Consistent 4px spacing scale. Mobile-first.
|
|
43
|
+
|
|
44
|
+
Depth: Layered gradients, backdrop-filter glass, box-shadow elevation hierarchy.
|
|
45
|
+
|
|
46
|
+
NEVER: cookie-cutter card grids, generic hero sections, border-radius:9999px everywhere, gray wireframe text, no visual rhythm.
|
|
47
|
+
</frontend_aesthetics>`
|
|
48
|
+
|
|
49
|
+
export async function run(ctx) {
|
|
50
|
+
const task = (ctx.args || "").trim()
|
|
51
|
+
const cwd = ctx.cwd || process.cwd()
|
|
52
|
+
const design = await detectDesignContext(cwd)
|
|
53
|
+
|
|
54
|
+
const parts = [AESTHETICS_PROMPT, ""]
|
|
55
|
+
|
|
56
|
+
if (Object.keys(design).length) {
|
|
57
|
+
parts.push("## Project Design Context")
|
|
58
|
+
if (design.framework) parts.push(`- Framework: ${design.framework}`)
|
|
59
|
+
if (design.css) parts.push(`- CSS: ${design.css}`)
|
|
60
|
+
if (design.lib) parts.push(`- Component Library: ${design.lib}`)
|
|
61
|
+
parts.push("")
|
|
62
|
+
parts.push("Read the project's existing styles/theme before writing new code. Extend, don't replace.")
|
|
63
|
+
parts.push("")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (task) {
|
|
67
|
+
parts.push(`## Task`)
|
|
68
|
+
parts.push(task)
|
|
69
|
+
parts.push("")
|
|
70
|
+
parts.push("Implement this with production-grade design quality. Make it look like a professional designer built it.")
|
|
71
|
+
} else {
|
|
72
|
+
parts.push("No task specified. Usage: /design <description of what to build>")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return parts.join("\n")
|
|
76
|
+
}
|
package/src/skill/generator.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeFile, mkdir } from "node:fs/promises"
|
|
2
2
|
import { join, basename } from "node:path"
|
|
3
|
-
import { homedir } from "node:os"
|
|
4
3
|
import { requestProvider } from "../provider/router.mjs"
|
|
4
|
+
import { userRootDir } from "../storage/paths.mjs"
|
|
5
5
|
|
|
6
6
|
const SKILL_GEN_SYSTEM = `You are a skill generator for kkcode, a terminal AI coding agent.
|
|
7
7
|
Your task is to generate a skill file based on the user's description.
|
|
@@ -86,6 +86,22 @@ export async function generateSkill({ description, configState, providerType, mo
|
|
|
86
86
|
const fenceMatch = content.match(/```(?:markdown|javascript|js|mjs)?\n([\s\S]*?)\n```/)
|
|
87
87
|
if (fenceMatch) content = fenceMatch[1]
|
|
88
88
|
|
|
89
|
+
// Safety: reject .mjs skills that contain dangerous patterns
|
|
90
|
+
if (type === "mjs") {
|
|
91
|
+
const dangerPatterns = [
|
|
92
|
+
/child_process/,
|
|
93
|
+
/\bexec\s*\(/,
|
|
94
|
+
/\bspawn\s*\(/,
|
|
95
|
+
/\beval\s*\(/,
|
|
96
|
+
/Function\s*\(/,
|
|
97
|
+
/require\s*\(\s*['"]fs['"]\s*\)/
|
|
98
|
+
]
|
|
99
|
+
const hasDanger = dangerPatterns.some(p => p.test(content))
|
|
100
|
+
if (hasDanger) {
|
|
101
|
+
return { name, filename: `${name}.${type}`, content, type, needsReview: true, reviewReason: "contains potentially dangerous code patterns (child_process, exec, eval, etc.)" }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
89
105
|
const filename = `${name}.${type}`
|
|
90
106
|
return { name, filename, content, type }
|
|
91
107
|
}
|
|
@@ -94,7 +110,7 @@ export async function generateSkill({ description, configState, providerType, mo
|
|
|
94
110
|
* Save a skill to the global skills directory.
|
|
95
111
|
*/
|
|
96
112
|
export async function saveSkillGlobal(filename, content) {
|
|
97
|
-
const dir = join(
|
|
113
|
+
const dir = join(userRootDir(), "skills")
|
|
98
114
|
await mkdir(dir, { recursive: true })
|
|
99
115
|
const filePath = join(dir, filename)
|
|
100
116
|
await writeFile(filePath, content, "utf-8")
|