@noclaf/cli 0.4.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/README.md +221 -0
- package/dist/auth.js +66 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/commands/auth.js +76 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/init.js +291 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/skills.js +22 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/sync.js +170 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/copy/auth.json +6 -0
- package/dist/cli/copy/flows.json +6 -0
- package/dist/cli/copy/init.json +19 -0
- package/dist/cli/copy/sync.json +3 -0
- package/dist/cli/copy.js +23 -0
- package/dist/cli/copy.js.map +1 -0
- package/dist/cli/flows/clients.js +108 -0
- package/dist/cli/flows/clients.js.map +1 -0
- package/dist/cli/flows/dependencies.js +68 -0
- package/dist/cli/flows/dependencies.js.map +1 -0
- package/dist/cli/flows/sections.js +45 -0
- package/dist/cli/flows/sections.js.map +1 -0
- package/dist/cli/ui/render.js +167 -0
- package/dist/cli/ui/render.js.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +96 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -0
- package/dist/database.types.js +11 -0
- package/dist/database.types.js.map +1 -0
- package/dist/lib/active-project.js +28 -0
- package/dist/lib/active-project.js.map +1 -0
- package/dist/lib/client-configs.js +179 -0
- package/dist/lib/client-configs.js.map +1 -0
- package/dist/lib/client-install.js +40 -0
- package/dist/lib/client-install.js.map +1 -0
- package/dist/lib/colors.js +67 -0
- package/dist/lib/colors.js.map +1 -0
- package/dist/lib/cowork-extension.js +131 -0
- package/dist/lib/cowork-extension.js.map +1 -0
- package/dist/lib/dependencies.js +159 -0
- package/dist/lib/dependencies.js.map +1 -0
- package/dist/lib/duration.js +5 -0
- package/dist/lib/duration.js.map +1 -0
- package/dist/lib/file-merge.js +33 -0
- package/dist/lib/file-merge.js.map +1 -0
- package/dist/lib/hooks.js +231 -0
- package/dist/lib/hooks.js.map +1 -0
- package/dist/lib/project-context.js +105 -0
- package/dist/lib/project-context.js.map +1 -0
- package/dist/lib/prompts.js +62 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/provision.js +222 -0
- package/dist/lib/provision.js.map +1 -0
- package/dist/lib/require-config.js +31 -0
- package/dist/lib/require-config.js.map +1 -0
- package/dist/lib/sections.js +85 -0
- package/dist/lib/sections.js.map +1 -0
- package/dist/lib/skill-serve.js +71 -0
- package/dist/lib/skill-serve.js.map +1 -0
- package/dist/lib/skills-cache.js +89 -0
- package/dist/lib/skills-cache.js.map +1 -0
- package/dist/lib/skills.js +219 -0
- package/dist/lib/skills.js.map +1 -0
- package/dist/lib/targets.js +150 -0
- package/dist/lib/targets.js.map +1 -0
- package/dist/lib/task-history.js +14 -0
- package/dist/lib/task-history.js.map +1 -0
- package/dist/lib/telemetry.js +32 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/tool-result.js +12 -0
- package/dist/lib/tool-result.js.map +1 -0
- package/dist/lib/version-check.js +88 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/logo.js +17 -0
- package/dist/logo.js.map +1 -0
- package/dist/mcp-server.js +162 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/spinner.js +12 -0
- package/dist/spinner.js.map +1 -0
- package/dist/supabase.js +95 -0
- package/dist/supabase.js.map +1 -0
- package/dist/tools/comment-task.js +80 -0
- package/dist/tools/comment-task.js.map +1 -0
- package/dist/tools/create-task.js +194 -0
- package/dist/tools/create-task.js.map +1 -0
- package/dist/tools/end-allocation.js +59 -0
- package/dist/tools/end-allocation.js.map +1 -0
- package/dist/tools/end-task-allocation.js +51 -0
- package/dist/tools/end-task-allocation.js.map +1 -0
- package/dist/tools/get-active-allocation.js +106 -0
- package/dist/tools/get-active-allocation.js.map +1 -0
- package/dist/tools/get-context.js +47 -0
- package/dist/tools/get-context.js.map +1 -0
- package/dist/tools/get-task.js +223 -0
- package/dist/tools/get-task.js.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-my-allocations.js +87 -0
- package/dist/tools/list-my-allocations.js.map +1 -0
- package/dist/tools/list-projects.js +34 -0
- package/dist/tools/list-projects.js.map +1 -0
- package/dist/tools/list-tasks.js +213 -0
- package/dist/tools/list-tasks.js.map +1 -0
- package/dist/tools/move-task.js +98 -0
- package/dist/tools/move-task.js.map +1 -0
- package/dist/tools/set-project.js +47 -0
- package/dist/tools/set-project.js.map +1 -0
- package/dist/tools/start-allocation.js +45 -0
- package/dist/tools/start-allocation.js.map +1 -0
- package/dist/tools/start-task-allocation.js +141 -0
- package/dist/tools/start-task-allocation.js.map +1 -0
- package/dist/tools/update-task.js +256 -0
- package/dist/tools/update-task.js.map +1 -0
- package/dist/version.js +16 -0
- package/dist/version.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, cpSync, readdirSync, readFileSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { homedir, tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import AdmZip from 'adm-zip';
|
|
5
|
+
/**
|
|
6
|
+
* Skills como repo aberto (não pacote npm): o CLI baixa o zipball do GitHub pro
|
|
7
|
+
* cache local (`~/.noclaf/skills`) e lê de lá — `skillsDir()` resolve pra cá sem
|
|
8
|
+
* checkout, e `noclaf sync` atualiza o cache sem republicar o CLI.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_REPO = 'Falcao-Tech/noclaf-skills';
|
|
11
|
+
const DEFAULT_REF = 'main';
|
|
12
|
+
/** `owner/repo` do repo de skills. Sobrescrevível via `NOCLAF_SKILLS_REPO`. */
|
|
13
|
+
export function skillsRepo() {
|
|
14
|
+
return process.env.NOCLAF_SKILLS_REPO || DEFAULT_REPO;
|
|
15
|
+
}
|
|
16
|
+
/** Branch/tag a baixar. Sobrescrevível via `NOCLAF_SKILLS_REF`. */
|
|
17
|
+
export function skillsRef() {
|
|
18
|
+
return process.env.NOCLAF_SKILLS_REF || DEFAULT_REF;
|
|
19
|
+
}
|
|
20
|
+
/** Raiz do cache local (o conteúdo do repo: `commands/`, `skills/`, `hooks/`, …). */
|
|
21
|
+
export function skillsCacheDir() {
|
|
22
|
+
return join(homedir(), '.noclaf', 'skills');
|
|
23
|
+
}
|
|
24
|
+
const MARKER = '.noclaf-skills.json';
|
|
25
|
+
/** Metadados do último fetch (repo/ref/quando). `null` se o cache não existe. */
|
|
26
|
+
export function cacheMeta() {
|
|
27
|
+
const p = join(skillsCacheDir(), MARKER);
|
|
28
|
+
if (!existsSync(p))
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(readFileSync(p, 'utf8'));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** O cache existe e parece válido (tem ao menos `skills/` ou `commands/`)? */
|
|
38
|
+
export function skillsCached() {
|
|
39
|
+
const dir = skillsCacheDir();
|
|
40
|
+
return existsSync(join(dir, 'skills')) || existsSync(join(dir, 'commands'));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Baixa o repo de skills (zipball do GitHub) pro cache local. Sem `git` — usa
|
|
44
|
+
* `fetch` (Node 20+) + `adm-zip`. Idempotente: com `force=false` e cache presente,
|
|
45
|
+
* não toca a rede. Se o download falhar mas houver cache antigo, segue com ele.
|
|
46
|
+
*/
|
|
47
|
+
export async function fetchSkills(opts = {}) {
|
|
48
|
+
const dir = skillsCacheDir();
|
|
49
|
+
const repo = skillsRepo();
|
|
50
|
+
const ref = skillsRef();
|
|
51
|
+
if (!opts.force && skillsCached()) {
|
|
52
|
+
return { status: 'cached', dir, repo, ref };
|
|
53
|
+
}
|
|
54
|
+
const url = `https://codeload.github.com/${repo}/zip/refs/heads/${ref}`;
|
|
55
|
+
const staging = join(tmpdir(), `noclaf-skills-${process.pid}-${Date.now()}`);
|
|
56
|
+
try {
|
|
57
|
+
const res = await fetch(url);
|
|
58
|
+
if (!res.ok)
|
|
59
|
+
throw new Error(`HTTP ${res.status} ao baixar ${url}`);
|
|
60
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
61
|
+
// O zipball tem um único dir raiz (`<repo>-<ref>/`); extrai e mira nele.
|
|
62
|
+
rmSync(staging, { recursive: true, force: true });
|
|
63
|
+
mkdirSync(staging, { recursive: true });
|
|
64
|
+
new AdmZip(buf).extractAllTo(staging, true);
|
|
65
|
+
const dirs = readdirSync(staging, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
66
|
+
const root = dirs.length === 1 ? join(staging, dirs[0].name) : staging;
|
|
67
|
+
// Substitui o cache pelo conteúdo baixado.
|
|
68
|
+
rmSync(dir, { recursive: true, force: true });
|
|
69
|
+
mkdirSync(dir, { recursive: true });
|
|
70
|
+
cpSync(root, dir, { recursive: true });
|
|
71
|
+
const meta = { repo, ref, fetchedAt: new Date().toISOString() };
|
|
72
|
+
writeFileSync(join(dir, MARKER), JSON.stringify(meta, null, 2) + '\n', 'utf8');
|
|
73
|
+
return { status: 'fetched', dir, repo, ref };
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
if (skillsCached()) {
|
|
77
|
+
return { status: 'cached', dir, repo, ref, error: err.message };
|
|
78
|
+
}
|
|
79
|
+
return { status: 'failed', dir, repo, ref, error: err.message };
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
rmSync(staging, { recursive: true, force: true });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Garante que o cache exista (baixa só se ausente). Best-effort pro runtime do MCP. */
|
|
86
|
+
export async function ensureSkillsCache() {
|
|
87
|
+
return fetchSkills({ force: false });
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=skills-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-cache.js","sourceRoot":"","sources":["../../src/lib/skills-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { join, relative, sep, dirname } from 'node:path';
|
|
4
|
+
import { skillsCacheDir, skillsCached } from './skills-cache.js';
|
|
5
|
+
/**
|
|
6
|
+
* Diretório do conteúdo das skills. Resolve em ordem: `NOCLAF_SKILLS_DIR`
|
|
7
|
+
* (checkout local), `@noclaf/skills` via require.resolve (dev legado), ou o
|
|
8
|
+
* cache `~/.noclaf/skills` populado por `noclaf sync`/`init` (fluxo padrão).
|
|
9
|
+
*/
|
|
10
|
+
export function skillsDir() {
|
|
11
|
+
const override = process.env.NOCLAF_SKILLS_DIR;
|
|
12
|
+
if (override && existsSync(override))
|
|
13
|
+
return override;
|
|
14
|
+
try {
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
return dirname(require.resolve('@noclaf/skills/package.json'));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
/* pacote ausente (modelo repo-aberto) → cai pro cache local */
|
|
20
|
+
}
|
|
21
|
+
if (skillsCached())
|
|
22
|
+
return skillsCacheDir();
|
|
23
|
+
throw new Error('Conteúdo de skills não encontrado. Rode `noclaf sync` pra baixar o repo ' +
|
|
24
|
+
'(ou defina NOCLAF_SKILLS_DIR apontando pra um checkout local).');
|
|
25
|
+
}
|
|
26
|
+
function listMarkdown(dir) {
|
|
27
|
+
const out = [];
|
|
28
|
+
const walk = (abs) => {
|
|
29
|
+
for (const entry of readdirSync(abs, { withFileTypes: true })) {
|
|
30
|
+
if (entry.name.startsWith('.'))
|
|
31
|
+
continue;
|
|
32
|
+
const childAbs = join(abs, entry.name);
|
|
33
|
+
if (entry.isDirectory())
|
|
34
|
+
walk(childAbs);
|
|
35
|
+
else if (entry.isFile() &&
|
|
36
|
+
entry.name.toLowerCase().endsWith('.md') &&
|
|
37
|
+
entry.name.toLowerCase() !== 'readme.md')
|
|
38
|
+
out.push(relative(dir, childAbs).split(sep).join('/'));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
walk(dir);
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parser de frontmatter minimalista: `key: value` de uma linha, mais blocos
|
|
46
|
+
* folded (`>`) e literal (`|`). Suficiente pros metadados (não é YAML completo).
|
|
47
|
+
*/
|
|
48
|
+
function parseFrontmatter(raw) {
|
|
49
|
+
const fm = {};
|
|
50
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(raw);
|
|
51
|
+
if (!match)
|
|
52
|
+
return { frontmatter: fm, body: raw };
|
|
53
|
+
const lines = match[1].split(/\r?\n/);
|
|
54
|
+
for (let i = 0; i < lines.length; i++) {
|
|
55
|
+
const m = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(lines[i]);
|
|
56
|
+
if (!m)
|
|
57
|
+
continue;
|
|
58
|
+
const key = m[1];
|
|
59
|
+
let value = m[2].trim();
|
|
60
|
+
if (/^[|>][+-]?$/.test(value)) {
|
|
61
|
+
const folded = value[0] === '>';
|
|
62
|
+
const collected = [];
|
|
63
|
+
while (i + 1 < lines.length && (lines[i + 1].trim() === '' || /^\s+\S/.test(lines[i + 1]))) {
|
|
64
|
+
collected.push(lines[++i].trim());
|
|
65
|
+
}
|
|
66
|
+
value = folded
|
|
67
|
+
? collected.join(' ').replace(/\s+/g, ' ').trim()
|
|
68
|
+
: collected.join('\n').trim();
|
|
69
|
+
fm[key] = value;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
73
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
74
|
+
value = value.slice(1, -1);
|
|
75
|
+
}
|
|
76
|
+
fm[key] = value;
|
|
77
|
+
}
|
|
78
|
+
return { frontmatter: fm, body: raw.slice(match[0].length) };
|
|
79
|
+
}
|
|
80
|
+
/** Clientes de IA reconhecidos pra visibilidade de docs. */
|
|
81
|
+
export const KNOWN_CLIENTS = ['claude-code', 'codex', 'cowork'];
|
|
82
|
+
const KNOWN_CLIENTS_SET = new Set(KNOWN_CLIENTS);
|
|
83
|
+
/**
|
|
84
|
+
* Parseia o campo `clients:` do frontmatter (lista separada por vírgula/espaço)
|
|
85
|
+
* num conjunto normalizado. Vazio/ausente/sem valor válido → `null` (= todos).
|
|
86
|
+
*/
|
|
87
|
+
export function parseClients(value) {
|
|
88
|
+
if (!value)
|
|
89
|
+
return null;
|
|
90
|
+
const list = value
|
|
91
|
+
.split(/[,\s]+/)
|
|
92
|
+
.map((s) => s.trim().toLowerCase())
|
|
93
|
+
.filter((s) => KNOWN_CLIENTS_SET.has(s));
|
|
94
|
+
return list.length > 0 ? [...new Set(list)] : null;
|
|
95
|
+
}
|
|
96
|
+
/** Um doc é visível pra um surface se não restringe clientes ou inclui aquele. */
|
|
97
|
+
export function docForSurface(doc, surface) {
|
|
98
|
+
if (!surface)
|
|
99
|
+
return true;
|
|
100
|
+
return !doc.clients || doc.clients.includes(surface);
|
|
101
|
+
}
|
|
102
|
+
/** Recorta a lista de docs pros visíveis num surface. */
|
|
103
|
+
export function filterSkillsForSurface(docs, surface) {
|
|
104
|
+
if (!surface)
|
|
105
|
+
return docs;
|
|
106
|
+
return docs.filter((d) => docForSurface(d, surface));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Filtra docs crus (relPath+conteúdo) pros visíveis num surface. Docs sem
|
|
110
|
+
* frontmatter de doc (ex.: scripts soltos) são mantidos por padrão.
|
|
111
|
+
*/
|
|
112
|
+
export function filterDocsForSurface(docs, surface) {
|
|
113
|
+
if (!surface)
|
|
114
|
+
return docs;
|
|
115
|
+
const parsed = toSkillDocs(docs.map((d) => ({ path: d.relPath, raw: d.content.toString('utf8') })));
|
|
116
|
+
const hidden = new Set(parsed.filter((n) => !docForSurface(n, surface)).map((n) => n.path));
|
|
117
|
+
return docs.filter((d) => !hidden.has(d.relPath));
|
|
118
|
+
}
|
|
119
|
+
function typeForPath(relPath) {
|
|
120
|
+
const parts = relPath.split('/');
|
|
121
|
+
const top = parts[0];
|
|
122
|
+
const base = parts[parts.length - 1].toLowerCase();
|
|
123
|
+
if (top === 'commands')
|
|
124
|
+
return 'command';
|
|
125
|
+
// Só `SKILL.md` é a skill; arquivos de apoio (STANDARDS.md, etc.) são `doc`.
|
|
126
|
+
if (top === 'skills')
|
|
127
|
+
return base === 'skill.md' ? 'skill' : 'doc';
|
|
128
|
+
if (top === 'agents')
|
|
129
|
+
return 'agent';
|
|
130
|
+
if (top === 'dependencies')
|
|
131
|
+
return 'dependency';
|
|
132
|
+
return 'doc';
|
|
133
|
+
}
|
|
134
|
+
/** Id de invocação: skill = nome da pasta (SKILL.md); o resto = basename sem `.md`. */
|
|
135
|
+
function idForPath(relPath) {
|
|
136
|
+
const parts = relPath.split('/');
|
|
137
|
+
const base = parts[parts.length - 1];
|
|
138
|
+
if (base.toLowerCase() === 'skill.md' && parts.length >= 2)
|
|
139
|
+
return parts[parts.length - 2];
|
|
140
|
+
return base.replace(/\.md$/i, '');
|
|
141
|
+
}
|
|
142
|
+
function humanize(id) {
|
|
143
|
+
return id.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* "Kinds" do pacote que viram docs. `rules/`, `hooks/`, `index.md`, `README.md`,
|
|
147
|
+
* `scripts/` etc. são deliberadamente ignorados — o CLI não lida com eles aqui.
|
|
148
|
+
*/
|
|
149
|
+
const SKILL_KINDS = ['commands', 'skills', 'agents', 'dependencies'];
|
|
150
|
+
/** Lê os `.md` dos kinds do pacote (`@noclaf/skills`) como RawDoc[]. */
|
|
151
|
+
export function readSkillFiles(dir = skillsDir()) {
|
|
152
|
+
if (!existsSync(dir)) {
|
|
153
|
+
throw new Error(`Pacote de skills não encontrado em ${dir}. Instale/publique @noclaf/skills.`);
|
|
154
|
+
}
|
|
155
|
+
const docs = [];
|
|
156
|
+
for (const kind of SKILL_KINDS) {
|
|
157
|
+
const kindDir = join(dir, kind);
|
|
158
|
+
if (!existsSync(kindDir))
|
|
159
|
+
continue;
|
|
160
|
+
for (const rel of listMarkdown(kindDir)) {
|
|
161
|
+
docs.push({ path: `${kind}/${rel}`, raw: readFileSync(join(kindDir, rel), 'utf-8') });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return docs;
|
|
165
|
+
}
|
|
166
|
+
/** Constrói os docs a partir de arquivos crus (frontmatter + corpo). */
|
|
167
|
+
export function toSkillDocs(files) {
|
|
168
|
+
return files
|
|
169
|
+
.map(({ path: relPath, raw }) => {
|
|
170
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
171
|
+
const id = idForPath(relPath);
|
|
172
|
+
return {
|
|
173
|
+
id,
|
|
174
|
+
uid: frontmatter.id ? String(frontmatter.id).trim() : null,
|
|
175
|
+
title: frontmatter.title || frontmatter.name || humanize(id),
|
|
176
|
+
type: typeForPath(relPath),
|
|
177
|
+
path: relPath,
|
|
178
|
+
description: frontmatter.description ?? '',
|
|
179
|
+
frontmatter,
|
|
180
|
+
content: body.trim(),
|
|
181
|
+
clients: parseClients(frontmatter.clients),
|
|
182
|
+
};
|
|
183
|
+
})
|
|
184
|
+
.sort((a, b) => a.path.localeCompare(b.path));
|
|
185
|
+
}
|
|
186
|
+
export function readSkillDocs(dir = skillsDir()) {
|
|
187
|
+
return toSkillDocs(readSkillFiles(dir));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Docs `dependency` do pacote — libs externas que a CLI oferece instalar no fim do
|
|
191
|
+
* `sync`/`init`. Cada arquivo em `dependencies/` é uma declaração; a presença no
|
|
192
|
+
* diretório é o que conta. Best-effort: `[]` se o pacote não estiver disponível.
|
|
193
|
+
*/
|
|
194
|
+
export function readDependencies(dir = skillsDir()) {
|
|
195
|
+
try {
|
|
196
|
+
return readSkillDocs(dir)
|
|
197
|
+
.filter((d) => d.type === 'dependency')
|
|
198
|
+
.sort((a, b) => a.title.localeCompare(b.title));
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Mapa `nome de invocação → id sequencial (frontmatter)`, pra telemetria estável.
|
|
206
|
+
* Best-effort: mapa vazio se o `@noclaf/skills` não estiver disponível.
|
|
207
|
+
*/
|
|
208
|
+
export function skillIdMap(dir = skillsDir()) {
|
|
209
|
+
const map = new Map();
|
|
210
|
+
try {
|
|
211
|
+
for (const d of readSkillDocs(dir))
|
|
212
|
+
map.set(d.id, d.uid);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
/* @noclaf/skills ausente → telemetria sem ids */
|
|
216
|
+
}
|
|
217
|
+
return map;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { toSkillDocs } from './skills.js';
|
|
5
|
+
import { readJson, readToml } from './file-merge.js';
|
|
6
|
+
export const claudeTarget = {
|
|
7
|
+
id: 'claude',
|
|
8
|
+
label: 'Claude Code (~/.claude)',
|
|
9
|
+
surface: 'claude-code',
|
|
10
|
+
targetDir: () => join(homedir(), '.claude'),
|
|
11
|
+
mapDocs: (docs) => docs,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Texto que substitui `$ARGUMENTS` na tradução pro Codex. Skills do Codex são
|
|
15
|
+
* selecionadas por descrição e dirigidas por linguagem natural — não há
|
|
16
|
+
* substituição de slash-args como no caminho de command/prompt do Claude.
|
|
17
|
+
*/
|
|
18
|
+
const ARGS_REWORD = 'the arguments the user provided';
|
|
19
|
+
/** Escapa uma descrição pra uma linha de YAML entre aspas duplas. */
|
|
20
|
+
function yamlQuote(value) {
|
|
21
|
+
const oneLine = value.replace(/\r?\n/g, ' ').replace(/\s+/g, ' ').trim();
|
|
22
|
+
return `"${oneLine.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
23
|
+
}
|
|
24
|
+
/** Renderiza o SKILL.md de um node no formato Agent Skills (name + description). */
|
|
25
|
+
export function toCodexSkillContent(node) {
|
|
26
|
+
const description = node.frontmatter.description || node.description || node.title;
|
|
27
|
+
const frontmatter = `---\nname: ${node.id}\ndescription: ${yamlQuote(description)}\n---\n`;
|
|
28
|
+
let body = node.content;
|
|
29
|
+
if (body.includes('$ARGUMENTS')) {
|
|
30
|
+
body = body.split('$ARGUMENTS').join(ARGS_REWORD);
|
|
31
|
+
}
|
|
32
|
+
// `argument-hint` não existe em skills — dobra num aviso de entrada esperada.
|
|
33
|
+
const hint = node.frontmatter['argument-hint'];
|
|
34
|
+
const inputLine = hint ? `**Expected input:** ${hint}\n\n` : '';
|
|
35
|
+
return `${frontmatter}\n${inputLine}${body.trim()}\n`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Renderiza um custom prompt do Codex (`~/.codex/prompts/<id>.md`). Diferente da skill,
|
|
39
|
+
* o Codex expande `$ARGUMENTS`/`$1..$9` aqui, então preservamos os placeholders.
|
|
40
|
+
*/
|
|
41
|
+
export function toCodexPromptContent(node) {
|
|
42
|
+
const description = node.frontmatter.description || node.description || node.title;
|
|
43
|
+
const hint = node.frontmatter['argument-hint'];
|
|
44
|
+
const fmLines = [`description: ${yamlQuote(description)}`];
|
|
45
|
+
if (hint)
|
|
46
|
+
fmLines.push(`argument-hint: ${yamlQuote(hint)}`);
|
|
47
|
+
const frontmatter = `---\n${fmLines.join('\n')}\n---\n`;
|
|
48
|
+
// Corpo original, com `$ARGUMENTS`/`$1` intactos (o Codex substitui na invocação).
|
|
49
|
+
return `${frontmatter}\n${node.content.trim()}\n`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Traduz os docs crus pro layout do Codex em dual-write: cada `command`/`skill` vira
|
|
53
|
+
* uma skill (`skills/<id>/SKILL.md`) E um custom prompt (`prompts/<id>.md`). Os
|
|
54
|
+
* arquivos de apoio de uma skill (`templates/*.md`, `*-PATTERN.md`, `STANDARDS.md` —
|
|
55
|
+
* type `doc`, vizinhos do `SKILL.md`) são carregados pra dentro de `skills/<id>/`
|
|
56
|
+
* preservando o path relativo, pra que o SKILL.md traduzido consiga referenciá-los
|
|
57
|
+
* exatamente como no Claude. `agent` e `doc` fora de uma skill são ignorados.
|
|
58
|
+
*/
|
|
59
|
+
export function toCodexDocs(docs) {
|
|
60
|
+
const nodes = toSkillDocs(docs.map((d) => ({ path: d.relPath, raw: d.content.toString('utf8') })));
|
|
61
|
+
const rawByPath = new Map(docs.map((d) => [d.relPath, d.content]));
|
|
62
|
+
// Pasta da skill (dir do SKILL.md) -> id, pra rotear os arquivos de apoio.
|
|
63
|
+
const skillFolders = new Map();
|
|
64
|
+
for (const node of nodes) {
|
|
65
|
+
if (node.type === 'skill') {
|
|
66
|
+
skillFolders.set(node.path.slice(0, node.path.lastIndexOf('/')), node.id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const out = [];
|
|
70
|
+
const seen = new Map(); // id -> path de origem (guarda de colisão)
|
|
71
|
+
for (const node of nodes) {
|
|
72
|
+
if (node.type === 'command' || node.type === 'skill') {
|
|
73
|
+
const prev = seen.get(node.id);
|
|
74
|
+
if (prev) {
|
|
75
|
+
throw new Error(`Tradução Codex: id duplicado "${node.id}" (${prev} e ${node.path}). ` +
|
|
76
|
+
`O id precisa ser único — renomeie um deles.`);
|
|
77
|
+
}
|
|
78
|
+
seen.set(node.id, node.path);
|
|
79
|
+
out.push({
|
|
80
|
+
relPath: `skills/${node.id}/SKILL.md`,
|
|
81
|
+
content: Buffer.from(toCodexSkillContent(node), 'utf8'),
|
|
82
|
+
});
|
|
83
|
+
out.push({
|
|
84
|
+
relPath: `prompts/${node.id}.md`,
|
|
85
|
+
content: Buffer.from(toCodexPromptContent(node), 'utf8'),
|
|
86
|
+
});
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Arquivo de apoio de uma skill: carrega verbatim pro dir da skill traduzida,
|
|
90
|
+
// mantendo o path relativo (ex.: `templates/spec.md`, `SPEC-PATTERN.md`).
|
|
91
|
+
if (node.type === 'doc') {
|
|
92
|
+
for (const [folder, id] of skillFolders) {
|
|
93
|
+
if (!node.path.startsWith(`${folder}/`))
|
|
94
|
+
continue;
|
|
95
|
+
const rel = node.path.slice(folder.length + 1);
|
|
96
|
+
const raw = rawByPath.get(node.path);
|
|
97
|
+
if (raw)
|
|
98
|
+
out.push({ relPath: `skills/${id}/${rel}`, content: raw });
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
export const codexTarget = {
|
|
106
|
+
id: 'codex',
|
|
107
|
+
label: 'Codex CLI (~/.codex)',
|
|
108
|
+
surface: 'codex',
|
|
109
|
+
targetDir: () => join(homedir(), '.codex'),
|
|
110
|
+
mapDocs: (docs) => toCodexDocs(docs),
|
|
111
|
+
};
|
|
112
|
+
export const ALL_TARGETS = [claudeTarget, codexTarget];
|
|
113
|
+
function claudeConfigured() {
|
|
114
|
+
const path = join(homedir(), '.claude', 'settings.json');
|
|
115
|
+
if (!existsSync(path))
|
|
116
|
+
return false;
|
|
117
|
+
try {
|
|
118
|
+
const json = (readJson(path) ?? {});
|
|
119
|
+
return Boolean(json.mcpServers?.noclaf);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function codexConfigured() {
|
|
126
|
+
const path = join(homedir(), '.codex', 'config.toml');
|
|
127
|
+
if (!existsSync(path))
|
|
128
|
+
return false;
|
|
129
|
+
try {
|
|
130
|
+
const toml = (readToml(path) ?? {});
|
|
131
|
+
return Boolean(toml.mcp_servers?.noclaf);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Alvos que já têm o servidor `noclaf` configurado (~/.claude/settings.json,
|
|
139
|
+
* ~/.codex/config.toml). Base do auto-detect de `sync`: provisiona pra cada
|
|
140
|
+
* cliente que o worker de fato usa, sem flags.
|
|
141
|
+
*/
|
|
142
|
+
export function detectConfiguredTargets() {
|
|
143
|
+
const targets = [];
|
|
144
|
+
if (claudeConfigured())
|
|
145
|
+
targets.push(claudeTarget);
|
|
146
|
+
if (codexConfigured())
|
|
147
|
+
targets.push(codexTarget);
|
|
148
|
+
return targets;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=targets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"targets.js","sourceRoot":"","sources":["../../src/lib/targets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export async function insertTaskHistory(supabase, entry) {
|
|
2
|
+
const { error } = await supabase.from('task_history').insert({
|
|
3
|
+
task_id: entry.task_id,
|
|
4
|
+
user_id: entry.user_id,
|
|
5
|
+
action: entry.action,
|
|
6
|
+
field: entry.field ?? null,
|
|
7
|
+
old_value: entry.old_value ?? null,
|
|
8
|
+
new_value: entry.new_value ?? null,
|
|
9
|
+
});
|
|
10
|
+
if (error) {
|
|
11
|
+
console.error(`[noclaf-cli] falha ao gravar task_history: ${error.message}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=task-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-history.js","sourceRoot":"","sources":["../../src/lib/task-history.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAA2B,EAC3B,KAAmB;IAEnB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;QAC3D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;QAClC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;KACnC,CAAC,CAAC;IACH,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,8CAA8C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function enabled() {
|
|
2
|
+
return process.env.NOCLAF_TELEMETRY !== "0" && !process.env.NOCLAF_NO_TELEMETRY;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Items (skills/commands/agents) provisionados a partir do plano do `provision`,
|
|
6
|
+
* já resolvidos pro id sequencial estável (via `uidByName`).
|
|
7
|
+
*/
|
|
8
|
+
export function provisionedItems(files, uidByName) {
|
|
9
|
+
const seen = new Set();
|
|
10
|
+
const items = [];
|
|
11
|
+
for (const f of files) {
|
|
12
|
+
const m = /^skills\/([^/]+)\/SKILL\.md$/.exec(f.relPath) ??
|
|
13
|
+
/^commands\/([^/]+)\.md$/.exec(f.relPath) ??
|
|
14
|
+
/^agents\/([^/]+)\.md$/.exec(f.relPath);
|
|
15
|
+
if (m && !seen.has(m[1])) {
|
|
16
|
+
seen.add(m[1]);
|
|
17
|
+
items.push({ name: m[1], id: uidByName.get(m[1]) ?? null });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return items.sort((a, b) => a.name.localeCompare(b.name));
|
|
21
|
+
}
|
|
22
|
+
/** Envia um evento de uso pro NOS. Best-effort, fire-and-forget. */
|
|
23
|
+
export function track(supabase, event) {
|
|
24
|
+
if (!supabase || !enabled())
|
|
25
|
+
return;
|
|
26
|
+
void supabase.functions
|
|
27
|
+
.invoke("track-usage", { body: { ...event, at: new Date().toISOString() } })
|
|
28
|
+
.catch(() => {
|
|
29
|
+
/* telemetria nunca quebra o fluxo */
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/lib/telemetry.ts"],"names":[],"mappings":"AAgCA,SAAS,OAAO;IACd,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAA4B,EAC5B,SAAqC;IAErC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GACL,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YACzC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,KAAK,CAAC,QAAkC,EAAE,KAAiB;IACzE,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO;IACpC,KAAK,QAAQ,CAAC,SAAS;SACpB,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC;SAC3E,KAAK,CAAC,GAAG,EAAE;QACV,qCAAqC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function jsonResult(data) {
|
|
2
|
+
return {
|
|
3
|
+
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
export function errorResult(message) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: 'text', text: message }],
|
|
9
|
+
isError: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=tool-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-result.js","sourceRoot":"","sources":["../../src/lib/tool-result.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACjE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import updateNotifier from 'update-notifier';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
function loadPkg() {
|
|
6
|
+
// Este módulo compila pra `dist/lib/version-check.js`, então o package.json fica
|
|
7
|
+
// dois níveis acima (raiz do pacote). Mesmo truque do `packageRoot()` do cowork-extension.
|
|
8
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const pkgPath = join(here, '..', '..', 'package.json');
|
|
10
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
11
|
+
}
|
|
12
|
+
const ONE_DAY_MS = 1000 * 60 * 60 * 24;
|
|
13
|
+
/**
|
|
14
|
+
* Inicia checagem em background (cacheada). Retorna o objeto pra inspeção.
|
|
15
|
+
*/
|
|
16
|
+
export function startVersionCheck() {
|
|
17
|
+
const pkg = loadPkg();
|
|
18
|
+
return updateNotifier({ pkg, updateCheckInterval: ONE_DAY_MS });
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Pro CLI interativo: chama .notify() com banner padrão no stdout.
|
|
22
|
+
*/
|
|
23
|
+
export function notifyCliIfUpdate() {
|
|
24
|
+
try {
|
|
25
|
+
const notifier = startVersionCheck();
|
|
26
|
+
notifier.notify({ defer: false, isGlobal: true });
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Best-effort. Nunca quebrar o CLI por causa de checagem de versão.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** `a > b` em semver simples (major.minor.patch; ignora pré-release). */
|
|
33
|
+
function semverGt(a, b) {
|
|
34
|
+
const pa = a.split('-')[0].split('.').map((n) => parseInt(n, 10) || 0);
|
|
35
|
+
const pb = b.split('-')[0].split('.').map((n) => parseInt(n, 10) || 0);
|
|
36
|
+
for (let i = 0; i < 3; i++) {
|
|
37
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
38
|
+
return true;
|
|
39
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Consulta o registro npm pela última versão publicada e compara com a instalada.
|
|
46
|
+
* Retorna `null` em qualquer falha (offline, timeout, registro bloqueado) — nunca
|
|
47
|
+
* quebra o fluxo do CLI. Usado pelo `noclaf sync` pra oferecer atualizar.
|
|
48
|
+
*/
|
|
49
|
+
export async function checkForUpdate(timeoutMs = 3000) {
|
|
50
|
+
try {
|
|
51
|
+
const pkg = loadPkg();
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
54
|
+
const res = await fetch(`https://registry.npmjs.org/${pkg.name}/latest`, {
|
|
55
|
+
signal: controller.signal,
|
|
56
|
+
headers: { accept: 'application/json' },
|
|
57
|
+
});
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
return null;
|
|
61
|
+
const data = (await res.json());
|
|
62
|
+
const latest = data.version;
|
|
63
|
+
if (!latest)
|
|
64
|
+
return null;
|
|
65
|
+
return { name: pkg.name, current: pkg.version, latest, hasUpdate: semverGt(latest, pkg.version) };
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Pro MCP server: SEM banner em stdout (corromperia JSON-RPC).
|
|
73
|
+
* Loga em stderr só se houver update — o Claude Code captura stderr.
|
|
74
|
+
*/
|
|
75
|
+
export function notifyMcpServerIfUpdate() {
|
|
76
|
+
try {
|
|
77
|
+
const notifier = startVersionCheck();
|
|
78
|
+
const update = notifier.update;
|
|
79
|
+
if (update && update.latest !== update.current) {
|
|
80
|
+
console.error(`[noclaf-cli] nova versão disponível: ${update.current} → ${update.latest}. ` +
|
|
81
|
+
`Atualize com: npm i -g @noclaf/cli`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// idem: best-effort.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=version-check.js.map
|