sinapse-ai 7.0.4 → 7.1.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/.sinapse-ai/core-config.yaml +2 -26
- package/.sinapse-ai/data/entity-registry.yaml +759 -926
- package/.sinapse-ai/data/registry-update-log.jsonl +22 -0
- package/.sinapse-ai/infrastructure/scripts/ide-sync/index.js +1 -49
- package/.sinapse-ai/infrastructure/scripts/validate-parity.js +0 -7
- package/.sinapse-ai/install-manifest.yaml +11 -43
- package/README.en.md +6 -11
- package/README.md +6 -11
- package/bin/modules/env-config.js +1 -2
- package/bin/sinapse-init.js +23 -188
- package/docs/ide-integration.md +22 -263
- package/docs/installation/README.md +4 -6
- package/docs/installation/faq.md +10 -33
- package/docs/installation/linux.md +0 -23
- package/docs/installation/macos.md +0 -10
- package/docs/installation/troubleshooting.md +5 -9
- package/docs/installation/v4-quick-start.md +1 -1
- package/docs/installation/windows.md +0 -18
- package/package.json +1 -9
- package/packages/installer/src/config/ide-configs.js +3 -49
- package/squads/squad-cloning/squad.yaml +2 -2
- package/squads/squad-finance/squad.yaml +2 -2
- package/squads/squad-product/agents/product-orqx.md +1 -1
- package/squads/squad-product/squad.yaml +1 -1
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/antigravity.js +0 -105
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/cursor.js +0 -94
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/github-copilot.js +0 -184
- package/.sinapse-ai/infrastructure/scripts/validate-gemini-integration.js +0 -151
- package/.sinapse-ai/product/templates/ide-rules/antigravity-rules.md +0 -115
- package/.sinapse-ai/product/templates/ide-rules/copilot-rules.md +0 -92
- package/.sinapse-ai/product/templates/ide-rules/cursor-rules.md +0 -115
- package/.sinapse-ai/product/templates/ide-rules/gemini-rules.md +0 -87
- package/docs/pt/platforms/antigravity.md +0 -508
- package/docs/pt/platforms/cursor.md +0 -633
- package/docs/pt/platforms/gemini-cli.md +0 -481
- package/docs/pt/platforms/github-copilot.md +0 -478
|
@@ -25,13 +25,9 @@ const path = require('path');
|
|
|
25
25
|
/**
|
|
26
26
|
* IDE Configuration Metadata
|
|
27
27
|
*
|
|
28
|
-
* SINAPSE v4 supports
|
|
28
|
+
* SINAPSE v4 supports 2 main IDEs:
|
|
29
29
|
* - Claude Code (Anthropic's official CLI) - Recommended
|
|
30
30
|
* - Codex CLI (OpenAI coding CLI)
|
|
31
|
-
* - Gemini CLI (Google AI coding CLI)
|
|
32
|
-
* - Cursor (AI-first code editor)
|
|
33
|
-
* - GitHub Copilot (GitHub's AI pair programmer)
|
|
34
|
-
* - AntiGravity (Google agentic platform)
|
|
35
31
|
*/
|
|
36
32
|
const IDE_CONFIGS = {
|
|
37
33
|
'claude-code': {
|
|
@@ -47,55 +43,13 @@ const IDE_CONFIGS = {
|
|
|
47
43
|
codex: {
|
|
48
44
|
name: 'Codex CLI',
|
|
49
45
|
description: '',
|
|
50
|
-
configFile: '
|
|
46
|
+
configFile: '.codex/instructions.md',
|
|
51
47
|
template: 'ide-rules/codex-rules.md',
|
|
52
|
-
requiresDirectory:
|
|
48
|
+
requiresDirectory: true,
|
|
53
49
|
format: 'text',
|
|
54
50
|
recommended: true,
|
|
55
51
|
agentFolder: path.join('.codex', 'agents'),
|
|
56
52
|
},
|
|
57
|
-
gemini: {
|
|
58
|
-
name: 'Gemini CLI',
|
|
59
|
-
description: '',
|
|
60
|
-
configFile: path.join('.gemini', 'rules.md'),
|
|
61
|
-
template: 'ide-rules/gemini-rules.md',
|
|
62
|
-
requiresDirectory: true,
|
|
63
|
-
format: 'text',
|
|
64
|
-
agentFolder: path.join('.gemini', 'rules', 'SINAPSE', 'agents'),
|
|
65
|
-
},
|
|
66
|
-
cursor: {
|
|
67
|
-
name: 'Cursor',
|
|
68
|
-
description: '',
|
|
69
|
-
configFile: path.join('.cursor', 'rules.md'),
|
|
70
|
-
template: 'ide-rules/cursor-rules.md',
|
|
71
|
-
requiresDirectory: true,
|
|
72
|
-
format: 'text',
|
|
73
|
-
agentFolder: path.join('.cursor', 'rules'),
|
|
74
|
-
},
|
|
75
|
-
'github-copilot': {
|
|
76
|
-
name: 'GitHub Copilot',
|
|
77
|
-
description: '',
|
|
78
|
-
configFile: path.join('.github', 'copilot-instructions.md'),
|
|
79
|
-
template: 'ide-rules/copilot-rules.md',
|
|
80
|
-
requiresDirectory: true,
|
|
81
|
-
format: 'text',
|
|
82
|
-
agentFolder: path.join('.github', 'agents'),
|
|
83
|
-
},
|
|
84
|
-
antigravity: {
|
|
85
|
-
name: 'AntiGravity',
|
|
86
|
-
description: '',
|
|
87
|
-
configFile: path.join('.antigravity', 'rules.md'),
|
|
88
|
-
template: 'ide-rules/antigravity-rules.md',
|
|
89
|
-
requiresDirectory: true,
|
|
90
|
-
format: 'text',
|
|
91
|
-
agentFolder: path.join('.agent', 'workflows'),
|
|
92
|
-
specialConfig: {
|
|
93
|
-
type: 'antigravity',
|
|
94
|
-
configJsonPath: path.join('.antigravity', 'antigravity.json'),
|
|
95
|
-
workflowsFolder: path.join('.agent', 'workflows'),
|
|
96
|
-
agentsFolder: path.join('.antigravity', 'agents'),
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
53
|
};
|
|
100
54
|
|
|
101
55
|
/**
|
|
@@ -264,7 +264,7 @@ config:
|
|
|
264
264
|
tier2: 2
|
|
265
265
|
tier3: 3
|
|
266
266
|
tools:
|
|
267
|
-
transcription: "
|
|
267
|
+
transcription: "Whisper API"
|
|
268
268
|
search: "Brave Search"
|
|
269
269
|
processing: "Claude Code (Max)"
|
|
270
270
|
sync: "Syncthing"
|
|
@@ -274,7 +274,7 @@ dependencies:
|
|
|
274
274
|
python: []
|
|
275
275
|
squads: []
|
|
276
276
|
external:
|
|
277
|
-
- name:
|
|
277
|
+
- name: Whisper
|
|
278
278
|
purpose: "Whisper transcription, Playwright capture"
|
|
279
279
|
required: false
|
|
280
280
|
- name: Brave Search
|
|
@@ -189,12 +189,12 @@ cross_squad_connections:
|
|
|
189
189
|
inbound:
|
|
190
190
|
- squad-commercial: "Dados de vendas, propostas fechadas, pipeline comercial"
|
|
191
191
|
- squad-growth: "Metricas de growth, CAC, conversion rates, funnel data"
|
|
192
|
-
- squad-
|
|
192
|
+
- squad-commercial: "Dados operacionais, timesheets, utilizacao de equipe"
|
|
193
193
|
- squad-product: "Custos de desenvolvimento, estimativas de esforco"
|
|
194
194
|
outbound:
|
|
195
195
|
- squad-commercial: "Rate cards, pricing tiers, margens por servico para propostas"
|
|
196
196
|
- squad-growth: "Unit economics, LTV/CAC, ROI por canal para otimizacao"
|
|
197
|
-
- squad-
|
|
197
|
+
- squad-commercial: "Budget targets, cost centers, vendor budgets"
|
|
198
198
|
- squad-brand: "Investimento em marca, ROI de branding"
|
|
199
199
|
|
|
200
200
|
tags:
|
|
@@ -80,7 +80,7 @@ Product experiments are owned by squad-product. However:
|
|
|
80
80
|
|
|
81
81
|
## Cross-Squad Handoffs
|
|
82
82
|
- **Receives from:** squad-commercial (NPS, feature requests), squad-research (market data)
|
|
83
|
-
- **Sends to:** squad-
|
|
83
|
+
- **Sends to:** squad-commercial (resource needs), squad-design (discovery opportunities)
|
|
84
84
|
|
|
85
85
|
## Escalation
|
|
86
86
|
|
|
@@ -233,7 +233,7 @@ cross_squad_handoffs:
|
|
|
233
233
|
receives: "UX designs, design system components, accessibility audit"
|
|
234
234
|
|
|
235
235
|
outbound:
|
|
236
|
-
- to: squad-
|
|
236
|
+
- to: squad-commercial
|
|
237
237
|
sends: "Resource needs, sprint capacity forecasts, process automation requests"
|
|
238
238
|
- to: squad-design
|
|
239
239
|
sends: "Discovery opportunities for UX, product specs for UI design"
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Antigravity Transformer - Cursor-style format
|
|
3
|
-
* @story 6.19 - IDE Command Auto-Sync System
|
|
4
|
-
*
|
|
5
|
-
* Format: Similar to Cursor, condensed rules format
|
|
6
|
-
* Target: .antigravity/rules/agents/*.md
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { getVisibleCommands, normalizeCommands } = require('../agent-parser');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Transform agent data to Antigravity format
|
|
13
|
-
* @param {object} agentData - Parsed agent data from agent-parser
|
|
14
|
-
* @returns {string} - Transformed content
|
|
15
|
-
*/
|
|
16
|
-
function transform(agentData) {
|
|
17
|
-
const agent = agentData.agent || {};
|
|
18
|
-
const persona = agentData.persona_profile || {};
|
|
19
|
-
|
|
20
|
-
const icon = agent.icon || '🤖';
|
|
21
|
-
const name = agent.name || agentData.id;
|
|
22
|
-
const title = agent.title || 'SINAPSE Agent';
|
|
23
|
-
const whenToUse = agent.whenToUse || 'Use this agent for specific tasks';
|
|
24
|
-
const archetype = persona.archetype || '';
|
|
25
|
-
|
|
26
|
-
// Get quick visibility commands (normalized to consistent format)
|
|
27
|
-
const allCommands = normalizeCommands(agentData.commands || []);
|
|
28
|
-
const quickCommands = getVisibleCommands(allCommands, 'quick');
|
|
29
|
-
const keyCommands = getVisibleCommands(allCommands, 'key');
|
|
30
|
-
|
|
31
|
-
// Build content (similar to Cursor)
|
|
32
|
-
let content = `# ${name} (@${agentData.id})
|
|
33
|
-
|
|
34
|
-
${icon} **${title}**${archetype ? ` | ${archetype}` : ''}
|
|
35
|
-
|
|
36
|
-
> ${whenToUse}
|
|
37
|
-
|
|
38
|
-
`;
|
|
39
|
-
|
|
40
|
-
// Add quick commands section
|
|
41
|
-
if (quickCommands.length > 0) {
|
|
42
|
-
content += `## Quick Commands
|
|
43
|
-
|
|
44
|
-
`;
|
|
45
|
-
for (const cmd of quickCommands) {
|
|
46
|
-
content += `- \`*${cmd.name}\` - ${cmd.description || 'No description'}\n`;
|
|
47
|
-
}
|
|
48
|
-
content += '\n';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Add key commands if different from quick
|
|
52
|
-
const keyOnlyCommands = keyCommands.filter(
|
|
53
|
-
k => !quickCommands.some(q => q.name === k.name)
|
|
54
|
-
);
|
|
55
|
-
if (keyOnlyCommands.length > 0) {
|
|
56
|
-
content += `## Key Commands
|
|
57
|
-
|
|
58
|
-
`;
|
|
59
|
-
for (const cmd of keyOnlyCommands) {
|
|
60
|
-
content += `- \`*${cmd.name}\` - ${cmd.description || 'No description'}\n`;
|
|
61
|
-
}
|
|
62
|
-
content += '\n';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Add all commands for reference (allCommands already normalized above)
|
|
66
|
-
if (allCommands.length > quickCommands.length + keyOnlyCommands.length) {
|
|
67
|
-
content += `## All Commands
|
|
68
|
-
|
|
69
|
-
`;
|
|
70
|
-
for (const cmd of allCommands) {
|
|
71
|
-
content += `- \`*${cmd.name}\` - ${cmd.description || 'No description'}\n`;
|
|
72
|
-
}
|
|
73
|
-
content += '\n';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Add collaboration section if available
|
|
77
|
-
if (agentData.sections.collaboration) {
|
|
78
|
-
content += `## Collaboration
|
|
79
|
-
|
|
80
|
-
${agentData.sections.collaboration}
|
|
81
|
-
|
|
82
|
-
`;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
content += `---
|
|
86
|
-
*SINAPSE Agent - Synced from .sinapse-ai/development/agents/${agentData.filename}*
|
|
87
|
-
`;
|
|
88
|
-
|
|
89
|
-
return content;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get the target filename for this agent
|
|
94
|
-
* @param {object} agentData - Parsed agent data
|
|
95
|
-
* @returns {string} - Target filename
|
|
96
|
-
*/
|
|
97
|
-
function getFilename(agentData) {
|
|
98
|
-
return agentData.filename;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports = {
|
|
102
|
-
transform,
|
|
103
|
-
getFilename,
|
|
104
|
-
format: 'cursor-style',
|
|
105
|
-
};
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cursor Transformer - Condensed rules format
|
|
3
|
-
* @story 6.19 - IDE Command Auto-Sync System
|
|
4
|
-
*
|
|
5
|
-
* Format: Condensed markdown with icon, title, quick commands
|
|
6
|
-
* Target: .cursor/rules/agents/*.md
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { getVisibleCommands, normalizeCommands } = require('../agent-parser');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Transform agent data to Cursor format
|
|
13
|
-
* @param {object} agentData - Parsed agent data from agent-parser
|
|
14
|
-
* @returns {string} - Transformed content
|
|
15
|
-
*/
|
|
16
|
-
function transform(agentData) {
|
|
17
|
-
const agent = agentData.agent || {};
|
|
18
|
-
const persona = agentData.persona_profile || {};
|
|
19
|
-
|
|
20
|
-
const icon = agent.icon || '🤖';
|
|
21
|
-
const name = agent.name || agentData.id;
|
|
22
|
-
const title = agent.title || 'SINAPSE Agent';
|
|
23
|
-
const whenToUse = agent.whenToUse || 'Use this agent for specific tasks';
|
|
24
|
-
const archetype = persona.archetype || '';
|
|
25
|
-
|
|
26
|
-
// Get quick visibility commands (normalized to consistent format)
|
|
27
|
-
const allCommands = normalizeCommands(agentData.commands || []);
|
|
28
|
-
const quickCommands = getVisibleCommands(allCommands, 'quick');
|
|
29
|
-
const keyCommands = getVisibleCommands(allCommands, 'key');
|
|
30
|
-
|
|
31
|
-
// Build content
|
|
32
|
-
let content = `# ${name} (@${agentData.id})
|
|
33
|
-
|
|
34
|
-
${icon} **${title}**${archetype ? ` | ${archetype}` : ''}
|
|
35
|
-
|
|
36
|
-
> ${whenToUse}
|
|
37
|
-
|
|
38
|
-
`;
|
|
39
|
-
|
|
40
|
-
// Add quick commands section
|
|
41
|
-
if (quickCommands.length > 0) {
|
|
42
|
-
content += `## Quick Commands
|
|
43
|
-
|
|
44
|
-
`;
|
|
45
|
-
for (const cmd of quickCommands) {
|
|
46
|
-
content += `- \`*${cmd.name}\` - ${cmd.description || 'No description'}\n`;
|
|
47
|
-
}
|
|
48
|
-
content += '\n';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Add key commands if different from quick
|
|
52
|
-
const keyOnlyCommands = keyCommands.filter(
|
|
53
|
-
k => !quickCommands.some(q => q.name === k.name)
|
|
54
|
-
);
|
|
55
|
-
if (keyOnlyCommands.length > 0) {
|
|
56
|
-
content += `## Key Commands
|
|
57
|
-
|
|
58
|
-
`;
|
|
59
|
-
for (const cmd of keyOnlyCommands) {
|
|
60
|
-
content += `- \`*${cmd.name}\` - ${cmd.description || 'No description'}\n`;
|
|
61
|
-
}
|
|
62
|
-
content += '\n';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Add collaboration section if available
|
|
66
|
-
if (agentData.sections.collaboration) {
|
|
67
|
-
content += `## Collaboration
|
|
68
|
-
|
|
69
|
-
${agentData.sections.collaboration}
|
|
70
|
-
|
|
71
|
-
`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
content += `---
|
|
75
|
-
*SINAPSE Agent - Synced from .sinapse-ai/development/agents/${agentData.filename}*
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
return content;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get the target filename for this agent
|
|
83
|
-
* @param {object} agentData - Parsed agent data
|
|
84
|
-
* @returns {string} - Target filename
|
|
85
|
-
*/
|
|
86
|
-
function getFilename(agentData) {
|
|
87
|
-
return agentData.filename;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = {
|
|
91
|
-
transform,
|
|
92
|
-
getFilename,
|
|
93
|
-
format: 'condensed-rules',
|
|
94
|
-
};
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Copilot Transformer - YAML frontmatter + condensed markdown
|
|
3
|
-
* @story 6.19 - IDE Command Auto-Sync System
|
|
4
|
-
* @issue #138 - Agent files not compatible with GitHub Copilot
|
|
5
|
-
*
|
|
6
|
-
* Format: .agent.md files with YAML frontmatter (--- delimiters)
|
|
7
|
-
* Target: .github/agents/*.agent.md
|
|
8
|
-
*
|
|
9
|
-
* GitHub Copilot custom agents require:
|
|
10
|
-
* - YAML frontmatter with `description` (required), `name`, `tools`
|
|
11
|
-
* - Markdown body under 30,000 characters
|
|
12
|
-
* - File extension: .agent.md
|
|
13
|
-
*
|
|
14
|
-
* @see https://docs.github.com/en/copilot/reference/custom-agents-configuration
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const { normalizeCommands, getVisibleCommands } = require('../agent-parser');
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Transform agent data to GitHub Copilot custom agent format
|
|
21
|
-
* @param {object} agentData - Parsed agent data from agent-parser
|
|
22
|
-
* @returns {string} - Transformed content with YAML frontmatter
|
|
23
|
-
*/
|
|
24
|
-
function transform(agentData) {
|
|
25
|
-
const agent = agentData.agent || {};
|
|
26
|
-
const persona = agentData.persona_profile || {};
|
|
27
|
-
const yamlData = agentData.yaml || {};
|
|
28
|
-
const personaBlock = yamlData.persona || {};
|
|
29
|
-
|
|
30
|
-
const id = agent.id || agentData.id;
|
|
31
|
-
const name = agent.name || id;
|
|
32
|
-
const title = agent.title || 'SINAPSE Agent';
|
|
33
|
-
const icon = agent.icon || '';
|
|
34
|
-
const description = escapeYamlString(agent.whenToUse || `${title} agent for development tasks`);
|
|
35
|
-
|
|
36
|
-
// Build YAML frontmatter
|
|
37
|
-
const frontmatter = [
|
|
38
|
-
'---',
|
|
39
|
-
`name: ${id}`,
|
|
40
|
-
`description: '${description}'`,
|
|
41
|
-
`tools: ['read', 'edit', 'search', 'execute']`,
|
|
42
|
-
'---',
|
|
43
|
-
].join('\n');
|
|
44
|
-
|
|
45
|
-
// Build markdown body
|
|
46
|
-
const body = buildMarkdownBody({
|
|
47
|
-
id,
|
|
48
|
-
name,
|
|
49
|
-
title,
|
|
50
|
-
icon,
|
|
51
|
-
personaBlock,
|
|
52
|
-
persona,
|
|
53
|
-
commands: agentData.commands || [],
|
|
54
|
-
sections: agentData.sections || {},
|
|
55
|
-
corePrinciples: yamlData.core_principles,
|
|
56
|
-
filename: agentData.filename,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const content = `${frontmatter}\n\n${body}`;
|
|
60
|
-
|
|
61
|
-
// Enforce 30K character limit
|
|
62
|
-
if (content.length > 30000) {
|
|
63
|
-
return truncateContent(content, 30000);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return content;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Build the markdown body for the Copilot agent prompt
|
|
71
|
-
* @param {object} params - Agent parameters
|
|
72
|
-
* @returns {string} - Markdown body
|
|
73
|
-
*/
|
|
74
|
-
function buildMarkdownBody(params) {
|
|
75
|
-
const { id, name, title, icon, personaBlock, persona, commands, sections, filename } = params;
|
|
76
|
-
|
|
77
|
-
const parts = [];
|
|
78
|
-
|
|
79
|
-
// Header
|
|
80
|
-
const headerIcon = icon ? `${icon} ` : '';
|
|
81
|
-
parts.push(`# ${headerIcon}${name} Agent (@${id})\n`);
|
|
82
|
-
|
|
83
|
-
// Role description
|
|
84
|
-
if (personaBlock.role) {
|
|
85
|
-
parts.push(`You are an expert ${personaBlock.role}.\n`);
|
|
86
|
-
} else {
|
|
87
|
-
parts.push(`You are an expert ${title}.\n`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Style
|
|
91
|
-
if (personaBlock.style) {
|
|
92
|
-
parts.push(`## Style\n\n${personaBlock.style}\n`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Core principles (may be in persona block or at root level of YAML)
|
|
96
|
-
const corePrinciples = personaBlock.core_principles || params.corePrinciples;
|
|
97
|
-
if (corePrinciples && Array.isArray(corePrinciples)) {
|
|
98
|
-
parts.push('## Core Principles\n');
|
|
99
|
-
for (const principle of corePrinciples) {
|
|
100
|
-
// Handle both string and object formats (YAML may parse "KEY: value" as {KEY: value})
|
|
101
|
-
if (typeof principle === 'string') {
|
|
102
|
-
parts.push(`- ${principle}`);
|
|
103
|
-
} else if (typeof principle === 'object' && principle !== null) {
|
|
104
|
-
const entries = Object.entries(principle);
|
|
105
|
-
for (const [key, value] of entries) {
|
|
106
|
-
parts.push(`- ${key}: ${value}`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
parts.push('');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Commands reference
|
|
114
|
-
const allCommands = normalizeCommands(commands);
|
|
115
|
-
const keyCommands = getVisibleCommands(allCommands, 'key');
|
|
116
|
-
const quickCommands = getVisibleCommands(allCommands, 'quick');
|
|
117
|
-
const displayCommands = keyCommands.length > 0 ? keyCommands : quickCommands.slice(0, 10);
|
|
118
|
-
|
|
119
|
-
if (displayCommands.length > 0) {
|
|
120
|
-
parts.push('## Commands\n');
|
|
121
|
-
parts.push('Use `*` prefix for commands:\n');
|
|
122
|
-
for (const cmd of displayCommands) {
|
|
123
|
-
parts.push(`- \`*${cmd.name}\` - ${cmd.description || 'No description'}`);
|
|
124
|
-
}
|
|
125
|
-
parts.push('');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Collaboration section (condensed)
|
|
129
|
-
if (sections.collaboration) {
|
|
130
|
-
parts.push(`## Collaboration\n\n${sections.collaboration}\n`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Sync footer
|
|
134
|
-
parts.push('---');
|
|
135
|
-
parts.push(`*SINAPSE Agent - Synced from .sinapse-ai/development/agents/${filename}*`);
|
|
136
|
-
parts.push('');
|
|
137
|
-
|
|
138
|
-
return parts.join('\n');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Escape a string for use as a YAML single-quoted value
|
|
143
|
-
* Single quotes inside the string must be doubled
|
|
144
|
-
* @param {string} str - Input string
|
|
145
|
-
* @returns {string} - Escaped string
|
|
146
|
-
*/
|
|
147
|
-
function escapeYamlString(str) {
|
|
148
|
-
if (!str) return '';
|
|
149
|
-
// In YAML single-quoted strings, single quotes are escaped by doubling them
|
|
150
|
-
return str.replace(/'/g, "''");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Truncate content to fit within character limit while keeping structure valid
|
|
155
|
-
* @param {string} content - Full content
|
|
156
|
-
* @param {number} maxChars - Maximum characters
|
|
157
|
-
* @returns {string} - Truncated content
|
|
158
|
-
*/
|
|
159
|
-
function truncateContent(content, maxChars) {
|
|
160
|
-
// Find the last complete section before the limit
|
|
161
|
-
const truncated = content.substring(0, maxChars - 100);
|
|
162
|
-
const lastNewline = truncated.lastIndexOf('\n\n');
|
|
163
|
-
|
|
164
|
-
if (lastNewline > 0) {
|
|
165
|
-
return truncated.substring(0, lastNewline) + '\n\n---\n*Content truncated to fit 30K limit*\n';
|
|
166
|
-
}
|
|
167
|
-
return truncated + '\n\n---\n*Content truncated to fit 30K limit*\n';
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Get the target filename for this agent (with .agent.md extension)
|
|
172
|
-
* @param {object} agentData - Parsed agent data
|
|
173
|
-
* @returns {string} - Target filename (e.g., "dev.agent.md")
|
|
174
|
-
*/
|
|
175
|
-
function getFilename(agentData) {
|
|
176
|
-
const id = (agentData.agent && agentData.agent.id) || agentData.id;
|
|
177
|
-
return `${id}.agent.md`;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
module.exports = {
|
|
181
|
-
transform,
|
|
182
|
-
getFilename,
|
|
183
|
-
format: 'github-copilot',
|
|
184
|
-
};
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
function getDefaultOptions() {
|
|
8
|
-
const projectRoot = process.cwd();
|
|
9
|
-
return {
|
|
10
|
-
projectRoot,
|
|
11
|
-
rulesFile: path.join(projectRoot, '.gemini', 'rules.md'),
|
|
12
|
-
agentsDir: path.join(projectRoot, '.gemini', 'rules', 'SINAPSE', 'agents'),
|
|
13
|
-
commandsDir: path.join(projectRoot, '.gemini', 'commands'),
|
|
14
|
-
extensionDir: path.join(projectRoot, 'packages', 'gemini-sinapse-extension'),
|
|
15
|
-
sourceAgentsDir: path.join(projectRoot, '.sinapse-ai', 'development', 'agents'),
|
|
16
|
-
quiet: false,
|
|
17
|
-
json: false,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function parseArgs(argv = process.argv.slice(2)) {
|
|
22
|
-
const args = new Set(argv);
|
|
23
|
-
return {
|
|
24
|
-
quiet: args.has('--quiet') || args.has('-q'),
|
|
25
|
-
json: args.has('--json'),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function countMarkdownFiles(dirPath) {
|
|
30
|
-
if (!fs.existsSync(dirPath)) return 0;
|
|
31
|
-
return fs.readdirSync(dirPath).filter((f) => f.endsWith('.md')).length;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function validateGeminiIntegration(options = {}) {
|
|
35
|
-
const projectRoot = options.projectRoot || process.cwd();
|
|
36
|
-
const resolved = {
|
|
37
|
-
...getDefaultOptions(),
|
|
38
|
-
...options,
|
|
39
|
-
projectRoot,
|
|
40
|
-
rulesFile: options.rulesFile || path.join(projectRoot, '.gemini', 'rules.md'),
|
|
41
|
-
agentsDir: options.agentsDir || path.join(projectRoot, '.gemini', 'rules', 'SINAPSE', 'agents'),
|
|
42
|
-
commandsDir: options.commandsDir || path.join(projectRoot, '.gemini', 'commands'),
|
|
43
|
-
extensionDir: options.extensionDir || path.join(projectRoot, 'packages', 'gemini-sinapse-extension'),
|
|
44
|
-
sourceAgentsDir: options.sourceAgentsDir || path.join(projectRoot, '.sinapse-ai', 'development', 'agents'),
|
|
45
|
-
};
|
|
46
|
-
const errors = [];
|
|
47
|
-
const warnings = [];
|
|
48
|
-
|
|
49
|
-
if (!fs.existsSync(resolved.rulesFile)) {
|
|
50
|
-
warnings.push(`Gemini rules file not found yet: ${path.relative(resolved.projectRoot, resolved.rulesFile)}`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (!fs.existsSync(resolved.agentsDir)) {
|
|
54
|
-
errors.push(`Missing Gemini agents dir: ${path.relative(resolved.projectRoot, resolved.agentsDir)}`);
|
|
55
|
-
}
|
|
56
|
-
if (!fs.existsSync(resolved.commandsDir)) {
|
|
57
|
-
errors.push(`Missing Gemini commands dir: ${path.relative(resolved.projectRoot, resolved.commandsDir)}`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const sourceCount = countMarkdownFiles(resolved.sourceAgentsDir);
|
|
61
|
-
const geminiCount = countMarkdownFiles(resolved.agentsDir);
|
|
62
|
-
const commandFiles = fs.existsSync(resolved.commandsDir)
|
|
63
|
-
? fs.readdirSync(resolved.commandsDir).filter((f) => f.endsWith('.toml'))
|
|
64
|
-
: [];
|
|
65
|
-
const expectedCommandCount = sourceCount > 0 ? sourceCount + 1 : 0;
|
|
66
|
-
|
|
67
|
-
if (sourceCount > 0 && commandFiles.length !== expectedCommandCount) {
|
|
68
|
-
warnings.push(`Gemini command count differs from source (${commandFiles.length}/${expectedCommandCount})`);
|
|
69
|
-
}
|
|
70
|
-
if (!commandFiles.includes('sinapse-menu.toml')) {
|
|
71
|
-
errors.push(`Missing Gemini command file: ${path.relative(resolved.projectRoot, path.join(resolved.commandsDir, 'sinapse-menu.toml'))}`);
|
|
72
|
-
}
|
|
73
|
-
if (sourceCount > 0 && geminiCount !== sourceCount) {
|
|
74
|
-
warnings.push(`Gemini agent count differs from source (${geminiCount}/${sourceCount})`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const requiredExtensionFiles = [
|
|
78
|
-
'extension.json',
|
|
79
|
-
'README.md',
|
|
80
|
-
path.join('commands', 'sinapse-status.js'),
|
|
81
|
-
path.join('commands', 'sinapse-agents.js'),
|
|
82
|
-
path.join('commands', 'sinapse-validate.js'),
|
|
83
|
-
path.join('hooks', 'hooks.json'),
|
|
84
|
-
];
|
|
85
|
-
|
|
86
|
-
for (const rel of requiredExtensionFiles) {
|
|
87
|
-
const abs = path.join(resolved.extensionDir, rel);
|
|
88
|
-
if (!fs.existsSync(abs)) {
|
|
89
|
-
errors.push(`Missing Gemini extension file: ${path.relative(resolved.projectRoot, abs)}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
ok: errors.length === 0,
|
|
95
|
-
errors,
|
|
96
|
-
warnings,
|
|
97
|
-
metrics: {
|
|
98
|
-
sourceAgents: sourceCount,
|
|
99
|
-
geminiAgents: geminiCount,
|
|
100
|
-
geminiCommands: commandFiles.length,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function formatHumanReport(result) {
|
|
106
|
-
if (result.ok) {
|
|
107
|
-
const lines = [
|
|
108
|
-
`✅ Gemini integration validation passed (agents: ${result.metrics.geminiAgents}, commands: ${result.metrics.geminiCommands})`,
|
|
109
|
-
];
|
|
110
|
-
if (result.warnings.length > 0) {
|
|
111
|
-
lines.push(...result.warnings.map((w) => `⚠️ ${w}`));
|
|
112
|
-
}
|
|
113
|
-
return lines.join('\n');
|
|
114
|
-
}
|
|
115
|
-
const lines = [
|
|
116
|
-
`❌ Gemini integration validation failed (${result.errors.length} issue(s))`,
|
|
117
|
-
...result.errors.map((e) => `- ${e}`),
|
|
118
|
-
];
|
|
119
|
-
if (result.warnings.length > 0) {
|
|
120
|
-
lines.push(...result.warnings.map((w) => `⚠️ ${w}`));
|
|
121
|
-
}
|
|
122
|
-
return lines.join('\n');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function main() {
|
|
126
|
-
const args = parseArgs();
|
|
127
|
-
const result = validateGeminiIntegration(args);
|
|
128
|
-
|
|
129
|
-
if (!args.quiet) {
|
|
130
|
-
if (args.json) {
|
|
131
|
-
console.log(JSON.stringify(result, null, 2));
|
|
132
|
-
} else {
|
|
133
|
-
console.log(formatHumanReport(result));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!result.ok) {
|
|
138
|
-
process.exitCode = 1;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (require.main === module) {
|
|
143
|
-
main();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
module.exports = {
|
|
147
|
-
validateGeminiIntegration,
|
|
148
|
-
parseArgs,
|
|
149
|
-
getDefaultOptions,
|
|
150
|
-
countMarkdownFiles,
|
|
151
|
-
};
|