@sayknow-cli/coding-agent 0.5.13 → 0.5.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/types/cli/setup-cli.d.ts +1 -1
  3. package/dist/types/defaults/skc-ui-skills.d.ts +12 -0
  4. package/dist/types/hooks/ui-skill-keywords.d.ts +84 -0
  5. package/dist/types/session-import/redact.d.ts +1 -1
  6. package/dist/types/setup/external-ui-skills.d.ts +37 -0
  7. package/package.json +7 -7
  8. package/src/cli/setup-cli.ts +22 -1
  9. package/src/cli/skills-cli.ts +29 -10
  10. package/src/commands/setup.ts +1 -0
  11. package/src/defaults/skc/ui-skills/LICENSE.appllama +21 -0
  12. package/src/defaults/skc/ui-skills/LICENSE.emilkowalski +21 -0
  13. package/src/defaults/skc/ui-skills/NOTICE.md +43 -0
  14. package/src/defaults/skc/ui-skills/animate/SKILL.md +536 -0
  15. package/src/defaults/skc/ui-skills/animation-vocabulary/SKILL.md +178 -0
  16. package/src/defaults/skc/ui-skills/apple-design/SKILL.md +285 -0
  17. package/src/defaults/skc/ui-skills/appllama-app-design-skill/SKILL.md +821 -0
  18. package/src/defaults/skc/ui-skills/ask-sonner/SKILL.md +157 -0
  19. package/src/defaults/skc/ui-skills/emil-design-eng/SKILL.md +671 -0
  20. package/src/defaults/skc/ui-skills/find-animation-opportunities/SKILL.md +137 -0
  21. package/src/defaults/skc/ui-skills/improve-animations/SKILL.md +305 -0
  22. package/src/defaults/skc/ui-skills/mobile-native/SKILL.md +308 -0
  23. package/src/defaults/skc/ui-skills/pick-ui-library/SKILL.md +82 -0
  24. package/src/defaults/skc/ui-skills/prototype/SKILL.md +300 -0
  25. package/src/defaults/skc/ui-skills/react-bits/SKILL.md +113 -0
  26. package/src/defaults/skc/ui-skills/review-animations/SKILL.md +312 -0
  27. package/src/defaults/skc-ui-skills.ts +108 -0
  28. package/src/extensibility/runtime-skill-discovery.ts +8 -2
  29. package/src/hooks/native-skill-hook.ts +14 -0
  30. package/src/hooks/ui-skill-keywords.ts +312 -0
  31. package/src/internal-urls/docs-index.generated.ts +1 -1
  32. package/src/prompts/agents/architect.md +1 -0
  33. package/src/prompts/agents/critic.md +1 -0
  34. package/src/prompts/agents/executor.md +1 -0
  35. package/src/prompts/agents/planner.md +1 -0
  36. package/src/prompts/system/system-prompt.md +1 -0
  37. package/src/prompts/tools/skill.md +2 -2
  38. package/src/sdk/session.ts +7 -5
  39. package/src/session-import/redact.ts +11 -6
  40. package/src/setup/external-ui-skills.ts +132 -0
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Install the frontend UI skills SKC routes to but cannot bundle.
3
+ *
4
+ * Most UI craft skills are compiled into the binary (see
5
+ * `defaults/skc-ui-skills.ts`). A few upstreams license their content for use
6
+ * but forbid redistributing the collection, so SKC must not carry them. For
7
+ * those, this installs upstream's own published payload into the project, where
8
+ * SKC's skill discovery picks it up like any other project skill.
9
+ *
10
+ * Target is `<project>/.agents/skills/<name>/`, which SKC's agents provider
11
+ * loads on the project walk-up.
12
+ */
13
+
14
+ import * as path from "node:path";
15
+ import { EXTERNAL_UI_SKILL_DEFINITIONS } from "../hooks/ui-skill-keywords";
16
+
17
+ export type ExternalUiSkillStatus = "installed" | "already-present" | "failed" | "missing";
18
+
19
+ export interface ExternalUiSkillResult {
20
+ skill: string;
21
+ source: string;
22
+ status: ExternalUiSkillStatus;
23
+ path: string;
24
+ detail?: string;
25
+ }
26
+
27
+ export interface ExternalUiSkillsReport {
28
+ projectDir: string;
29
+ installed: number;
30
+ alreadyPresent: number;
31
+ failed: number;
32
+ missing: number;
33
+ skills: ExternalUiSkillResult[];
34
+ }
35
+
36
+ export interface InstallExternalUiSkillsOptions {
37
+ cwd: string;
38
+ /** Report what would happen without running any installer. */
39
+ check?: boolean;
40
+ /** Reinstall even when the skill is already present. */
41
+ force?: boolean;
42
+ }
43
+
44
+ function installedSkillPath(cwd: string, skill: string): string {
45
+ return path.join(cwd, ".agents", "skills", skill, "SKILL.md");
46
+ }
47
+
48
+ export async function installExternalUiSkills(
49
+ options: InstallExternalUiSkillsOptions,
50
+ ): Promise<ExternalUiSkillsReport> {
51
+ const cwd = path.resolve(options.cwd);
52
+ const skills: ExternalUiSkillResult[] = [];
53
+
54
+ for (const definition of EXTERNAL_UI_SKILL_DEFINITIONS) {
55
+ const target = installedSkillPath(cwd, definition.skill);
56
+ const present = await Bun.file(target).exists();
57
+
58
+ if (present && !options.force) {
59
+ skills.push({ skill: definition.skill, source: definition.source, status: "already-present", path: target });
60
+ continue;
61
+ }
62
+ if (options.check) {
63
+ skills.push({
64
+ skill: definition.skill,
65
+ source: definition.source,
66
+ status: "missing",
67
+ path: target,
68
+ detail: definition.installCommand,
69
+ });
70
+ continue;
71
+ }
72
+
73
+ // Upstream's own publisher CLI. SKC never republishes the payload; it only
74
+ // runs the documented install into the user's project.
75
+ const proc = Bun.spawn(["sh", "-c", definition.installCommand], {
76
+ cwd,
77
+ stdout: "pipe",
78
+ stderr: "pipe",
79
+ });
80
+ const [stderr, exitCode] = await Promise.all([new Response(proc.stderr).text(), proc.exited]);
81
+ const landed = await Bun.file(target).exists();
82
+
83
+ if (exitCode === 0 && landed) {
84
+ skills.push({ skill: definition.skill, source: definition.source, status: "installed", path: target });
85
+ continue;
86
+ }
87
+ skills.push({
88
+ skill: definition.skill,
89
+ source: definition.source,
90
+ status: "failed",
91
+ path: target,
92
+ detail:
93
+ exitCode !== 0
94
+ ? `installer exited ${exitCode}: ${stderr.trim().split("\n").at(-1) ?? "no output"}`
95
+ : "installer reported success but no SKILL.md landed",
96
+ });
97
+ }
98
+
99
+ return {
100
+ projectDir: cwd,
101
+ installed: skills.filter(entry => entry.status === "installed").length,
102
+ alreadyPresent: skills.filter(entry => entry.status === "already-present").length,
103
+ failed: skills.filter(entry => entry.status === "failed").length,
104
+ missing: skills.filter(entry => entry.status === "missing").length,
105
+ skills,
106
+ };
107
+ }
108
+
109
+ export function formatExternalUiSkillsReport(report: ExternalUiSkillsReport): string {
110
+ const lines: string[] = [];
111
+ for (const entry of report.skills) {
112
+ const relative = path.relative(report.projectDir, entry.path) || entry.path;
113
+ switch (entry.status) {
114
+ case "installed":
115
+ lines.push(`installed ${entry.skill} -> ${relative}`);
116
+ break;
117
+ case "already-present":
118
+ lines.push(`present ${entry.skill} -> ${relative}`);
119
+ break;
120
+ case "missing":
121
+ lines.push(`missing ${entry.skill} (run: ${entry.detail})`);
122
+ break;
123
+ case "failed":
124
+ lines.push(`failed ${entry.skill}: ${entry.detail}`);
125
+ break;
126
+ }
127
+ }
128
+ lines.push(
129
+ `${report.installed} installed, ${report.alreadyPresent} already present, ${report.missing} missing, ${report.failed} failed.`,
130
+ );
131
+ return lines.join("\n");
132
+ }