@prismshadow/penguin-skills 0.0.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 +201 -0
- package/README.md +32 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/skills/agent-creation/SKILL.md +73 -0
- package/skills/agent-creation/icon.svg +6 -0
- package/skills/agent-evaluation/SKILL.md +123 -0
- package/skills/agent-evaluation/icon.svg +6 -0
- package/skills/agent-optimization/SKILL.md +146 -0
- package/skills/agent-optimization/icon.svg +7 -0
- package/skills/agenthub-models/SKILL.md +123 -0
- package/skills/agenthub-models/icon.svg +9 -0
- package/skills/benchmark-design/SKILL.md +156 -0
- package/skills/benchmark-design/icon.svg +7 -0
- package/skills/data-analysis/SKILL.md +39 -0
- package/skills/data-analysis/icon.svg +5 -0
- package/skills/penguin-cli/SKILL.md +69 -0
- package/skills/penguin-cli/icon.svg +5 -0
- package/skills/penguin-sdk/SKILL.md +88 -0
- package/skills/penguin-sdk/icon.svg +6 -0
- package/skills/software-engineering/SKILL.md +34 -0
- package/skills/software-engineering/icon.svg +5 -0
- package/skills/web-design/SKILL.md +40 -0
- package/skills/web-design/icon.svg +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @prismshadow/penguin-skills
|
|
2
|
+
|
|
3
|
+
The PenguinHarness built-in skill library. A Skill is a directory with a `SKILL.md` (frontmatter: name, description, version, updated) — files are the runtime source of truth and ship raw in this package's npm tarball.
|
|
4
|
+
|
|
5
|
+
Skills follow the "index first, body on demand" design: only their metadata is injected into an Agent's system prompt; the Agent reads the full `SKILL.md` via shell when it actually needs it.
|
|
6
|
+
|
|
7
|
+
Included skills:
|
|
8
|
+
|
|
9
|
+
| Group | Skills |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Agent Development | `agent-creation`, `benchmark-design`, `agent-evaluation`, `agent-optimization` |
|
|
12
|
+
| Data Analysis | `data-analysis` |
|
|
13
|
+
| Penguin Development | `penguin-sdk`, `penguin-cli`, `agenthub-models` |
|
|
14
|
+
| Web Development | `web-design` |
|
|
15
|
+
| Software Engineering | `software-engineering` |
|
|
16
|
+
|
|
17
|
+
The first group powers the self-improvement loop: design a Benchmark, evaluate the Target Agent, optimize it to version N+1 with a snapshot before every round.
|
|
18
|
+
|
|
19
|
+
## Documentation
|
|
20
|
+
|
|
21
|
+
- [Skills](https://penguin.ooo/docs/skills)
|
|
22
|
+
- [Self-Improvement](https://penguin.ooo/docs/self-improvement)
|
|
23
|
+
|
|
24
|
+
## Development
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm --filter @prismshadow/penguin-skills build # tsup → dist/ (loader API)
|
|
28
|
+
pnpm --filter @prismshadow/penguin-skills typecheck
|
|
29
|
+
pnpm --filter @prismshadow/penguin-skills test
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Part of [PenguinHarness](https://github.com/Prism-Shadow/penguin-harness) · Apache-2.0
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Skill's frontmatter metadata (four fields: name / description / version / updated; description itself is English-only, may also carry description_zh and short_description(_zh)). */
|
|
2
|
+
interface SkillMetadata {
|
|
3
|
+
/** Skill name (matches its containing directory name). */
|
|
4
|
+
name: string;
|
|
5
|
+
/** One-line description; injected into the model prompt via `{{SKILL_METADATA}}`. */
|
|
6
|
+
description: string;
|
|
7
|
+
/** UI short description (frontmatter `short_description`, optional): preferred in compact spots like cards, falls back to the full description if missing; not injected into the prompt. */
|
|
8
|
+
shortDescription?: string;
|
|
9
|
+
/** Chinese short description (frontmatter `short_description_zh`, optional). */
|
|
10
|
+
shortDescriptionZh?: string;
|
|
11
|
+
/** Version number (natural number); falls back to 1 on parse failure. */
|
|
12
|
+
version: number;
|
|
13
|
+
/** Update date (YYYY-MM-DD); defaults to "". */
|
|
14
|
+
updated: string;
|
|
15
|
+
}
|
|
16
|
+
/** A Skill in the library: metadata + full SKILL.md content (including frontmatter, written as-is on install). */
|
|
17
|
+
interface LibrarySkill extends SkillMetadata {
|
|
18
|
+
content: string;
|
|
19
|
+
/** Optional raw `icon.svg` content in the directory (custom icon, the file is the sole source, copied alongside SKILL.md on install); absent means none (frontend falls back to the default book icon). */
|
|
20
|
+
icon?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Skill group manifest entry: group id, title (optionally with a Chinese title, displayed per UI language), and member Skill names. */
|
|
23
|
+
interface SkillGroupInfo {
|
|
24
|
+
id: string;
|
|
25
|
+
title: string;
|
|
26
|
+
/** Chinese group title (optional, displayed per UI language). */
|
|
27
|
+
titleZh?: string;
|
|
28
|
+
/** Member Skill names (i.e., directory names under `skills/`). */
|
|
29
|
+
skills: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Grouping result: group metadata + member Skills read from library files. */
|
|
32
|
+
interface ResolvedSkillGroup extends Omit<SkillGroupInfo, "skills"> {
|
|
33
|
+
skills: LibrarySkill[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parses the frontmatter at the start of SKILL.md: only recognizes `key: value` lines inside the
|
|
37
|
+
* first `---` block (split on the first colon, value trimmed, values may themselves contain colons);
|
|
38
|
+
* all fields are scalars, no YAML dependency needed.
|
|
39
|
+
* Error tolerance: returns null if the `---` block or name is missing; version falls back to 1 if
|
|
40
|
+
* it isn't a natural number; updated defaults to "".
|
|
41
|
+
*/
|
|
42
|
+
declare function parseSkillFrontmatter(content: string): SkillMetadata | null;
|
|
43
|
+
/** Reads all Skills in the library (one per subdirectory under `skills/`), sorted by name. */
|
|
44
|
+
declare function loadLibrarySkills(): LibrarySkill[];
|
|
45
|
+
/**
|
|
46
|
+
* Skill group manifest; members are library directory names.
|
|
47
|
+
* Docs: /docs/skills § "Built-in library".
|
|
48
|
+
*/
|
|
49
|
+
declare const SKILL_GROUPS: SkillGroupInfo[];
|
|
50
|
+
/**
|
|
51
|
+
* Groups library Skills according to SKILL_GROUPS (a member name missing from `all` is skipped);
|
|
52
|
+
* Skills not listed in any group are appended to an Other group (only appears if non-empty). A
|
|
53
|
+
* pure function, the testable core of loadSkillGroups.
|
|
54
|
+
*/
|
|
55
|
+
declare function groupSkills(all: LibrarySkill[]): ResolvedSkillGroup[];
|
|
56
|
+
/** Reads library files and groups them: SKILL_GROUPS order comes first, ungrouped Skills are appended to an Other group (only appears if non-empty). */
|
|
57
|
+
declare function loadSkillGroups(): ResolvedSkillGroup[];
|
|
58
|
+
/** Reads a single library Skill by name; returns undefined if the name contains illegal characters (path traversal guard) or doesn't exist. */
|
|
59
|
+
declare function librarySkill(name: string): LibrarySkill | undefined;
|
|
60
|
+
|
|
61
|
+
export { type LibrarySkill, type ResolvedSkillGroup, SKILL_GROUPS, type SkillGroupInfo, type SkillMetadata, groupSkills, librarySkill, loadLibrarySkills, loadSkillGroups, parseSkillFrontmatter };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
function parseSkillFrontmatter(content) {
|
|
6
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content.replace(/^\uFEFF/, ""));
|
|
7
|
+
if (!match) return null;
|
|
8
|
+
const fields = {};
|
|
9
|
+
for (const line of match[1].split(/\r?\n/)) {
|
|
10
|
+
const idx = line.indexOf(":");
|
|
11
|
+
if (idx <= 0) continue;
|
|
12
|
+
const key = line.slice(0, idx).trim();
|
|
13
|
+
if (key) fields[key] = line.slice(idx + 1).trim();
|
|
14
|
+
}
|
|
15
|
+
const name = fields["name"];
|
|
16
|
+
if (!name) return null;
|
|
17
|
+
const version = Number.parseInt(fields["version"] ?? "", 10);
|
|
18
|
+
const shortDescription = fields["short_description"];
|
|
19
|
+
const shortDescriptionZh = fields["short_description_zh"];
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
description: fields["description"] ?? "",
|
|
23
|
+
// short_description(_zh) is optional: omitted when absent (undefined keys aren't set).
|
|
24
|
+
...shortDescription !== void 0 ? { shortDescription } : {},
|
|
25
|
+
...shortDescriptionZh !== void 0 ? { shortDescriptionZh } : {},
|
|
26
|
+
version: Number.isInteger(version) && version >= 1 ? version : 1,
|
|
27
|
+
updated: fields["updated"] ?? ""
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var SKILLS_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "skills");
|
|
31
|
+
var SKILL_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
32
|
+
function readSkillDir(name) {
|
|
33
|
+
const dir = path.join(SKILLS_ROOT, name);
|
|
34
|
+
let content;
|
|
35
|
+
try {
|
|
36
|
+
content = fs.readFileSync(path.join(dir, "SKILL.md"), "utf8");
|
|
37
|
+
} catch {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
let icon;
|
|
41
|
+
try {
|
|
42
|
+
icon = fs.readFileSync(path.join(dir, "icon.svg"), "utf8");
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
const meta = parseSkillFrontmatter(content) ?? {
|
|
46
|
+
name,
|
|
47
|
+
description: "",
|
|
48
|
+
version: 1,
|
|
49
|
+
updated: ""
|
|
50
|
+
};
|
|
51
|
+
return { ...meta, name, content, ...icon !== void 0 ? { icon } : {} };
|
|
52
|
+
}
|
|
53
|
+
function loadLibrarySkills() {
|
|
54
|
+
const skills = [];
|
|
55
|
+
for (const entry of fs.readdirSync(SKILLS_ROOT, { withFileTypes: true })) {
|
|
56
|
+
if (!entry.isDirectory()) continue;
|
|
57
|
+
const skill = readSkillDir(entry.name);
|
|
58
|
+
if (skill) skills.push(skill);
|
|
59
|
+
}
|
|
60
|
+
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
61
|
+
}
|
|
62
|
+
var SKILL_GROUPS = [
|
|
63
|
+
{
|
|
64
|
+
id: "agent-development",
|
|
65
|
+
title: "Agent Development",
|
|
66
|
+
titleZh: "Agent \u5F00\u53D1",
|
|
67
|
+
skills: ["agent-creation", "benchmark-design", "agent-evaluation", "agent-optimization"]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "data-analysis",
|
|
71
|
+
title: "Data Analysis",
|
|
72
|
+
titleZh: "\u6570\u636E\u5206\u6790",
|
|
73
|
+
skills: ["data-analysis"]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "penguin-development",
|
|
77
|
+
title: "Penguin Development",
|
|
78
|
+
titleZh: "Penguin \u5F00\u53D1",
|
|
79
|
+
skills: ["penguin-sdk", "penguin-cli", "agenthub-models"]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "web-development",
|
|
83
|
+
title: "Web Development",
|
|
84
|
+
titleZh: "\u7F51\u9875\u5F00\u53D1",
|
|
85
|
+
skills: ["web-design"]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "software-engineering",
|
|
89
|
+
title: "Software Engineering",
|
|
90
|
+
titleZh: "\u8F6F\u4EF6\u5DE5\u7A0B",
|
|
91
|
+
skills: ["software-engineering"]
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
function groupSkills(all) {
|
|
95
|
+
const byName = new Map(all.map((skill) => [skill.name, skill]));
|
|
96
|
+
const grouped = /* @__PURE__ */ new Set();
|
|
97
|
+
const groups = SKILL_GROUPS.map((group) => {
|
|
98
|
+
const members = [];
|
|
99
|
+
for (const name of group.skills) {
|
|
100
|
+
const skill = byName.get(name);
|
|
101
|
+
if (!skill) continue;
|
|
102
|
+
members.push(skill);
|
|
103
|
+
grouped.add(name);
|
|
104
|
+
}
|
|
105
|
+
return { ...group, skills: members };
|
|
106
|
+
});
|
|
107
|
+
const others = all.filter((skill) => !grouped.has(skill.name));
|
|
108
|
+
if (others.length > 0) {
|
|
109
|
+
groups.push({
|
|
110
|
+
id: "other",
|
|
111
|
+
title: "Other",
|
|
112
|
+
titleZh: "\u5176\u4ED6",
|
|
113
|
+
skills: others
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return groups;
|
|
117
|
+
}
|
|
118
|
+
function loadSkillGroups() {
|
|
119
|
+
return groupSkills(loadLibrarySkills());
|
|
120
|
+
}
|
|
121
|
+
function librarySkill(name) {
|
|
122
|
+
if (!SKILL_NAME_PATTERN.test(name)) return void 0;
|
|
123
|
+
return readSkillDir(name);
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
SKILL_GROUPS,
|
|
127
|
+
groupSkills,
|
|
128
|
+
librarySkill,
|
|
129
|
+
loadLibrarySkills,
|
|
130
|
+
loadSkillGroups,
|
|
131
|
+
parseSkillFrontmatter
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * PenguinHarness Skill library: built-in SKILL.md docs and skill group manifest.\n *\n * The runtime source of truth for library content is the package's `skills/<skill_name>/SKILL.md`\n * files: frontmatter is parsed on read (same rules as installed Skills), so editing a file takes\n * effect immediately with no caching (files are small, calls are infrequent). Only the skill group\n * manifest (id, title, and member names) is hardcoded in code; install / uninstall / scan still live\n * in core's state layer.\n *\n * Docs: packages/docs/content/skills.{zh,en}.md (site path /docs/skills) documents the Skill\n * format and the built-in library.\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/** Skill's frontmatter metadata (four fields: name / description / version / updated; description itself is English-only, may also carry description_zh and short_description(_zh)). */\nexport interface SkillMetadata {\n /** Skill name (matches its containing directory name). */\n name: string;\n /** One-line description; injected into the model prompt via `{{SKILL_METADATA}}`. */\n description: string;\n /** UI short description (frontmatter `short_description`, optional): preferred in compact spots like cards, falls back to the full description if missing; not injected into the prompt. */\n shortDescription?: string;\n /** Chinese short description (frontmatter `short_description_zh`, optional). */\n shortDescriptionZh?: string;\n /** Version number (natural number); falls back to 1 on parse failure. */\n version: number;\n /** Update date (YYYY-MM-DD); defaults to \"\". */\n updated: string;\n}\n\n/** A Skill in the library: metadata + full SKILL.md content (including frontmatter, written as-is on install). */\nexport interface LibrarySkill extends SkillMetadata {\n content: string;\n /** Optional raw `icon.svg` content in the directory (custom icon, the file is the sole source, copied alongside SKILL.md on install); absent means none (frontend falls back to the default book icon). */\n icon?: string;\n}\n\n/** Skill group manifest entry: group id, title (optionally with a Chinese title, displayed per UI language), and member Skill names. */\nexport interface SkillGroupInfo {\n id: string;\n title: string;\n /** Chinese group title (optional, displayed per UI language). */\n titleZh?: string;\n /** Member Skill names (i.e., directory names under `skills/`). */\n skills: string[];\n}\n\n/** Grouping result: group metadata + member Skills read from library files. */\nexport interface ResolvedSkillGroup extends Omit<SkillGroupInfo, \"skills\"> {\n skills: LibrarySkill[];\n}\n\n/**\n * Parses the frontmatter at the start of SKILL.md: only recognizes `key: value` lines inside the\n * first `---` block (split on the first colon, value trimmed, values may themselves contain colons);\n * all fields are scalars, no YAML dependency needed.\n * Error tolerance: returns null if the `---` block or name is missing; version falls back to 1 if\n * it isn't a natural number; updated defaults to \"\".\n */\nexport function parseSkillFrontmatter(content: string): SkillMetadata | null {\n // Strip a possible UTF-8 BOM (may be introduced by editors when manually editing an installed SKILL.md); CRLF is handled by \\r?\\n.\n const match = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(content.replace(/^\\uFEFF/, \"\"));\n if (!match) return null;\n const fields: Record<string, string> = {};\n for (const line of match[1]!.split(/\\r?\\n/)) {\n const idx = line.indexOf(\":\");\n if (idx <= 0) continue;\n const key = line.slice(0, idx).trim();\n if (key) fields[key] = line.slice(idx + 1).trim();\n }\n const name = fields[\"name\"];\n if (!name) return null;\n const version = Number.parseInt(fields[\"version\"] ?? \"\", 10);\n const shortDescription = fields[\"short_description\"];\n const shortDescriptionZh = fields[\"short_description_zh\"];\n return {\n name,\n description: fields[\"description\"] ?? \"\",\n // short_description(_zh) is optional: omitted when absent (undefined keys aren't set).\n ...(shortDescription !== undefined ? { shortDescription } : {}),\n ...(shortDescriptionZh !== undefined ? { shortDescriptionZh } : {}),\n version: Number.isInteger(version) && version >= 1 ? version : 1,\n updated: fields[\"updated\"] ?? \"\",\n };\n}\n\n/** Root directory of library files: the package's `skills/` (both dist/ and src/ sit one level below the package root, so one level up reaches it). */\nconst SKILLS_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"..\", \"skills\");\n\n/** Character rule for Skill names (directory names): prevents path traversal. */\nconst SKILL_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;\n\n/**\n * Reads a single library directory to construct a LibrarySkill; returns undefined if SKILL.md\n * doesn't exist. name is taken from the directory name (overriding frontmatter); falls back to\n * empty metadata if frontmatter parsing fails.\n * The optional icon.svg in the directory is read alongside it (as a raw string); the icon field\n * is omitted if missing.\n */\nfunction readSkillDir(name: string): LibrarySkill | undefined {\n const dir = path.join(SKILLS_ROOT, name);\n let content: string;\n try {\n content = fs.readFileSync(path.join(dir, \"SKILL.md\"), \"utf8\");\n } catch {\n return undefined;\n }\n let icon: string | undefined;\n try {\n icon = fs.readFileSync(path.join(dir, \"icon.svg\"), \"utf8\");\n } catch {\n // icon.svg is optional: no custom icon if missing.\n }\n const meta = parseSkillFrontmatter(content) ?? {\n name,\n description: \"\",\n version: 1,\n updated: \"\",\n };\n return { ...meta, name, content, ...(icon !== undefined ? { icon } : {}) };\n}\n\n/** Reads all Skills in the library (one per subdirectory under `skills/`), sorted by name. */\nexport function loadLibrarySkills(): LibrarySkill[] {\n const skills: LibrarySkill[] = [];\n for (const entry of fs.readdirSync(SKILLS_ROOT, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const skill = readSkillDir(entry.name);\n if (skill) skills.push(skill);\n }\n return skills.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Skill group manifest; members are library directory names.\n * Docs: /docs/skills § \"Built-in library\".\n */\nexport const SKILL_GROUPS: SkillGroupInfo[] = [\n {\n id: \"agent-development\",\n title: \"Agent Development\",\n titleZh: \"Agent 开发\",\n skills: [\"agent-creation\", \"benchmark-design\", \"agent-evaluation\", \"agent-optimization\"],\n },\n {\n id: \"data-analysis\",\n title: \"Data Analysis\",\n titleZh: \"数据分析\",\n skills: [\"data-analysis\"],\n },\n {\n id: \"penguin-development\",\n title: \"Penguin Development\",\n titleZh: \"Penguin 开发\",\n skills: [\"penguin-sdk\", \"penguin-cli\", \"agenthub-models\"],\n },\n {\n id: \"web-development\",\n title: \"Web Development\",\n titleZh: \"网页开发\",\n skills: [\"web-design\"],\n },\n {\n id: \"software-engineering\",\n title: \"Software Engineering\",\n titleZh: \"软件工程\",\n skills: [\"software-engineering\"],\n },\n];\n\n/**\n * Groups library Skills according to SKILL_GROUPS (a member name missing from `all` is skipped);\n * Skills not listed in any group are appended to an Other group (only appears if non-empty). A\n * pure function, the testable core of loadSkillGroups.\n */\nexport function groupSkills(all: LibrarySkill[]): ResolvedSkillGroup[] {\n const byName = new Map(all.map((skill) => [skill.name, skill]));\n const grouped = new Set<string>();\n const groups: ResolvedSkillGroup[] = SKILL_GROUPS.map((group) => {\n const members: LibrarySkill[] = [];\n for (const name of group.skills) {\n const skill = byName.get(name);\n if (!skill) continue;\n members.push(skill);\n grouped.add(name);\n }\n return { ...group, skills: members };\n });\n const others = all.filter((skill) => !grouped.has(skill.name));\n if (others.length > 0) {\n groups.push({\n id: \"other\",\n title: \"Other\",\n titleZh: \"其他\",\n skills: others,\n });\n }\n return groups;\n}\n\n/** Reads library files and groups them: SKILL_GROUPS order comes first, ungrouped Skills are appended to an Other group (only appears if non-empty). */\nexport function loadSkillGroups(): ResolvedSkillGroup[] {\n return groupSkills(loadLibrarySkills());\n}\n\n/** Reads a single library Skill by name; returns undefined if the name contains illegal characters (path traversal guard) or doesn't exist. */\nexport function librarySkill(name: string): LibrarySkill | undefined {\n if (!SKILL_NAME_PATTERN.test(name)) return undefined;\n return readSkillDir(name);\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prismshadow/penguin-skills",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "PenguinHarness skill library: built-in SKILL.md documents and skill groups, decoupled from core.",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Prism-Shadow/penguin-harness.git",
|
|
10
|
+
"directory": "packages/skills"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^24.0.0",
|
|
22
|
+
"tsup": "^8.3.0",
|
|
23
|
+
"typescript": "^5.6.0",
|
|
24
|
+
"vitest": "^2.1.0"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"skills",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
36
|
+
"test": "vitest run --passWithNoTests",
|
|
37
|
+
"build": "tsup"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-creation
|
|
3
|
+
description: Turn a user requirement into a concrete agent — write the target agent's AGENTS.md and install the skills it needs.
|
|
4
|
+
short_description: Turn a requirement into a working agent.
|
|
5
|
+
short_description_zh: 把需求变成可用的 Agent。
|
|
6
|
+
version: 1
|
|
7
|
+
updated: 2026-07-17T00:00:00Z
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Agent Creation
|
|
11
|
+
|
|
12
|
+
This skill turns a user requirement into a working agent configuration — plain files in the target agent's directory.
|
|
13
|
+
|
|
14
|
+
## Before you start
|
|
15
|
+
|
|
16
|
+
If the user's message only invokes this skill (e.g. "use agent-creation skill") without a concrete requirement, ask the user what agent they want and what it should do. Do not start until the requirement is clear.
|
|
17
|
+
|
|
18
|
+
## Locate the target agent
|
|
19
|
+
|
|
20
|
+
All agents of this project live side by side in the project directory:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
PROJECT_DIR="<project_dir>" # the Project Dir value from your Environment section
|
|
24
|
+
ls "$PROJECT_DIR/agents" # existing agents (each is a folder here)
|
|
25
|
+
TARGET="$PROJECT_DIR/agents/<agent_id>" # the agent to configure
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
An agent directory contains `agent_state/` (`system_config.yaml`, `AGENTS.md`, `skills/`, `memory/`, `tools/`) plus `scratchpad/` — and `traces/`, which appears once the agent has run at least once.
|
|
29
|
+
|
|
30
|
+
## Write AGENTS.md
|
|
31
|
+
|
|
32
|
+
`agent_state/AGENTS.md` is injected into the agent's system prompt — it is where the user requirement becomes behavior. Keep `system_config.yaml`'s `system_prompt` untouched (that is the stable system layer); put everything requirement-specific in AGENTS.md:
|
|
33
|
+
|
|
34
|
+
- Role — what the agent is for, in one or two sentences.
|
|
35
|
+
- Domain guidance — the concrete rules, steps and constraints derived from the user requirement.
|
|
36
|
+
|
|
37
|
+
Be concise: AGENTS.md is prompt context, not documentation.
|
|
38
|
+
|
|
39
|
+
## Install skills
|
|
40
|
+
|
|
41
|
+
A skill is a directory `agent_state/skills/<skill_name>/` containing a `SKILL.md`:
|
|
42
|
+
|
|
43
|
+
```md
|
|
44
|
+
---
|
|
45
|
+
name: <skill_name>
|
|
46
|
+
description: <skill_description>
|
|
47
|
+
version: 1
|
|
48
|
+
updated: <ISO 8601 timestamp>
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
<skill_instructions>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The frontmatter may also carry optional `short_description` and `short_description_zh` lines (a short UI blurb and its Chinese variant) — the UI prefers them for display, while prompt injection always uses the English `description`.
|
|
55
|
+
|
|
56
|
+
Installing is all it takes: the frontmatter metadata of every `SKILL.md` under `skills/` is injected into the target agent's system prompt automatically — do not register skills in AGENTS.md.
|
|
57
|
+
|
|
58
|
+
Write skills yourself, or fetch existing ones from the internet with shell commands (`curl`, `git clone`) and place them under `skills/`. Anything fetched from the internet must be read in full and reviewed before installing — a skill becomes durable instructions the target agent will follow in every future session; never install one you have not read, and tell the user what it does.
|
|
59
|
+
|
|
60
|
+
## Set name and description
|
|
61
|
+
|
|
62
|
+
In the target's `agent_state/system_config.yaml`, set the top-level `name:` and `description:` fields so the agent is recognizable in lists. Edit only these two fields.
|
|
63
|
+
|
|
64
|
+
## Creating a brand-new agent
|
|
65
|
+
|
|
66
|
+
Prefer configuring an agent the user already created. If you must create one from scratch: pick a short id (letters, digits, `_`, `-`), copy the default agent's `system_config.yaml` as the base, and create the layout described above:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
mkdir -p "$TARGET/agent_state/skills" "$TARGET/agent_state/memory" "$TARGET/agent_state/tools" "$TARGET/scratchpad"
|
|
70
|
+
cp "$PROJECT_DIR/agents/default_agent/agent_state/system_config.yaml" "$TARGET/agent_state/"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
A new agent starts with no skills — install only what it needs. Then write its AGENTS.md, name and description as above.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<circle cx="9.5" cy="8" r="3.3" />
|
|
3
|
+
<path d="M3.8 20c0-3.1 2.6-5.7 5.7-5.7 1.5 0 2.9.6 3.9 1.5" />
|
|
4
|
+
<path d="M18 13.5v7" />
|
|
5
|
+
<path d="M14.5 17h7" />
|
|
6
|
+
</svg>
|