@fprad0/skill-master-mcp 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +168 -0
  3. package/VERSION.md +9 -0
  4. package/bin/skill-master-configure-private-registry.mjs +3 -0
  5. package/bin/skill-master.mjs +3 -0
  6. package/dist/catalog.d.ts +11 -0
  7. package/dist/catalog.d.ts.map +1 -0
  8. package/dist/catalog.js +202 -0
  9. package/dist/catalog.js.map +1 -0
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +284 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/recommender.d.ts +6 -0
  15. package/dist/recommender.d.ts.map +1 -0
  16. package/dist/recommender.js +102 -0
  17. package/dist/recommender.js.map +1 -0
  18. package/dist/skill-network.d.ts +67 -0
  19. package/dist/skill-network.d.ts.map +1 -0
  20. package/dist/skill-network.js +226 -0
  21. package/dist/skill-network.js.map +1 -0
  22. package/dist/types.d.ts +89 -0
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js +2 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/update.d.ts +45 -0
  27. package/dist/update.d.ts.map +1 -0
  28. package/dist/update.js +288 -0
  29. package/dist/update.js.map +1 -0
  30. package/docs/operations/GUIA_NPM_PRIVADO.md +250 -0
  31. package/examples/client-configs/claude-code.commands.md +17 -0
  32. package/examples/client-configs/claude-code.project.mcp.json +18 -0
  33. package/examples/client-configs/claude-desktop.macos.json +18 -0
  34. package/examples/client-configs/claude-desktop.windows.json +20 -0
  35. package/examples/client-configs/codex.windows.toml +11 -0
  36. package/examples/client-configs/gemini-code-assist.intellij.mcp.json +18 -0
  37. package/examples/client-configs/gemini.linux.settings.json +21 -0
  38. package/examples/client-configs/gemini.windows.settings.json +23 -0
  39. package/examples/client-configs/generic-stdio.json +16 -0
  40. package/manifests/channels/beta.json +25 -0
  41. package/manifests/channels/stable.json +26 -0
  42. package/network/approved-skills.json +5 -0
  43. package/package.json +60 -0
  44. package/scripts/configure-private-registry.mjs +124 -0
  45. package/scripts/lib/private-registry.mjs +56 -0
  46. package/sources.json +8 -0
@@ -0,0 +1,226 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ const CONTRIBUTION_SCHEMA_VERSION = 'skill-master-contribution-v1';
5
+ const POLICY_VERSION = 'safe-skill-network-v1';
6
+ const MAX_SKILL_SCAN_BYTES = 512_000;
7
+ const normalizeSkillName = (value) => value
8
+ .normalize('NFD')
9
+ .replace(/[\u0300-\u036f]/g, '')
10
+ .toLowerCase()
11
+ .trim();
12
+ const hashValue = (value) => createHash('sha256').update(value).digest('hex');
13
+ const redactSensitive = (value) => value
14
+ .replace(/(sk-[a-zA-Z0-9_-]{16,})/g, '[REDACTED_OPENAI_KEY]')
15
+ .replace(/(gh[pousr]_[a-zA-Z0-9_]{20,})/g, '[REDACTED_GITHUB_TOKEN]')
16
+ .replace(/([A-Za-z0-9+/]{32,}={0,2})/g, '[REDACTED_LONG_TOKEN]');
17
+ const safeLocationHint = (location) => {
18
+ if (/^https?:\/\//i.test(location)) {
19
+ try {
20
+ const url = new URL(location);
21
+ return `${url.hostname}${url.pathname.split('/').slice(-3).join('/')}`;
22
+ }
23
+ catch {
24
+ return 'remote/SKILL.md';
25
+ }
26
+ }
27
+ const parent = path.basename(path.dirname(location));
28
+ return `${parent}/SKILL.md`;
29
+ };
30
+ const isContributionScope = (sourceKind) => sourceKind === 'local' || sourceKind === 'workspace' || sourceKind === 'plugin';
31
+ const readSkillMarkdownForRiskScan = async (skill) => {
32
+ if (/^https?:\/\//i.test(skill.location)) {
33
+ return '';
34
+ }
35
+ try {
36
+ const stats = await fs.stat(skill.location);
37
+ if (!stats.isFile() || stats.size > MAX_SKILL_SCAN_BYTES) {
38
+ return '';
39
+ }
40
+ return await fs.readFile(skill.location, 'utf8');
41
+ }
42
+ catch {
43
+ return '';
44
+ }
45
+ };
46
+ const detectRiskFlags = (markdown) => {
47
+ const flags = new Set();
48
+ const content = markdown.toLowerCase();
49
+ if (/curl\s+[^|\n]+\|\s*(sh|bash)/i.test(markdown))
50
+ flags.add('shell-pipe-download');
51
+ if (/iwr\s+[^|\n]+\|\s*iex/i.test(markdown) || /invoke-webrequest[\s\S]{0,120}iex/i.test(markdown))
52
+ flags.add('powershell-download-exec');
53
+ if (/powershell(\.exe)?\s+-enc(odedcommand)?/i.test(markdown))
54
+ flags.add('encoded-powershell');
55
+ if (/\brm\s+-rf\s+(\/|\$HOME|~)/i.test(markdown))
56
+ flags.add('destructive-shell-command');
57
+ if (/\b(eval|exec)\s*\(/i.test(markdown))
58
+ flags.add('dynamic-code-execution');
59
+ if (/sk-[a-zA-Z0-9_-]{16,}/.test(markdown) || /gh[pousr]_[a-zA-Z0-9_]{20,}/.test(markdown))
60
+ flags.add('possible-secret');
61
+ if (content.includes('disable antivirus') || content.includes('bypass antivirus'))
62
+ flags.add('evasion-language');
63
+ return [...flags].sort();
64
+ };
65
+ export const emptyApprovedSkillIndex = () => ({
66
+ generatedAt: new Date(0).toISOString(),
67
+ policyVersion: POLICY_VERSION,
68
+ skills: [],
69
+ });
70
+ export const readApprovedSkillIndex = async (indexPath) => {
71
+ try {
72
+ const raw = await fs.readFile(indexPath, 'utf8');
73
+ const parsed = JSON.parse(raw);
74
+ return {
75
+ generatedAt: parsed.generatedAt,
76
+ policyVersion: parsed.policyVersion,
77
+ skills: Array.isArray(parsed.skills) ? parsed.skills : [],
78
+ };
79
+ }
80
+ catch {
81
+ return emptyApprovedSkillIndex();
82
+ }
83
+ };
84
+ export const prepareSkillContribution = async ({ snapshotSkills, approvedIndex, outputDir, machineLabel, includeBodyPreview, includeWorkspace, includePlugin, maxCandidates, }) => {
85
+ const knownNames = new Set(approvedIndex.skills.map((skill) => normalizeSkillName(skill.name)));
86
+ const knownHashes = new Set(approvedIndex.skills.map((skill) => skill.contentHash));
87
+ const candidates = [];
88
+ const skipped = {
89
+ alreadyKnownByName: 0,
90
+ alreadyKnownByHash: 0,
91
+ unsupportedSource: 0,
92
+ missingContentHash: 0,
93
+ };
94
+ for (const skill of snapshotSkills) {
95
+ if (!isContributionScope(skill.sourceKind)) {
96
+ skipped.unsupportedSource += 1;
97
+ continue;
98
+ }
99
+ if (skill.sourceKind === 'workspace' && !includeWorkspace) {
100
+ skipped.unsupportedSource += 1;
101
+ continue;
102
+ }
103
+ if (skill.sourceKind === 'plugin' && !includePlugin) {
104
+ skipped.unsupportedSource += 1;
105
+ continue;
106
+ }
107
+ if (!skill.contentHash) {
108
+ skipped.missingContentHash += 1;
109
+ continue;
110
+ }
111
+ if (knownHashes.has(skill.contentHash)) {
112
+ skipped.alreadyKnownByHash += 1;
113
+ continue;
114
+ }
115
+ if (knownNames.has(normalizeSkillName(skill.name))) {
116
+ skipped.alreadyKnownByName += 1;
117
+ continue;
118
+ }
119
+ const markdown = await readSkillMarkdownForRiskScan(skill);
120
+ const riskFlags = detectRiskFlags(markdown);
121
+ const bodyPreview = includeBodyPreview
122
+ ? redactSensitive(markdown.replace(/\s+/g, ' ').trim()).slice(0, 800)
123
+ : undefined;
124
+ candidates.push({
125
+ name: skill.name,
126
+ description: skill.description,
127
+ contentHash: skill.contentHash,
128
+ sourceKind: skill.sourceKind,
129
+ sourceLabel: skill.sourceLabel,
130
+ locationHint: safeLocationHint(skill.location),
131
+ locationHash: hashValue(skill.location),
132
+ headings: skill.headings.slice(0, 20),
133
+ keywords: skill.keywords.slice(0, 30),
134
+ modifiedAt: skill.modifiedAt,
135
+ riskFlags,
136
+ ...(bodyPreview ? { bodyPreview } : {}),
137
+ });
138
+ if (candidates.length >= maxCandidates) {
139
+ break;
140
+ }
141
+ }
142
+ const draft = {
143
+ schemaVersion: CONTRIBUTION_SCHEMA_VERSION,
144
+ generatedAt: new Date().toISOString(),
145
+ policyVersion: POLICY_VERSION,
146
+ ...(machineLabel ? { machineLabel } : {}),
147
+ privacy: {
148
+ fullPathsIncluded: false,
149
+ rawSkillBodiesIncluded: false,
150
+ bodyPreviewIncluded: includeBodyPreview,
151
+ },
152
+ candidates,
153
+ skipped,
154
+ };
155
+ await fs.mkdir(outputDir, { recursive: true });
156
+ const timestamp = draft.generatedAt.replace(/[:.]/g, '-');
157
+ const filePath = path.join(outputDir, `skill-contribution-${timestamp}.json`);
158
+ await fs.writeFile(filePath, JSON.stringify(draft, null, 2), 'utf8');
159
+ return { draft, filePath };
160
+ };
161
+ export const reviewSkillContribution = async ({ contributionPath, approvedIndex, }) => {
162
+ let draft;
163
+ try {
164
+ draft = JSON.parse(await fs.readFile(contributionPath, 'utf8'));
165
+ }
166
+ catch {
167
+ return {
168
+ schemaVersion: 'unknown',
169
+ totalCandidates: 0,
170
+ highRiskCandidates: 0,
171
+ alreadyApprovedByHash: 0,
172
+ alreadyApprovedByName: 0,
173
+ recommendation: 'invalid',
174
+ findings: ['Contribution file could not be parsed as JSON.'],
175
+ };
176
+ }
177
+ if (draft.schemaVersion !== CONTRIBUTION_SCHEMA_VERSION || !Array.isArray(draft.candidates)) {
178
+ return {
179
+ schemaVersion: draft.schemaVersion ?? 'unknown',
180
+ generatedAt: draft.generatedAt,
181
+ totalCandidates: 0,
182
+ highRiskCandidates: 0,
183
+ alreadyApprovedByHash: 0,
184
+ alreadyApprovedByName: 0,
185
+ recommendation: 'invalid',
186
+ findings: ['Contribution schema is not supported.'],
187
+ };
188
+ }
189
+ const knownNames = new Set(approvedIndex.skills.map((skill) => normalizeSkillName(skill.name)));
190
+ const knownHashes = new Set(approvedIndex.skills.map((skill) => skill.contentHash));
191
+ const highRiskTerms = new Set([
192
+ 'possible-secret',
193
+ 'shell-pipe-download',
194
+ 'powershell-download-exec',
195
+ 'encoded-powershell',
196
+ 'destructive-shell-command',
197
+ 'evasion-language',
198
+ ]);
199
+ const highRiskCandidates = draft.candidates.filter((candidate) => candidate.riskFlags.some((flag) => highRiskTerms.has(flag)));
200
+ const alreadyApprovedByHash = draft.candidates.filter((candidate) => knownHashes.has(candidate.contentHash)).length;
201
+ const alreadyApprovedByName = draft.candidates.filter((candidate) => knownNames.has(normalizeSkillName(candidate.name))).length;
202
+ const findings = [];
203
+ if (draft.privacy.fullPathsIncluded)
204
+ findings.push('Full paths are included; reject or sanitize before sharing.');
205
+ if (draft.privacy.rawSkillBodiesIncluded)
206
+ findings.push('Raw skill bodies are included; reject unless manually reviewed.');
207
+ if (highRiskCandidates.length > 0)
208
+ findings.push(`${highRiskCandidates.length} candidate(s) contain high-risk flags.`);
209
+ if (alreadyApprovedByHash > 0)
210
+ findings.push(`${alreadyApprovedByHash} candidate(s) already exist by content hash.`);
211
+ if (alreadyApprovedByName > 0)
212
+ findings.push(`${alreadyApprovedByName} candidate(s) already exist by normalized name.`);
213
+ if (findings.length === 0)
214
+ findings.push('No blocking issue found. Human review is still required before approval.');
215
+ return {
216
+ schemaVersion: draft.schemaVersion,
217
+ generatedAt: draft.generatedAt,
218
+ totalCandidates: draft.candidates.length,
219
+ highRiskCandidates: highRiskCandidates.length,
220
+ alreadyApprovedByHash,
221
+ alreadyApprovedByName,
222
+ recommendation: highRiskCandidates.length > 0 ? 'needs-human-security-review' : 'safe-to-review',
223
+ findings,
224
+ };
225
+ };
226
+ //# sourceMappingURL=skill-network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-network.js","sourceRoot":"","sources":["../src/skill-network.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ export type SkillSourceKind = 'workspace' | 'local' | 'plugin' | 'web';
2
+ export type SkillRecord = {
3
+ id: string;
4
+ name: string;
5
+ description: string;
6
+ contentHash?: string;
7
+ sourceKind: SkillSourceKind;
8
+ sourceLabel: string;
9
+ location: string;
10
+ headings: string[];
11
+ keywords: string[];
12
+ bodyPreview: string;
13
+ trusted: boolean;
14
+ modifiedAt?: string;
15
+ };
16
+ export type CatalogSnapshot = {
17
+ generatedAt: string;
18
+ skills: SkillRecord[];
19
+ warnings: string[];
20
+ };
21
+ export type WebSource = {
22
+ name: string;
23
+ type: 'github-tree';
24
+ repository: string;
25
+ branch: string;
26
+ enabled: boolean;
27
+ };
28
+ export type SourcesConfig = {
29
+ localRoots: string[];
30
+ workspaceRoots: string[];
31
+ webSources: WebSource[];
32
+ };
33
+ export type Recommendation = {
34
+ skill: SkillRecord;
35
+ score: number;
36
+ reasons: string[];
37
+ phase: string;
38
+ required: boolean;
39
+ };
40
+ export type RemoteManifest = {
41
+ name: string;
42
+ channel: string;
43
+ version: string;
44
+ semver: string;
45
+ publishedAt: string;
46
+ git: {
47
+ repo: string;
48
+ branch: string;
49
+ commit: string;
50
+ };
51
+ node: {
52
+ minimum: string;
53
+ };
54
+ update: {
55
+ strategy: string;
56
+ requiresCleanTree: boolean;
57
+ installCommand?: string;
58
+ buildCommand?: string;
59
+ };
60
+ changelog: string[];
61
+ };
62
+ export type SyncStatus = {
63
+ localVersion: string;
64
+ localSemver: string;
65
+ localCommit: string;
66
+ localBranch: string;
67
+ localClean: boolean;
68
+ remoteVersion?: string;
69
+ remoteSemver?: string;
70
+ remoteCommit?: string;
71
+ remotePublishedAt?: string;
72
+ updateAvailable: boolean;
73
+ recommendedAction: string;
74
+ manifestSource: string;
75
+ };
76
+ export type ApprovedSkillSummary = {
77
+ name: string;
78
+ description: string;
79
+ contentHash: string;
80
+ sourceKind: SkillSourceKind | 'network';
81
+ approvedAt: string;
82
+ approvedBy?: string;
83
+ };
84
+ export type ApprovedSkillIndex = {
85
+ generatedAt: string;
86
+ policyVersion: string;
87
+ skills: ApprovedSkillSummary[];
88
+ };
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import type { RemoteManifest, SyncStatus } from './types.js';
2
+ export declare const DEFAULT_RELEASE_BRANCH = "main";
3
+ export declare const DEFAULT_UPDATE_CHANNEL = "stable";
4
+ export declare const manifestPathForChannel: (channel: string) => string;
5
+ export declare const buildRecommendedAction: ({ localClean, updateAvailable, channel, branch, packageMode, }: {
6
+ localClean: boolean;
7
+ updateAvailable: boolean;
8
+ channel: string;
9
+ branch: string;
10
+ packageMode: boolean;
11
+ }) => string;
12
+ export declare const buildSuggestedUpdateStep: ({ packageMode, branch, }: {
13
+ packageMode: boolean;
14
+ branch: string;
15
+ }) => string;
16
+ export declare const compareSemver: (left: string, right: string) => number;
17
+ export declare const parseRemoteManifest: (raw: string) => RemoteManifest | null;
18
+ export declare const readVersionFromMarkdown: (versionFile: string) => Promise<{
19
+ version: string;
20
+ semver: string;
21
+ }>;
22
+ export declare const loadRemoteManifest: ({ repoRoot, manifestUrl, branch, channel, }: {
23
+ repoRoot: string;
24
+ manifestUrl: string;
25
+ branch: string;
26
+ channel: string;
27
+ }) => Promise<{
28
+ manifest: RemoteManifest | null;
29
+ source: string;
30
+ }>;
31
+ export declare const buildSyncStatus: (params: {
32
+ repoRoot: string;
33
+ manifestUrl: string;
34
+ versionFile: string;
35
+ branch?: string;
36
+ channel?: string;
37
+ }) => Promise<SyncStatus>;
38
+ export declare const buildUpdatePlan: (params: {
39
+ repoRoot: string;
40
+ manifestUrl: string;
41
+ versionFile: string;
42
+ branch?: string;
43
+ channel?: string;
44
+ }) => Promise<string[]>;
45
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgC7D,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAE/C,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,KAAG,MACnB,CAAC;AAEvC,eAAO,MAAM,sBAAsB,GAAI,gEAMpC;IACD,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB,KAAG,MAcH,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,0BAGtC;IACD,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,KAAG,MAIH,CAAC;AAkBF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,MAmB3D,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,KAAG,cAAc,GAAG,IAMlE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,KAClB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQ7C,CAAC;AA4GF,eAAO,MAAM,kBAAkB,GAAU,6CAKtC;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,KAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA6B9D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,QAAQ;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,OAAO,CAAC,UAAU,CA4DrB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,QAAQ;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KAAG,OAAO,CAAC,MAAM,EAAE,CAmCnB,CAAC"}
package/dist/update.js ADDED
@@ -0,0 +1,288 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import { execFile } from 'node:child_process';
3
+ import { promises as fs } from 'node:fs';
4
+ import { promisify } from 'node:util';
5
+ import { z } from 'zod';
6
+ const execFileAsync = promisify(execFile);
7
+ const manifestSchema = z.object({
8
+ name: z.string(),
9
+ channel: z.string(),
10
+ version: z.string(),
11
+ semver: z.string(),
12
+ publishedAt: z.string(),
13
+ git: z.object({
14
+ repo: z.string(),
15
+ branch: z.string(),
16
+ commit: z.string(),
17
+ }),
18
+ node: z.object({
19
+ minimum: z.string(),
20
+ }),
21
+ update: z.object({
22
+ strategy: z.string(),
23
+ requiresCleanTree: z.boolean(),
24
+ installCommand: z.string(),
25
+ buildCommand: z.string(),
26
+ }),
27
+ changelog: z.array(z.string()),
28
+ });
29
+ const githubContentSchema = z.object({
30
+ content: z.string(),
31
+ encoding: z.string(),
32
+ });
33
+ export const DEFAULT_RELEASE_BRANCH = 'main';
34
+ export const DEFAULT_UPDATE_CHANNEL = 'stable';
35
+ export const manifestPathForChannel = (channel) => `manifests/channels/${channel}.json`;
36
+ export const buildRecommendedAction = ({ localClean, updateAvailable, channel, branch, packageMode, }) => {
37
+ if (!localClean) {
38
+ return 'Ha alteracoes locais; revise antes de atualizar.';
39
+ }
40
+ if (!updateAvailable) {
41
+ return `Versao local alinhada com o canal ${channel}.`;
42
+ }
43
+ if (packageMode) {
44
+ return `Atualizacao disponivel no canal ${channel}. Atualize o pacote no registry privado ou reexecute o cliente MCP com a versao mais recente.`;
45
+ }
46
+ return `Atualizacao disponivel no canal ${channel}. Use git pull --ff-only origin ${branch}, npm ci e npm run build.`;
47
+ };
48
+ export const buildSuggestedUpdateStep = ({ packageMode, branch, }) => (packageMode
49
+ ? 'Passos sugeridos: atualizar o pacote no registry privado -> reiniciar o cliente MCP.'
50
+ : `Passos sugeridos: git pull --ff-only origin ${branch} -> npm ci -> npm run build -> reiniciar o MCP.`);
51
+ const runCommand = async (command, args, cwd) => {
52
+ try {
53
+ const { stdout } = await execFileAsync(command, args, cwd ? { cwd, windowsHide: true } : { windowsHide: true });
54
+ return stdout.trim();
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ };
60
+ const runGit = async (repoRoot, args) => runCommand('git', args, repoRoot);
61
+ export const compareSemver = (left, right) => {
62
+ const leftParts = left.split('.').map((value) => Number(value));
63
+ const rightParts = right.split('.').map((value) => Number(value));
64
+ const size = Math.max(leftParts.length, rightParts.length);
65
+ for (let index = 0; index < size; index += 1) {
66
+ const leftValue = leftParts[index] ?? 0;
67
+ const rightValue = rightParts[index] ?? 0;
68
+ if (leftValue > rightValue) {
69
+ return 1;
70
+ }
71
+ if (leftValue < rightValue) {
72
+ return -1;
73
+ }
74
+ }
75
+ return 0;
76
+ };
77
+ export const parseRemoteManifest = (raw) => {
78
+ try {
79
+ return manifestSchema.parse(JSON.parse(raw));
80
+ }
81
+ catch {
82
+ return null;
83
+ }
84
+ };
85
+ export const readVersionFromMarkdown = async (versionFile) => {
86
+ const raw = await fs.readFile(versionFile, 'utf8');
87
+ const values = [...raw.matchAll(/`([^`]+)`/g)].map((match) => match[1]);
88
+ return {
89
+ version: values[0] ?? '00.01',
90
+ semver: values[1] ?? '0.0.1',
91
+ };
92
+ };
93
+ const loadManifestFromHttp = async (manifestUrl) => {
94
+ try {
95
+ const response = await fetch(manifestUrl, { signal: AbortSignal.timeout(12_000) });
96
+ if (!response.ok) {
97
+ return null;
98
+ }
99
+ return parseRemoteManifest(await response.text());
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ };
105
+ const parseGitHubManifestLocation = (manifestUrl) => {
106
+ try {
107
+ const url = new URL(manifestUrl);
108
+ if (url.hostname === 'raw.githubusercontent.com') {
109
+ const parts = url.pathname.split('/').filter(Boolean);
110
+ if (parts.length < 4) {
111
+ return null;
112
+ }
113
+ const [owner, repo, ref, ...pathParts] = parts;
114
+ return {
115
+ ownerRepo: `${owner}/${repo}`,
116
+ ref,
117
+ path: pathParts.join('/'),
118
+ };
119
+ }
120
+ if (url.hostname === 'github.com') {
121
+ const parts = url.pathname.split('/').filter(Boolean);
122
+ const blobIndex = parts.indexOf('blob');
123
+ if (blobIndex !== 2 || parts.length < 5) {
124
+ return null;
125
+ }
126
+ const [owner, repo] = parts;
127
+ const ref = parts[3];
128
+ const path = parts.slice(4).join('/');
129
+ return {
130
+ ownerRepo: `${owner}/${repo}`,
131
+ ref,
132
+ path,
133
+ };
134
+ }
135
+ return null;
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ };
141
+ const loadManifestFromGitHubCli = async (manifestUrl) => {
142
+ const location = parseGitHubManifestLocation(manifestUrl);
143
+ if (!location) {
144
+ return null;
145
+ }
146
+ const response = await runCommand('gh', [
147
+ 'api',
148
+ `repos/${location.ownerRepo}/contents/${location.path}?ref=${location.ref}`,
149
+ ]);
150
+ if (!response) {
151
+ return null;
152
+ }
153
+ try {
154
+ const payload = githubContentSchema.parse(JSON.parse(response));
155
+ const decoded = Buffer.from(payload.content.replace(/\n/g, ''), payload.encoding).toString('utf8');
156
+ return parseRemoteManifest(decoded);
157
+ }
158
+ catch {
159
+ return null;
160
+ }
161
+ };
162
+ const loadManifestFromGitTracking = async ({ repoRoot, branch, channel, }) => {
163
+ const origin = await runGit(repoRoot, ['remote', 'get-url', 'origin']);
164
+ if (!origin) {
165
+ return null;
166
+ }
167
+ await runGit(repoRoot, ['fetch', 'origin', '--prune']);
168
+ const manifestText = await runGit(repoRoot, [
169
+ 'show',
170
+ `origin/${branch}:${manifestPathForChannel(channel)}`,
171
+ ]);
172
+ return manifestText ? parseRemoteManifest(manifestText) : null;
173
+ };
174
+ export const loadRemoteManifest = async ({ repoRoot, manifestUrl, branch, channel, }) => {
175
+ const fromGit = await loadManifestFromGitTracking({ repoRoot, branch, channel });
176
+ if (fromGit) {
177
+ return {
178
+ manifest: fromGit,
179
+ source: `git:origin/${branch}:${manifestPathForChannel(channel)}`,
180
+ };
181
+ }
182
+ const fromHttp = await loadManifestFromHttp(manifestUrl);
183
+ if (fromHttp) {
184
+ return {
185
+ manifest: fromHttp,
186
+ source: manifestUrl,
187
+ };
188
+ }
189
+ const fromGh = await loadManifestFromGitHubCli(manifestUrl);
190
+ if (fromGh) {
191
+ return {
192
+ manifest: fromGh,
193
+ source: `gh:${manifestUrl}`,
194
+ };
195
+ }
196
+ return {
197
+ manifest: null,
198
+ source: manifestUrl,
199
+ };
200
+ };
201
+ export const buildSyncStatus = async (params) => {
202
+ const branch = params.branch ?? DEFAULT_RELEASE_BRANCH;
203
+ const channel = params.channel ?? DEFAULT_UPDATE_CHANNEL;
204
+ const local = await readVersionFromMarkdown(params.versionFile).catch(() => ({
205
+ version: '00.01',
206
+ semver: '0.0.1',
207
+ }));
208
+ const remoteResult = await loadRemoteManifest({
209
+ repoRoot: params.repoRoot,
210
+ manifestUrl: params.manifestUrl,
211
+ branch,
212
+ channel,
213
+ });
214
+ const remote = remoteResult.manifest;
215
+ const localCommit = (await runGit(params.repoRoot, ['rev-parse', '--short', 'HEAD'])) ?? 'unknown';
216
+ const localBranch = (await runGit(params.repoRoot, ['rev-parse', '--abbrev-ref', 'HEAD'])) ?? 'unknown';
217
+ const gitStatus = (await runGit(params.repoRoot, ['status', '--short'])) ?? '';
218
+ const localClean = gitStatus.length === 0;
219
+ const remoteTrackingCommit = await runGit(params.repoRoot, ['rev-parse', '--short', `origin/${branch}`]);
220
+ const packageMode = localCommit === 'unknown' || localBranch === 'unknown';
221
+ if (!remote) {
222
+ return {
223
+ localVersion: local.version,
224
+ localSemver: local.semver,
225
+ localCommit,
226
+ localBranch,
227
+ localClean,
228
+ updateAvailable: false,
229
+ recommendedAction: 'Nao foi possivel consultar o manifesto remoto. Verifique origin, canal e autenticacao do GitHub.',
230
+ manifestSource: remoteResult.source,
231
+ };
232
+ }
233
+ const semverComparison = compareSemver(local.semver, remote.semver);
234
+ const branchHasNewCommit = Boolean(remoteTrackingCommit && remoteTrackingCommit !== localCommit);
235
+ const updateAvailable = semverComparison < 0 || (semverComparison <= 0 && branchHasNewCommit);
236
+ const recommendedAction = buildRecommendedAction({
237
+ localClean,
238
+ updateAvailable,
239
+ channel,
240
+ branch,
241
+ packageMode,
242
+ });
243
+ return {
244
+ localVersion: local.version,
245
+ localSemver: local.semver,
246
+ localCommit,
247
+ localBranch,
248
+ localClean,
249
+ remoteVersion: remote.version,
250
+ remoteSemver: remote.semver,
251
+ remoteCommit: remoteTrackingCommit ?? remote.git.commit,
252
+ remotePublishedAt: remote.publishedAt,
253
+ updateAvailable,
254
+ recommendedAction,
255
+ manifestSource: remoteResult.source,
256
+ };
257
+ };
258
+ export const buildUpdatePlan = async (params) => {
259
+ const branch = params.branch ?? DEFAULT_RELEASE_BRANCH;
260
+ const channel = params.channel ?? DEFAULT_UPDATE_CHANNEL;
261
+ const status = await buildSyncStatus({
262
+ ...params,
263
+ branch,
264
+ channel,
265
+ });
266
+ const steps = [
267
+ `Canal remoto: ${channel}`,
268
+ `Fonte do manifesto: ${status.manifestSource}`,
269
+ `Versao local: ${status.localVersion} (${status.localSemver})`,
270
+ `Commit local: ${status.localCommit}`,
271
+ `Arvore limpa: ${status.localClean ? 'sim' : 'nao'}`,
272
+ ];
273
+ if (status.remoteVersion) {
274
+ steps.push(`Versao remota: ${status.remoteVersion} (${status.remoteSemver})`);
275
+ }
276
+ if (status.remoteCommit) {
277
+ steps.push(`Commit remoto rastreado: ${status.remoteCommit}`);
278
+ }
279
+ steps.push(status.recommendedAction);
280
+ if (status.updateAvailable) {
281
+ steps.push(buildSuggestedUpdateStep({
282
+ packageMode: status.localCommit === 'unknown' || status.localBranch === 'unknown',
283
+ branch,
284
+ }));
285
+ }
286
+ return steps;
287
+ };
288
+ //# sourceMappingURL=update.js.map