ganbatte-os 0.2.16 → 0.2.17
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.
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
],
|
|
11
11
|
"supportedIdes": {
|
|
12
12
|
"claude-code": { "workspaceDir": ".claude", "adapter": "integrations/claude", "status": "active" },
|
|
13
|
-
"antigravity": { "workspaceDir": ".antigravity", "adapter": "integrations/antigravity", "status": "active" },
|
|
13
|
+
"antigravity": { "workspaceDir": ".antigravity", "skillsDir": ".antigravity/skills", "adapter": "integrations/antigravity", "status": "active" },
|
|
14
14
|
"gemini-cli": { "workspaceDir": ".gemini", "contextFile": "GEMINI.md", "status": "active" },
|
|
15
15
|
"cursor": { "workspaceDir": ".cursor", "ruleFile": ".cursor/rules/g-os.mdc", "status": "active" },
|
|
16
|
-
"codex": { "workspaceDir": ".codex", "adapter": "integrations/codex", "status": "active" },
|
|
16
|
+
"codex": { "workspaceDir": ".codex", "skillsDir": ".agents/skills", "adapter": "integrations/codex", "status": "active" },
|
|
17
17
|
"opencode": { "workspaceDir": ".opencode", "adapter": "integrations/opencode", "status": "active" },
|
|
18
18
|
"kilo-code": { "workspaceDir": ".kilocode", "ruleFile": ".kilocode/rules/g-os.md", "status": "active" },
|
|
19
|
-
"qwen-code": { "workspaceDir": ".qwen", "adapter": "integrations/qwen", "status": "active" }
|
|
19
|
+
"qwen-code": { "workspaceDir": ".qwen", "skillsDir": ".qwen/skills", "commandsDir": ".qwen/commands/gos", "agentsDir": ".qwen/agents", "adapter": "integrations/qwen", "status": "active" }
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -30,30 +30,102 @@ function skillWrapper(slug, target) {
|
|
|
30
30
|
return `# gos-${slug}\n\nFonte canonica: \`${target}\`\n\nLeia e siga a skill em \`${target}\`.\nEste arquivo existe apenas como adapter fino para a IDE.`;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function qwenCommandWrapper(name, description, target) {
|
|
34
|
+
const desc = (description || name).replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
|
|
35
|
+
return `---\ndescription: "${desc}"\n---\n\n# ${name} (Qwen Command Adapter)\n\n> Adapter para Qwen Code. Fonte canonica: \`${target}\`.\n\nCANONICAL-SOURCE: ${target}\n\n## Adapter Contract\n\n1. Leia o arquivo canonico em **CANONICAL-SOURCE** por completo.\n2. Execute as instrucoes desse arquivo como fonte primaria.\n3. Argumentos do usuario: {{args}}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function claudeCommandWrapper(name, description, target, argumentHint) {
|
|
39
|
+
const desc = (description || name).replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
|
|
40
|
+
const hint = argumentHint ? `\nargument-hint: "${argumentHint.replace(/"/g, '\\"')}"` : '\nargument-hint: "[argumentos opcionais]"';
|
|
41
|
+
return `---\ndescription: "${desc}"${hint}\n---\n\n# ${name} (Claude Adapter)\n\n> Adapter fino para Claude. Fonte canonica: \`${target}\`.\n\nCANONICAL-SOURCE: ${target}\n\n## Adapter Contract\n\n1. Leia o arquivo canonico indicado em **CANONICAL-SOURCE** por completo.\n2. Execute as instrucoes desse arquivo como fonte primaria.\n3. Argumentos do usuario: $ARGUMENTS`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function extractAgentDescription(filePath) {
|
|
45
|
+
if (!fs.existsSync(filePath)) return '';
|
|
46
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
47
|
+
const topBlock = content.split(/\n\s+persona:/)[0];
|
|
48
|
+
for (const field of ['role', 'title', 'description']) {
|
|
49
|
+
const re = new RegExp(`^\\s{2,4}${field}:\\s*(.+)`, 'm');
|
|
50
|
+
const match = topBlock.match(re);
|
|
51
|
+
if (match) return match[1].trim().replace(/^['"]|['"]$/g, '');
|
|
52
|
+
}
|
|
53
|
+
const useForMatch = content.match(/Use para:\s*\n+\s*-\s*(.+)/);
|
|
54
|
+
if (useForMatch) return `Agent para ${useForMatch[1].trim()}`;
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseFrontmatter(filePath) {
|
|
59
|
+
if (!fs.existsSync(filePath)) return {};
|
|
60
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
61
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
62
|
+
if (!match) return {};
|
|
63
|
+
const fm = {};
|
|
64
|
+
const lines = match[1].split('\n');
|
|
65
|
+
for (let i = 0; i < lines.length; i++) {
|
|
66
|
+
const kv = lines[i].match(/^(\w[\w-]*):\s*(.*)/);
|
|
67
|
+
if (!kv) continue;
|
|
68
|
+
let val = kv[2].trim();
|
|
69
|
+
if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
|
|
70
|
+
if (val === '>' || val === '|' || val === '>-' || val === '|-') {
|
|
71
|
+
const parts = [];
|
|
72
|
+
while (i + 1 < lines.length && /^\s+\S/.test(lines[i + 1])) {
|
|
73
|
+
parts.push(lines[++i].trim());
|
|
74
|
+
}
|
|
75
|
+
val = parts.join(' ');
|
|
76
|
+
}
|
|
77
|
+
fm[kv[1]] = val;
|
|
78
|
+
}
|
|
79
|
+
return fm;
|
|
80
|
+
}
|
|
81
|
+
|
|
33
82
|
function main() {
|
|
34
83
|
const agents = readJson(path.join(root, '.gos', 'agents', 'profiles', 'index.json')).profiles;
|
|
35
84
|
const skills = readJson(path.join(root, '.gos', 'skills', 'registry.json')).skills;
|
|
36
85
|
|
|
37
86
|
for (const agent of agents) {
|
|
87
|
+
const agentProfilePath = path.join(root, '.gos', 'agents', 'profiles', agent.path);
|
|
88
|
+
const agentDesc = extractAgentDescription(agentProfilePath) || `${agent.id} agent`;
|
|
89
|
+
|
|
90
|
+
// Claude commands (requires YAML frontmatter with description)
|
|
38
91
|
const claudeFile = path.join(root, '.claude', 'commands', 'gos', 'agents', `${agent.id}.md`);
|
|
39
|
-
|
|
40
|
-
|
|
92
|
+
writeFile(claudeFile, claudeCommandWrapper(`gos-${agent.id}`, agentDesc, relativeTarget(claudeFile, agentProfilePath)));
|
|
93
|
+
|
|
94
|
+
// Qwen commands (requires YAML frontmatter with description)
|
|
95
|
+
const qwenCmd = path.join(root, '.qwen', 'commands', 'gos', 'agents', `${agent.id}.md`);
|
|
96
|
+
writeFile(qwenCmd, qwenCommandWrapper(`gos-${agent.id}`, agentDesc, relativeTarget(qwenCmd, agentProfilePath)));
|
|
97
|
+
|
|
98
|
+
// Qwen sub-agents
|
|
99
|
+
const qwenAgent = path.join(root, '.qwen', 'agents', `gos-${agent.id}.md`);
|
|
100
|
+
const agentTarget = relativeTarget(qwenAgent, agentProfilePath);
|
|
101
|
+
const safeDesc = agentDesc.replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
|
|
102
|
+
writeFile(qwenAgent, `---\nname: "gos-${agent.id}"\ndescription: "${safeDesc}"\nmodel: inherit\ntools:\n - Read\n - Glob\n - Grep\n - Bash\n - Edit\n - Write\n---\n\nFonte canonica: \`${agentTarget}\`\nLeia e siga o perfil em \`${agentTarget}\`.`);
|
|
41
103
|
}
|
|
42
104
|
|
|
43
105
|
for (const skill of skills) {
|
|
44
106
|
const skillTargetPath = skill.skillFile || skill.path;
|
|
107
|
+
const canonicalPath = path.join(root, '.gos', skillTargetPath);
|
|
45
108
|
const claudeSkill = path.join(root, '.claude', 'commands', 'gos', 'skills', `${skill.slug}.md`);
|
|
46
|
-
const codexSkill = path.join(root, '.
|
|
109
|
+
const codexSkill = path.join(root, '.agents', 'skills', `gos-${skill.slug}`, 'SKILL.md');
|
|
110
|
+
const antigravitySkill = path.join(root, '.antigravity', 'skills', `gos-${skill.slug}`, 'SKILL.md');
|
|
47
111
|
const geminiSkill = path.join(root, '.gemini', 'skills', `gos-${skill.slug}`, 'SKILL.md');
|
|
48
112
|
const opencodeSkill = path.join(root, '.opencode', 'skills', `gos-${skill.slug}`, 'SKILL.md');
|
|
49
113
|
const qwenSkill = path.join(root, '.qwen', 'skills', `gos-${skill.slug}`, 'SKILL.md');
|
|
50
114
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
writeFile(
|
|
54
|
-
writeFile(
|
|
55
|
-
|
|
56
|
-
writeFile(
|
|
115
|
+
const qwenCmd = path.join(root, '.qwen', 'commands', 'gos', 'skills', `${skill.slug}.md`);
|
|
116
|
+
|
|
117
|
+
writeFile(claudeSkill, skillWrapper(skill.slug, relativeTarget(claudeSkill, canonicalPath)));
|
|
118
|
+
writeFile(codexSkill, skillWrapper(skill.slug, relativeTarget(codexSkill, canonicalPath)));
|
|
119
|
+
writeFile(antigravitySkill, skillWrapper(skill.slug, relativeTarget(antigravitySkill, canonicalPath)));
|
|
120
|
+
writeFile(geminiSkill, skillWrapper(skill.slug, relativeTarget(geminiSkill, canonicalPath)));
|
|
121
|
+
writeFile(opencodeSkill, skillWrapper(skill.slug, relativeTarget(opencodeSkill, canonicalPath)));
|
|
122
|
+
writeFile(qwenSkill, skillWrapper(skill.slug, relativeTarget(qwenSkill, canonicalPath)));
|
|
123
|
+
const skillFm = parseFrontmatter(canonicalPath);
|
|
124
|
+
const skillDesc = skillFm.description || skill.description || skill.name || skill.slug;
|
|
125
|
+
const skillArgHint = skillFm['argument-hint'] || '';
|
|
126
|
+
writeFile(qwenCmd, qwenCommandWrapper(`gos-${skill.slug}`, skillDesc, relativeTarget(qwenCmd, canonicalPath)));
|
|
127
|
+
// Overwrite Claude skill with frontmatter version
|
|
128
|
+
writeFile(claudeSkill, claudeCommandWrapper(`gos-${skill.slug}`, skillDesc, relativeTarget(claudeSkill, canonicalPath), skillArgHint));
|
|
57
129
|
}
|
|
58
130
|
|
|
59
131
|
const antigravityInstructions = [
|
|
@@ -68,7 +140,16 @@ function main() {
|
|
|
68
140
|
...agents.map((agent) => `- ${agent.id}`),
|
|
69
141
|
'',
|
|
70
142
|
'Skills curadas:',
|
|
71
|
-
...skills.map((skill) => `- ${skill.slug}`)
|
|
143
|
+
...skills.map((skill) => `- ${skill.slug}`),
|
|
144
|
+
'',
|
|
145
|
+
'## Como invocar Skills',
|
|
146
|
+
'',
|
|
147
|
+
'Para usar uma skill, leia o arquivo canonico e siga suas instrucoes.',
|
|
148
|
+
'Skills tambem disponiveis como adapters em `.antigravity/skills/`.',
|
|
149
|
+
'',
|
|
150
|
+
'| Skill | Arquivo canonico |',
|
|
151
|
+
'|-------|-----------------|',
|
|
152
|
+
...skills.map((skill) => `| \`gos-${skill.slug}\` | \`.gos/${skill.skillFile || skill.path}\` |`)
|
|
72
153
|
].join('\n');
|
|
73
154
|
|
|
74
155
|
writeFile(path.join(root, '.antigravity', 'instructions.md'), antigravityInstructions);
|
package/package.json
CHANGED