@withpica/mcp-server 2.51.0 → 2.52.0
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/.claude/settings.local.json +5 -0
- package/CHANGELOG.md +0 -41
- package/dist/prompts/index.d.ts +0 -32
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +0 -235
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/index.d.ts +0 -10
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +1 -134
- package/dist/resources/index.js.map +1 -1
- package/dist/server-instructions.d.ts +3 -4
- package/dist/server-instructions.d.ts.map +1 -1
- package/dist/server-instructions.js +1 -4
- package/dist/server-instructions.js.map +1 -1
- package/dist/server.d.ts +0 -26
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -108
- package/dist/server.js.map +1 -1
- package/dist/tools/agent-identity.d.ts.map +1 -1
- package/dist/tools/agent-identity.js +0 -15
- package/dist/tools/agent-identity.js.map +1 -1
- package/dist/tools/agreement-types.d.ts.map +1 -1
- package/dist/tools/agreement-types.js +0 -24
- package/dist/tools/agreement-types.js.map +1 -1
- package/dist/tools/agreements.d.ts.map +1 -1
- package/dist/tools/agreements.js +3 -21
- package/dist/tools/agreements.js.map +1 -1
- package/dist/tools/analytics.d.ts.map +1 -1
- package/dist/tools/analytics.js +1 -19
- package/dist/tools/analytics.js.map +1 -1
- package/dist/tools/app-tools.d.ts.map +1 -1
- package/dist/tools/app-tools.js +2 -11
- package/dist/tools/app-tools.js.map +1 -1
- package/dist/tools/assets.d.ts.map +1 -1
- package/dist/tools/assets.js +0 -33
- package/dist/tools/assets.js.map +1 -1
- package/dist/tools/audio-files.d.ts +0 -5
- package/dist/tools/audio-files.d.ts.map +1 -1
- package/dist/tools/audio-files.js +0 -91
- package/dist/tools/audio-files.js.map +1 -1
- package/dist/tools/audit.d.ts.map +1 -1
- package/dist/tools/audit.js +2 -11
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +0 -6
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/bulk.d.ts.map +1 -1
- package/dist/tools/bulk.js +0 -6
- package/dist/tools/bulk.js.map +1 -1
- package/dist/tools/calendar.d.ts.map +1 -1
- package/dist/tools/calendar.js +0 -3
- package/dist/tools/calendar.js.map +1 -1
- package/dist/tools/collaborators.d.ts.map +1 -1
- package/dist/tools/collaborators.js +3 -24
- package/dist/tools/collaborators.js.map +1 -1
- package/dist/tools/comparisons.d.ts.map +1 -1
- package/dist/tools/comparisons.js +0 -6
- package/dist/tools/comparisons.js.map +1 -1
- package/dist/tools/credits.d.ts +0 -18
- package/dist/tools/credits.d.ts.map +1 -1
- package/dist/tools/credits.js +4 -344
- package/dist/tools/credits.js.map +1 -1
- package/dist/tools/custody.d.ts.map +1 -1
- package/dist/tools/custody.js +2 -23
- package/dist/tools/custody.js.map +1 -1
- package/dist/tools/dashboard.d.ts.map +1 -1
- package/dist/tools/dashboard.js +7 -43
- package/dist/tools/dashboard.js.map +1 -1
- package/dist/tools/directory.d.ts.map +1 -1
- package/dist/tools/directory.js +0 -3
- package/dist/tools/directory.js.map +1 -1
- package/dist/tools/discovery.d.ts.map +1 -1
- package/dist/tools/discovery.js +7 -94
- package/dist/tools/discovery.js.map +1 -1
- package/dist/tools/disputes.d.ts.map +1 -1
- package/dist/tools/disputes.js +1 -4
- package/dist/tools/disputes.js.map +1 -1
- package/dist/tools/documents.d.ts.map +1 -1
- package/dist/tools/documents.js +0 -3
- package/dist/tools/documents.js.map +1 -1
- package/dist/tools/duplicates.d.ts.map +1 -1
- package/dist/tools/duplicates.js +0 -6
- package/dist/tools/duplicates.js.map +1 -1
- package/dist/tools/enrichment.d.ts.map +1 -1
- package/dist/tools/enrichment.js +0 -33
- package/dist/tools/enrichment.js.map +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/exports.js +3 -18
- package/dist/tools/exports.js.map +1 -1
- package/dist/tools/feedback.d.ts.map +1 -1
- package/dist/tools/feedback.js +0 -3
- package/dist/tools/feedback.js.map +1 -1
- package/dist/tools/files.d.ts +30 -0
- package/dist/tools/files.d.ts.map +1 -0
- package/dist/tools/files.js +98 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/groups.d.ts.map +1 -1
- package/dist/tools/groups.js +0 -12
- package/dist/tools/groups.js.map +1 -1
- package/dist/tools/import-documents.d.ts.map +1 -1
- package/dist/tools/import-documents.js +1 -10
- package/dist/tools/import-documents.js.map +1 -1
- package/dist/tools/import.d.ts.map +1 -1
- package/dist/tools/import.js +3 -36
- package/dist/tools/import.js.map +1 -1
- package/dist/tools/index.d.ts +6 -142
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +115 -269
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/integrations.d.ts.map +1 -1
- package/dist/tools/integrations.js +8 -28
- package/dist/tools/integrations.js.map +1 -1
- package/dist/tools/labels.d.ts.map +1 -1
- package/dist/tools/labels.js +0 -3
- package/dist/tools/labels.js.map +1 -1
- package/dist/tools/licensing.d.ts.map +1 -1
- package/dist/tools/licensing.js +0 -15
- package/dist/tools/licensing.js.map +1 -1
- package/dist/tools/memory.d.ts.map +1 -1
- package/dist/tools/memory.js +3 -15
- package/dist/tools/memory.js.map +1 -1
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +15 -77
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/multimedia.d.ts.map +1 -1
- package/dist/tools/multimedia.js +0 -15
- package/dist/tools/multimedia.js.map +1 -1
- package/dist/tools/my-reported-issues.d.ts.map +1 -1
- package/dist/tools/my-reported-issues.js +0 -3
- package/dist/tools/my-reported-issues.js.map +1 -1
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +0 -12
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/notifications.d.ts.map +1 -1
- package/dist/tools/notifications.js +1 -25
- package/dist/tools/notifications.js.map +1 -1
- package/dist/tools/onboarding.d.ts.map +1 -1
- package/dist/tools/onboarding.js +0 -3
- package/dist/tools/onboarding.js.map +1 -1
- package/dist/tools/people.d.ts.map +1 -1
- package/dist/tools/people.js +1 -16
- package/dist/tools/people.js.map +1 -1
- package/dist/tools/projects.d.ts.map +1 -1
- package/dist/tools/projects.js +0 -18
- package/dist/tools/projects.js.map +1 -1
- package/dist/tools/publishers.d.ts.map +1 -1
- package/dist/tools/publishers.js +0 -6
- package/dist/tools/publishers.js.map +1 -1
- package/dist/tools/recordings.d.ts.map +1 -1
- package/dist/tools/recordings.js +0 -15
- package/dist/tools/recordings.js.map +1 -1
- package/dist/tools/recovery-hints.d.ts.map +1 -1
- package/dist/tools/recovery-hints.js +2 -28
- package/dist/tools/recovery-hints.js.map +1 -1
- package/dist/tools/release-rich.d.ts.map +1 -1
- package/dist/tools/release-rich.js +2 -4
- package/dist/tools/release-rich.js.map +1 -1
- package/dist/tools/releases.d.ts.map +1 -1
- package/dist/tools/releases.js +0 -55
- package/dist/tools/releases.js.map +1 -1
- package/dist/tools/report-issue.d.ts.map +1 -1
- package/dist/tools/report-issue.js +0 -3
- package/dist/tools/report-issue.js.map +1 -1
- package/dist/tools/royalties.d.ts.map +1 -1
- package/dist/tools/royalties.js +3 -18
- package/dist/tools/royalties.js.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +1 -10
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/send.d.ts.map +1 -1
- package/dist/tools/send.js +0 -9
- package/dist/tools/send.js.map +1 -1
- package/dist/tools/sessions.d.ts.map +1 -1
- package/dist/tools/sessions.js +0 -12
- package/dist/tools/sessions.js.map +1 -1
- package/dist/tools/settings.d.ts.map +1 -1
- package/dist/tools/settings.js +3 -30
- package/dist/tools/settings.js.map +1 -1
- package/dist/tools/share-links.d.ts.map +1 -1
- package/dist/tools/share-links.js +0 -15
- package/dist/tools/share-links.js.map +1 -1
- package/dist/tools/signup.d.ts.map +1 -1
- package/dist/tools/signup.js +0 -3
- package/dist/tools/signup.js.map +1 -1
- package/dist/tools/split-sheets.d.ts.map +1 -1
- package/dist/tools/split-sheets.js +1 -22
- package/dist/tools/split-sheets.js.map +1 -1
- package/dist/tools/storage-config.d.ts.map +1 -1
- package/dist/tools/storage-config.js +0 -6
- package/dist/tools/storage-config.js.map +1 -1
- package/dist/tools/subscription.d.ts.map +1 -1
- package/dist/tools/subscription.js +10 -9
- package/dist/tools/subscription.js.map +1 -1
- package/dist/tools/sync-placements.d.ts.map +1 -1
- package/dist/tools/sync-placements.js +2 -20
- package/dist/tools/sync-placements.js.map +1 -1
- package/dist/tools/team.d.ts.map +1 -1
- package/dist/tools/team.js +0 -15
- package/dist/tools/team.js.map +1 -1
- package/dist/tools/telegram.d.ts.map +1 -1
- package/dist/tools/telegram.js +0 -9
- package/dist/tools/telegram.js.map +1 -1
- package/dist/tools/uploads.d.ts.map +1 -1
- package/dist/tools/uploads.js +0 -6
- package/dist/tools/uploads.js.map +1 -1
- package/dist/tools/works.d.ts.map +1 -1
- package/dist/tools/works.js +3 -37
- package/dist/tools/works.js.map +1 -1
- package/package.json +6 -7
- package/server.json +2 -2
- package/dist/prompts/creator-question-atlas.d.ts +0 -48
- package/dist/prompts/creator-question-atlas.d.ts.map +0 -1
- package/dist/prompts/creator-question-atlas.js +0 -618
- package/dist/prompts/creator-question-atlas.js.map +0 -1
- package/dist/skills/index.d.ts +0 -42
- package/dist/skills/index.d.ts.map +0 -1
- package/dist/skills/index.js +0 -59
- package/dist/skills/index.js.map +0 -1
- package/dist/skills/skills.generated.d.ts +0 -25
- package/dist/skills/skills.generated.d.ts.map +0 -1
- package/dist/skills/skills.generated.js +0 -86
- package/dist/skills/skills.generated.js.map +0 -1
- package/dist/tools/access-simulate.d.ts +0 -23
- package/dist/tools/access-simulate.d.ts.map +0 -1
- package/dist/tools/access-simulate.js +0 -165
- package/dist/tools/access-simulate.js.map +0 -1
- package/dist/tools/explainability.d.ts +0 -24
- package/dist/tools/explainability.d.ts.map +0 -1
- package/dist/tools/explainability.js +0 -137
- package/dist/tools/explainability.js.map +0 -1
- package/dist/tools/my-recent-questions.d.ts +0 -25
- package/dist/tools/my-recent-questions.d.ts.map +0 -1
- package/dist/tools/my-recent-questions.js +0 -186
- package/dist/tools/my-recent-questions.js.map +0 -1
- package/dist/tools/share-send.d.ts +0 -28
- package/dist/tools/share-send.d.ts.map +0 -1
- package/dist/tools/share-send.js +0 -131
- package/dist/tools/share-send.js.map +0 -1
- package/dist/tools/sharing.d.ts +0 -29
- package/dist/tools/sharing.d.ts.map +0 -1
- package/dist/tools/sharing.js +0 -131
- package/dist/tools/sharing.js.map +0 -1
- package/dist/tools/skills.d.ts +0 -25
- package/dist/tools/skills.d.ts.map +0 -1
- package/dist/tools/skills.js +0 -144
- package/dist/tools/skills.js.map +0 -1
- package/scripts/build-skills.ts +0 -229
package/dist/tools/sharing.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
-
import { formatSuccess } from "@withpica/mcp-utils";
|
|
3
|
-
export class SharingTools {
|
|
4
|
-
pica;
|
|
5
|
-
constructor(pica) {
|
|
6
|
-
this.pica = pica;
|
|
7
|
-
}
|
|
8
|
-
getTools() {
|
|
9
|
-
return [
|
|
10
|
-
{
|
|
11
|
-
definition: {
|
|
12
|
-
name: "pica_share_trace",
|
|
13
|
-
tier: "read",
|
|
14
|
-
description: "Use when the user asks: 'why does Tony have access to this song?', 'who can see this work?', 'how did this person see my recording?'. " +
|
|
15
|
-
"Returns the chain of reasons a viewer (user or org) can see an entity. " +
|
|
16
|
-
"Composes four substrates — org membership, custody chain, share links, cross-org grants — and ranks reasons by directness. " +
|
|
17
|
-
"Two-axis access: 403 INSUFFICIENT_SCOPE if you don't own the entity; has_access:false with reasons:[] when you DO own it but the viewer can't see. " +
|
|
18
|
-
"→ then: pica_share_links_list / pica_share_links_revoke (revoke a share_link reason), pica_works_inspect / pica_recordings_inspect (verify state)",
|
|
19
|
-
workflows: "infrastructure",
|
|
20
|
-
vernacular_kind: "creator-entry",
|
|
21
|
-
inputSchema: {
|
|
22
|
-
type: "object",
|
|
23
|
-
properties: {
|
|
24
|
-
entity_type: {
|
|
25
|
-
type: "string",
|
|
26
|
-
enum: ["work", "recording", "person"],
|
|
27
|
-
description: "What kind of entity to trace access to. Persons only support the org_membership substrate (no work-scoped reasons apply).",
|
|
28
|
-
},
|
|
29
|
-
entity_id: {
|
|
30
|
-
type: "string",
|
|
31
|
-
description: "UUID of the work, recording, or person.",
|
|
32
|
-
},
|
|
33
|
-
viewer_user_id: {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "UUID of the user whose access we're tracing. Supply EITHER viewer_user_id OR viewer_org_id, not both.",
|
|
36
|
-
},
|
|
37
|
-
viewer_org_id: {
|
|
38
|
-
type: "string",
|
|
39
|
-
description: "UUID of the org whose access we're tracing. Supply EITHER viewer_user_id OR viewer_org_id, not both.",
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
required: ["entity_type", "entity_id"],
|
|
43
|
-
},
|
|
44
|
-
nextSteps: [
|
|
45
|
-
{
|
|
46
|
-
tool: "pica_share_links_list",
|
|
47
|
-
reason: "When the trace surfaces a share_link reason, list links for the work to find the right one to revoke.",
|
|
48
|
-
when: "on_success",
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
tool: "pica_works_inspect",
|
|
52
|
-
reason: "Inspect the work to see related metadata when investigating sharing.",
|
|
53
|
-
when: "on_success",
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
executor: this.shareTrace.bind(this),
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
}
|
|
61
|
-
async shareTrace(args) {
|
|
62
|
-
const entityType = args.entity_type;
|
|
63
|
-
const entityId = args.entity_id;
|
|
64
|
-
const viewerUserId = args.viewer_user_id;
|
|
65
|
-
const viewerOrgId = args.viewer_org_id;
|
|
66
|
-
if (!entityType ||
|
|
67
|
-
!["work", "recording", "person"].includes(entityType)) {
|
|
68
|
-
return {
|
|
69
|
-
content: [
|
|
70
|
-
{
|
|
71
|
-
type: "text",
|
|
72
|
-
text: "entity_type must be 'work', 'recording', or 'person'.",
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
isError: true,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
if (!entityId) {
|
|
79
|
-
return {
|
|
80
|
-
content: [{ type: "text", text: "entity_id is required." }],
|
|
81
|
-
isError: true,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (Boolean(viewerUserId) === Boolean(viewerOrgId)) {
|
|
85
|
-
return {
|
|
86
|
-
content: [
|
|
87
|
-
{
|
|
88
|
-
type: "text",
|
|
89
|
-
text: "supply exactly one of viewer_user_id or viewer_org_id.",
|
|
90
|
-
},
|
|
91
|
-
],
|
|
92
|
-
isError: true,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
const result = await this.pica.shareTrace.trace({
|
|
97
|
-
entity_type: entityType,
|
|
98
|
-
entity_id: entityId,
|
|
99
|
-
viewer_user_id: viewerUserId,
|
|
100
|
-
viewer_org_id: viewerOrgId,
|
|
101
|
-
});
|
|
102
|
-
const verdict = result.has_access
|
|
103
|
-
? `Access via ${result.reasons.length} reason${result.reasons.length === 1 ? "" : "s"} (most-direct: ${result.reasons[0]?.kind})`
|
|
104
|
-
: "No access — viewer cannot see this entity";
|
|
105
|
-
return formatSuccess(verdict, result);
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
109
|
-
// 403 INSUFFICIENT_SCOPE bubbles up as a fetch error from the
|
|
110
|
-
// SDK — surface it without leaking entity existence.
|
|
111
|
-
if (/INSUFFICIENT_SCOPE|insufficient_scope|403/i.test(errorMessage)) {
|
|
112
|
-
return {
|
|
113
|
-
content: [
|
|
114
|
-
{
|
|
115
|
-
type: "text",
|
|
116
|
-
text: `entity is not in scope for this organisation — only the entity's owning org can trace its sharing graph.`,
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
isError: true,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
content: [
|
|
124
|
-
{ type: "text", text: `Failed to trace sharing: ${errorMessage}` },
|
|
125
|
-
],
|
|
126
|
-
isError: true,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
//# sourceMappingURL=sharing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sharing.js","sourceRoot":"","sources":["../../src/tools/sharing.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/skills.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill tools — ADR-140 Phase 2b
|
|
3
|
-
*
|
|
4
|
-
* Two meta-tools, not N wrapper tools (which would inflate the registry and
|
|
5
|
-
* load every body eagerly). Mirrors the _inspect-sections lazy-slicing shape:
|
|
6
|
-
* - pica_skill_list — tiny summary (names + triggers + audience), cheap
|
|
7
|
-
* - pica_skill_get — full methodology body, loaded only on demand
|
|
8
|
-
*
|
|
9
|
-
* The same content is reachable via skill:// resources (SEP-2640 bridge),
|
|
10
|
-
* so clients that natively read skill:// URIs don't need these tools — but
|
|
11
|
-
* every current client supports tools and not every client reads skill://
|
|
12
|
-
* yet, so the tool lane is the today-it-works fallback.
|
|
13
|
-
*/
|
|
14
|
-
import { ToolDefinition, ToolExecutor } from "./index.js";
|
|
15
|
-
export declare class SkillsTools {
|
|
16
|
-
private registry;
|
|
17
|
-
constructor();
|
|
18
|
-
getTools(): Array<{
|
|
19
|
-
definition: ToolDefinition;
|
|
20
|
-
executor: ToolExecutor;
|
|
21
|
-
}>;
|
|
22
|
-
private listSkills;
|
|
23
|
-
private getSkill;
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/tools/skills.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAGtE,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAiB;;IAMjC,QAAQ,IAAI,KAAK,CAAC;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC;YAsD3D,UAAU;YAsBV,QAAQ;CAkEvB"}
|
package/dist/tools/skills.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
-
import { SkillsRegistry, SkillNotFoundError } from "../skills/index.js";
|
|
3
|
-
export class SkillsTools {
|
|
4
|
-
registry;
|
|
5
|
-
constructor() {
|
|
6
|
-
this.registry = new SkillsRegistry();
|
|
7
|
-
}
|
|
8
|
-
getTools() {
|
|
9
|
-
return [
|
|
10
|
-
{
|
|
11
|
-
definition: {
|
|
12
|
-
name: "pica_skill_list",
|
|
13
|
-
tier: "read",
|
|
14
|
-
description: "Use when the user asks: 'what catalog workflows are available?', 'what can you help me do with my songs?', 'show me my workflow options'. " +
|
|
15
|
-
"Returns the list of downloadable PICA skill methodologies — name, one-line description, and trigger phrases. " +
|
|
16
|
-
"Cheap to call. Use pica_skill_get(name) to load a specific skill's full methodology body when you're ready to follow it.",
|
|
17
|
-
workflows: "infrastructure",
|
|
18
|
-
vernacular_kind: "creator-entry",
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {},
|
|
22
|
-
additionalProperties: false,
|
|
23
|
-
},
|
|
24
|
-
annotations: {
|
|
25
|
-
readOnlyHint: true,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
executor: this.listSkills.bind(this),
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
definition: {
|
|
32
|
-
name: "pica_skill_get",
|
|
33
|
-
tier: "read",
|
|
34
|
-
description: "Use when the user asks: 'audit my catalog', 'register my songs', 'prepare for sync', 'set up my workspace', 'close the loop on this song'. " +
|
|
35
|
-
"Returns the full methodology body for one skill — markdown with step-by-step instructions, tool chains, and offer scripts. " +
|
|
36
|
-
"Call pica_skill_list first to see available skill names, then pica_skill_get to load one. Read once at the start of the workflow; do not re-fetch on every step.",
|
|
37
|
-
workflows: "infrastructure",
|
|
38
|
-
vernacular_kind: "creator-entry",
|
|
39
|
-
inputSchema: {
|
|
40
|
-
type: "object",
|
|
41
|
-
properties: {
|
|
42
|
-
name: {
|
|
43
|
-
type: "string",
|
|
44
|
-
description: "Kebab-case skill name from pica_skill_list (e.g. 'catalog-audit', 'register-my-works', 'prepare-for-sync').",
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
required: ["name"],
|
|
48
|
-
additionalProperties: false,
|
|
49
|
-
},
|
|
50
|
-
annotations: {
|
|
51
|
-
readOnlyHint: true,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
executor: this.getSkill.bind(this),
|
|
55
|
-
},
|
|
56
|
-
];
|
|
57
|
-
}
|
|
58
|
-
async listSkills(_args) {
|
|
59
|
-
const skills = this.registry.listSkills();
|
|
60
|
-
return {
|
|
61
|
-
content: [
|
|
62
|
-
{
|
|
63
|
-
type: "text",
|
|
64
|
-
text: skills.length
|
|
65
|
-
? `Available skills (${skills.length}):\n\n` +
|
|
66
|
-
skills
|
|
67
|
-
.map((s) => `- ${s.name} — ${s.description}\n triggers: ${s.triggers.join(", ")}\n audience: ${s.audience}`)
|
|
68
|
-
.join("\n\n") +
|
|
69
|
-
"\n\nCall pica_skill_get(name) to load a skill's full methodology."
|
|
70
|
-
: "No skills available.",
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
structuredContent: { skills },
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
async getSkill(args) {
|
|
77
|
-
const name = String(args?.name ?? "").trim();
|
|
78
|
-
if (!name) {
|
|
79
|
-
return {
|
|
80
|
-
isError: true,
|
|
81
|
-
content: [
|
|
82
|
-
{
|
|
83
|
-
type: "text",
|
|
84
|
-
text: "Missing required argument: name. Call pica_skill_list to see available skill names.",
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
let skill;
|
|
90
|
-
try {
|
|
91
|
-
skill = this.registry.getSkill(name);
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
if (err instanceof SkillNotFoundError) {
|
|
95
|
-
return {
|
|
96
|
-
isError: true,
|
|
97
|
-
content: [
|
|
98
|
-
{
|
|
99
|
-
type: "text",
|
|
100
|
-
text: `Skill not found: ${name}. Call pica_skill_list to see available skill names.`,
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
throw err;
|
|
106
|
-
}
|
|
107
|
-
const frontmatterSummary = [
|
|
108
|
-
`# ${skill.name}`,
|
|
109
|
-
"",
|
|
110
|
-
`**Description:** ${skill.description}`,
|
|
111
|
-
`**Audience:** ${skill.audience}`,
|
|
112
|
-
`**Triggers:** ${skill.triggers.join(", ")}`,
|
|
113
|
-
`**Tools used:** ${skill.tools_required.join(", ")}`,
|
|
114
|
-
`**Output:** ${skill.output}`,
|
|
115
|
-
"",
|
|
116
|
-
"---",
|
|
117
|
-
"",
|
|
118
|
-
].join("\n");
|
|
119
|
-
return {
|
|
120
|
-
content: [
|
|
121
|
-
{
|
|
122
|
-
type: "text",
|
|
123
|
-
text: frontmatterSummary + skill.body,
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
type: "resource_link",
|
|
127
|
-
uri: `skill://withpica/${skill.name}/SKILL.md`,
|
|
128
|
-
name: `Skill — ${skill.name}`,
|
|
129
|
-
description: skill.description,
|
|
130
|
-
mimeType: "text/markdown",
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
structuredContent: {
|
|
134
|
-
name: skill.name,
|
|
135
|
-
description: skill.description,
|
|
136
|
-
triggers: skill.triggers,
|
|
137
|
-
audience: skill.audience,
|
|
138
|
-
tools_required: skill.tools_required,
|
|
139
|
-
output: skill.output,
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=skills.js.map
|
package/dist/tools/skills.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/tools/skills.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAiB7D,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExE,MAAM,OAAO,WAAW;IACd,QAAQ,CAAiB;IAEjC;QACE,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACvC,CAAC;IAED,QAAQ;QACN,OAAO;YACL;gBACE,UAAU,EAAE;oBACV,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,MAAM;oBACZ,WAAW,EACT,4IAA4I;wBAC5I,+GAA+G;wBAC/G,0HAA0H;oBAC5H,SAAS,EAAE,gBAAgB;oBAC3B,eAAe,EAAE,eAAe;oBAChC,WAAW,EAAE;wBACX,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE,EAAE;wBACd,oBAAoB,EAAE,KAAK;qBAC5B;oBACD,WAAW,EAAE;wBACX,YAAY,EAAE,IAAI;qBACnB;iBACF;gBACD,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;aACrC;YACD;gBACE,UAAU,EAAE;oBACV,IAAI,EAAE,gBAAgB;oBACtB,IAAI,EAAE,MAAM;oBACZ,WAAW,EACT,6IAA6I;wBAC7I,6HAA6H;wBAC7H,kKAAkK;oBACpK,SAAS,EAAE,gBAAgB;oBAC3B,eAAe,EAAE,eAAe;oBAChC,WAAW,EAAE;wBACX,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,IAAI,EAAE;gCACJ,IAAI,EAAE,QAAQ;gCACd,WAAW,EACT,6GAA6G;6BAChH;yBACF;wBACD,QAAQ,EAAE,CAAC,MAAM,CAAC;wBAClB,oBAAoB,EAAE,KAAK;qBAC5B;oBACD,WAAW,EAAE;wBACX,YAAY,EAAE,IAAI;qBACnB;iBACF;gBACD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;aACnC;SACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,KAA0B;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC1C,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,MAAM,CAAC,MAAM;wBACjB,CAAC,CAAC,qBAAqB,MAAM,CAAC,MAAM,QAAQ;4BAC1C,MAAM;iCACH,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,iBAAiB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CACpG;iCACA,IAAI,CAAC,MAAM,CAAC;4BACf,mEAAmE;wBACrE,CAAC,CAAC,sBAAsB;iBAC3B;aACF;YACD,iBAAiB,EAAE,EAAE,MAAM,EAAE;SAC9B,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,IAAyB;QAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,qFAAqF;qBAC5F;iBACF;aACF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,kBAAkB,EAAE,CAAC;gBACtC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,oBAAoB,IAAI,sDAAsD;yBACrF;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,kBAAkB,GAAG;YACzB,KAAK,KAAK,CAAC,IAAI,EAAE;YACjB,EAAE;YACF,oBAAoB,KAAK,CAAC,WAAW,EAAE;YACvC,iBAAiB,KAAK,CAAC,QAAQ,EAAE;YACjC,iBAAiB,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC5C,mBAAmB,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACpD,eAAe,KAAK,CAAC,MAAM,EAAE;YAC7B,EAAE;YACF,KAAK;YACL,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,kBAAkB,GAAG,KAAK,CAAC,IAAI;iBACtC;gBACD;oBACE,IAAI,EAAE,eAAe;oBACrB,GAAG,EAAE,oBAAoB,KAAK,CAAC,IAAI,WAAW;oBAC9C,IAAI,EAAE,WAAW,KAAK,CAAC,IAAI,EAAE;oBAC7B,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,QAAQ,EAAE,eAAe;iBAC1B;aACF;YACD,iBAAiB,EAAE;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB;SACF,CAAC;IACJ,CAAC;CACF"}
|
package/scripts/build-skills.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ADR-140 Phase 2b — generator for `skills.generated.ts`.
|
|
5
|
-
*
|
|
6
|
-
* Reads `src/skills/<name>/SKILL.md` files, parses YAML frontmatter, and emits
|
|
7
|
-
* a TypeScript constant consumed by SkillsRegistry. Generation at build time
|
|
8
|
-
* (not runtime FS reads) so npm-published `dist/` ships bundled bytes — `.md`
|
|
9
|
-
* files are excluded by `.npmignore`.
|
|
10
|
-
*
|
|
11
|
-
* Frontmatter shape:
|
|
12
|
-
* ---
|
|
13
|
-
* name: kebab-case-name
|
|
14
|
-
* description: one-line
|
|
15
|
-
* triggers:
|
|
16
|
-
* - phrase one
|
|
17
|
-
* - phrase two
|
|
18
|
-
* audience: manager / artist / etc
|
|
19
|
-
* tools_required:
|
|
20
|
-
* - tool_a
|
|
21
|
-
* - tool_b
|
|
22
|
-
* output: one-line description
|
|
23
|
-
* ---
|
|
24
|
-
*
|
|
25
|
-
* Hand-rolled YAML parser (frontmatter only — no nested objects, no anchors).
|
|
26
|
-
* Adding a `js-yaml` dep would be overkill for the constrained shape.
|
|
27
|
-
*
|
|
28
|
-
* Re-runs are deterministic: same .md files produce a byte-identical output.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import { readFileSync, readdirSync, writeFileSync, existsSync } from "node:fs";
|
|
32
|
-
import { dirname, join } from "node:path";
|
|
33
|
-
import { fileURLToPath } from "node:url";
|
|
34
|
-
|
|
35
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
36
|
-
const __dirname = dirname(__filename);
|
|
37
|
-
const MCP_SERVER_ROOT = join(__dirname, "..");
|
|
38
|
-
const SKILLS_ROOT = join(MCP_SERVER_ROOT, "src/skills");
|
|
39
|
-
const OUTPUT_PATH = join(SKILLS_ROOT, "skills.generated.ts");
|
|
40
|
-
|
|
41
|
-
interface SkillFrontmatter {
|
|
42
|
-
name: string;
|
|
43
|
-
description: string;
|
|
44
|
-
triggers: string[];
|
|
45
|
-
audience: string;
|
|
46
|
-
tools_required: string[];
|
|
47
|
-
output: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface ParsedSkill extends SkillFrontmatter {
|
|
51
|
-
body: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function parseFrontmatter(src: string, sourceFile: string): ParsedSkill {
|
|
55
|
-
// Strip leading HTML comment (copyright header) if present, then expect ---
|
|
56
|
-
let i = 0;
|
|
57
|
-
if (src.startsWith("<!--")) {
|
|
58
|
-
const end = src.indexOf("-->");
|
|
59
|
-
if (end === -1) {
|
|
60
|
-
throw new Error(`${sourceFile}: unterminated HTML comment header`);
|
|
61
|
-
}
|
|
62
|
-
i = end + 3;
|
|
63
|
-
// Skip whitespace/newlines
|
|
64
|
-
while (i < src.length && /\s/.test(src[i])) i++;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (src.slice(i, i + 3) !== "---") {
|
|
68
|
-
throw new Error(`${sourceFile}: missing --- frontmatter opener`);
|
|
69
|
-
}
|
|
70
|
-
i += 3;
|
|
71
|
-
// Skip newline after opener
|
|
72
|
-
while (i < src.length && src[i] !== "\n") i++;
|
|
73
|
-
i++;
|
|
74
|
-
|
|
75
|
-
const closeIdx = src.indexOf("\n---", i);
|
|
76
|
-
if (closeIdx === -1) {
|
|
77
|
-
throw new Error(`${sourceFile}: missing --- frontmatter closer`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const frontmatterText = src.slice(i, closeIdx);
|
|
81
|
-
const bodyStart = closeIdx + 4; // skip \n---
|
|
82
|
-
const body = src.slice(bodyStart).replace(/^\n+/, "").trimEnd() + "\n";
|
|
83
|
-
|
|
84
|
-
// Parse: key: value OR key: (list follows)
|
|
85
|
-
const fm: Record<string, string | string[]> = {};
|
|
86
|
-
const lines = frontmatterText.split("\n");
|
|
87
|
-
let currentListKey: string | null = null;
|
|
88
|
-
|
|
89
|
-
for (const line of lines) {
|
|
90
|
-
if (line.trim() === "") {
|
|
91
|
-
currentListKey = null;
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
const listItemMatch = line.match(/^\s+-\s+(.+)$/);
|
|
95
|
-
if (listItemMatch && currentListKey) {
|
|
96
|
-
(fm[currentListKey] as string[]).push(listItemMatch[1].trim());
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const kvMatch = line.match(/^([a-z_][a-z0-9_]*)\s*:\s*(.*)$/i);
|
|
100
|
-
if (!kvMatch) continue;
|
|
101
|
-
const key = kvMatch[1];
|
|
102
|
-
const value = kvMatch[2].trim();
|
|
103
|
-
if (value === "") {
|
|
104
|
-
// List follows
|
|
105
|
-
fm[key] = [];
|
|
106
|
-
currentListKey = key;
|
|
107
|
-
} else {
|
|
108
|
-
fm[key] = value;
|
|
109
|
-
currentListKey = null;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Validate required fields
|
|
114
|
-
const required = [
|
|
115
|
-
"name",
|
|
116
|
-
"description",
|
|
117
|
-
"triggers",
|
|
118
|
-
"audience",
|
|
119
|
-
"tools_required",
|
|
120
|
-
"output",
|
|
121
|
-
];
|
|
122
|
-
for (const field of required) {
|
|
123
|
-
if (!(field in fm)) {
|
|
124
|
-
throw new Error(`${sourceFile}: missing required frontmatter field "${field}"`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
if (!Array.isArray(fm.triggers) || fm.triggers.length === 0) {
|
|
128
|
-
throw new Error(`${sourceFile}: triggers must be a non-empty list`);
|
|
129
|
-
}
|
|
130
|
-
if (!Array.isArray(fm.tools_required) || fm.tools_required.length === 0) {
|
|
131
|
-
throw new Error(`${sourceFile}: tools_required must be a non-empty list`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
name: fm.name as string,
|
|
136
|
-
description: fm.description as string,
|
|
137
|
-
triggers: fm.triggers as string[],
|
|
138
|
-
audience: fm.audience as string,
|
|
139
|
-
tools_required: fm.tools_required as string[],
|
|
140
|
-
output: fm.output as string,
|
|
141
|
-
body,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function discoverSkills(): ParsedSkill[] {
|
|
146
|
-
if (!existsSync(SKILLS_ROOT)) {
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
const entries = readdirSync(SKILLS_ROOT, { withFileTypes: true });
|
|
150
|
-
const skills: ParsedSkill[] = [];
|
|
151
|
-
for (const entry of entries) {
|
|
152
|
-
if (!entry.isDirectory()) continue;
|
|
153
|
-
const skillFile = join(SKILLS_ROOT, entry.name, "SKILL.md");
|
|
154
|
-
if (!existsSync(skillFile)) continue;
|
|
155
|
-
const src = readFileSync(skillFile, "utf-8");
|
|
156
|
-
const parsed = parseFrontmatter(src, `src/skills/${entry.name}/SKILL.md`);
|
|
157
|
-
if (parsed.name !== entry.name) {
|
|
158
|
-
throw new Error(
|
|
159
|
-
`src/skills/${entry.name}/SKILL.md: frontmatter name "${parsed.name}" must match directory name "${entry.name}"`,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
skills.push(parsed);
|
|
163
|
-
}
|
|
164
|
-
skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
165
|
-
return skills;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function emit(skills: ParsedSkill[]): string {
|
|
169
|
-
const header = `// Copyright (c) 2024-2026 Withpica Ltd. All rights reserved.
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* GENERATED FILE — DO NOT EDIT BY HAND.
|
|
173
|
-
*
|
|
174
|
-
* Regenerated by \`scripts/build-skills.ts\` from \`src/skills/<name>/SKILL.md\`.
|
|
175
|
-
* Runs in \`prebuild\` and \`prepublishOnly\`. See ADR-140 Phase 2b.
|
|
176
|
-
*/
|
|
177
|
-
|
|
178
|
-
export interface Skill {
|
|
179
|
-
/** Stable kebab-case identifier matching the directory name. */
|
|
180
|
-
name: string;
|
|
181
|
-
/** One-line description shown in pica_skill_list. */
|
|
182
|
-
description: string;
|
|
183
|
-
/** Trigger phrases an agent should recognise as invoking this skill. */
|
|
184
|
-
triggers: string[];
|
|
185
|
-
/** Audience tag (manager / artist / sync supervisor / etc). */
|
|
186
|
-
audience: string;
|
|
187
|
-
/** Tools the skill body chains. Lint-checkable. */
|
|
188
|
-
tools_required: string[];
|
|
189
|
-
/** One-line output shape description. */
|
|
190
|
-
output: string;
|
|
191
|
-
/** Full skill methodology body — markdown, exposed by pica_skill_get. */
|
|
192
|
-
body: string;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
`;
|
|
196
|
-
const lines: string[] = [header, "export const SKILLS: Record<string, Skill> = {"];
|
|
197
|
-
for (const skill of skills) {
|
|
198
|
-
lines.push(` ${JSON.stringify(skill.name)}: {`);
|
|
199
|
-
lines.push(` name: ${JSON.stringify(skill.name)},`);
|
|
200
|
-
lines.push(` description: ${JSON.stringify(skill.description)},`);
|
|
201
|
-
lines.push(` triggers: ${JSON.stringify(skill.triggers)},`);
|
|
202
|
-
lines.push(` audience: ${JSON.stringify(skill.audience)},`);
|
|
203
|
-
lines.push(` tools_required: ${JSON.stringify(skill.tools_required)},`);
|
|
204
|
-
lines.push(` output: ${JSON.stringify(skill.output)},`);
|
|
205
|
-
lines.push(` body: ${JSON.stringify(skill.body)},`);
|
|
206
|
-
lines.push(` },`);
|
|
207
|
-
}
|
|
208
|
-
lines.push("};");
|
|
209
|
-
lines.push("");
|
|
210
|
-
lines.push(
|
|
211
|
-
`export const SKILL_NAMES: ReadonlyArray<string> = ${JSON.stringify(skills.map((s) => s.name))};`,
|
|
212
|
-
);
|
|
213
|
-
lines.push("");
|
|
214
|
-
return lines.join("\n");
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function main(): void {
|
|
218
|
-
const skills = discoverSkills();
|
|
219
|
-
const output = emit(skills);
|
|
220
|
-
writeFileSync(OUTPUT_PATH, output, "utf-8");
|
|
221
|
-
console.log(
|
|
222
|
-
`[build-skills] Wrote ${skills.length} skill(s) to src/skills/skills.generated.ts`,
|
|
223
|
-
);
|
|
224
|
-
for (const skill of skills) {
|
|
225
|
-
console.log(` - ${skill.name} (${skill.body.length} bytes body)`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
main();
|