@maccesar/titools 2.0.6 → 2.2.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/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
- package/README.md +250 -168
- package/agents/{ti-researcher.md → ti-pro.md} +10 -10
- package/bin/titools.js +16 -12
- package/lib/cleanup.js +95 -0
- package/lib/commands/agents.js +146 -70
- package/lib/commands/skills.js +349 -0
- package/lib/commands/uninstall.js +189 -154
- package/lib/commands/update.js +104 -21
- package/lib/config.js +26 -20
- package/lib/downloader.js +1 -1
- package/lib/installer.js +37 -97
- package/lib/platform.js +9 -5
- package/lib/prompts/checkboxCancel.js +264 -0
- package/lib/prompts/selectCancel.js +204 -0
- package/lib/symlink.js +19 -7
- package/lib/utils.js +21 -31
- package/package.json +10 -10
- package/skills/alloy-guides/SKILL.md +8 -30
- package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
- package/skills/alloy-guides/references/CONCEPTS.md +5 -25
- package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
- package/skills/alloy-guides/references/MODELS.md +40 -10
- package/skills/alloy-guides/references/PURGETSS.md +1 -11
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
- package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
- package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
- package/skills/alloy-guides/references/WIDGETS.md +1 -17
- package/skills/alloy-howtos/SKILL.md +1 -22
- package/skills/alloy-howtos/references/best_practices.md +0 -17
- package/skills/alloy-howtos/references/cli_reference.md +1 -23
- package/skills/alloy-howtos/references/config_files.md +86 -15
- package/skills/alloy-howtos/references/custom_tags.md +14 -13
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
- package/skills/alloy-howtos/references/samples.md +4 -14
- package/skills/purgetss/SKILL.md +11 -37
- package/skills/purgetss/references/EXAMPLES.md +106 -17
- package/skills/purgetss/references/animation-system.md +0 -67
- package/skills/purgetss/references/apply-directive.md +0 -18
- package/skills/purgetss/references/arbitrary-values.md +0 -25
- package/skills/purgetss/references/class-index.md +0 -46
- package/skills/purgetss/references/cli-commands.md +0 -41
- package/skills/purgetss/references/configurable-properties.md +0 -55
- package/skills/purgetss/references/custom-rules.md +0 -14
- package/skills/purgetss/references/customization-deep-dive.md +0 -49
- package/skills/purgetss/references/dynamic-component-creation.md +56 -37
- package/skills/purgetss/references/grid-layout.md +0 -32
- package/skills/purgetss/references/icon-fonts.md +0 -50
- package/skills/purgetss/references/installation-setup.md +61 -32
- package/skills/purgetss/references/migration-guide.md +127 -0
- package/skills/purgetss/references/opacity-modifier.md +0 -34
- package/skills/purgetss/references/performance-tips.md +261 -0
- package/skills/purgetss/references/platform-modifiers.md +0 -46
- package/skills/purgetss/references/smart-mappings.md +0 -12
- package/skills/purgetss/references/tikit-components.md +393 -0
- package/skills/purgetss/references/titanium-resets.md +1 -27
- package/skills/purgetss/references/ui-ux-design.md +467 -117
- package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
- package/skills/ti-expert/references/alloy-builtins.md +387 -0
- package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
- package/skills/ti-expert/references/anti-patterns.md +90 -0
- package/skills/ti-expert/references/cli-expert.md +109 -0
- package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
- package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
- package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
- package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
- package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
- package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
- package/skills/ti-expert/references/performance-listview.md +251 -0
- package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
- package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
- package/skills/ti-expert/references/security-fundamentals.md +284 -0
- package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
- package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
- package/skills/ti-expert/references/testing-unit.md +433 -0
- package/skills/ti-expert/references/theming.md +394 -0
- package/skills/ti-guides/SKILL.md +1 -14
- package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
- package/skills/ti-guides/references/app-distribution.md +48 -10
- package/skills/ti-guides/references/application-frameworks.md +9 -2
- package/skills/ti-guides/references/cli-reference.md +338 -82
- package/skills/ti-guides/references/coding-best-practices.md +14 -4
- package/skills/ti-guides/references/commonjs-advanced.md +103 -6
- package/skills/ti-guides/references/hello-world.md +5 -2
- package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
- package/skills/ti-guides/references/javascript-primer.md +4 -3
- package/skills/ti-guides/references/resources.md +0 -1
- package/skills/ti-guides/references/style-and-conventions.md +57 -9
- package/skills/ti-guides/references/tiapp-config.md +48 -6
- package/skills/ti-howtos/SKILL.md +2 -27
- package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
- package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
- package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
- package/skills/ti-howtos/references/cross-platform-development.md +68 -37
- package/skills/ti-howtos/references/debugging-profiling.md +8 -53
- package/skills/ti-howtos/references/extending-titanium.md +12 -51
- package/skills/ti-howtos/references/google-maps-v2.md +30 -29
- package/skills/ti-howtos/references/ios-map-kit.md +19 -25
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
- package/skills/ti-howtos/references/local-data-sources.md +45 -37
- package/skills/ti-howtos/references/location-and-maps.md +47 -28
- package/skills/ti-howtos/references/media-apis.md +84 -27
- package/skills/ti-howtos/references/notification-services.md +40 -89
- package/skills/ti-howtos/references/remote-data-sources.md +21 -36
- package/skills/ti-howtos/references/tutorials.md +79 -39
- package/skills/ti-howtos/references/using-modules.md +4 -30
- package/skills/ti-howtos/references/web-content-integration.md +28 -45
- package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
- package/skills/ti-ui/SKILL.md +1 -21
- package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
- package/skills/ti-ui/references/animation-and-matrices.md +0 -47
- package/skills/ti-ui/references/application-structures.md +0 -46
- package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
- package/skills/ti-ui/references/event-handling.md +32 -40
- package/skills/ti-ui/references/gestures.md +0 -40
- package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
- package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
- package/skills/ti-ui/references/listviews-and-performance.md +187 -73
- package/skills/ti-ui/references/orientation.md +57 -71
- package/skills/ti-ui/references/platform-ui-android.md +114 -48
- package/skills/ti-ui/references/platform-ui-ios.md +63 -38
- package/skills/ti-ui/references/scrolling-views.md +14 -23
- package/skills/ti-ui/references/tableviews.md +6 -56
- package/lib/commands/install.js +0 -188
- package/skills/alloy-expert/references/anti-patterns.md +0 -133
- package/skills/alloy-expert/references/testing.md +0 -872
- package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
- package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
- /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
- /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: ti-
|
|
2
|
+
name: ti-pro
|
|
3
3
|
description: Titanium SDK and Alloy research specialist. Preloads all 7 titanium-* skills for comprehensive analysis. Use proactively for: analyzing Titanium/Alloy codebases, reviewing Alloy app architecture, researching Titanium SDK implementations, exploring mobile app architectural questions, multi-feature research across Titanium APIs, cross-referencing framework patterns, or investigating platform-specific Titanium differences. Returns findings with specific file/line references from all documentation.
|
|
4
4
|
skills:
|
|
5
|
-
-
|
|
5
|
+
- ti-expert
|
|
6
6
|
- alloy-guides
|
|
7
7
|
- alloy-howtos
|
|
8
8
|
- purgetss
|
|
@@ -21,10 +21,10 @@ You are a deep-dive research specialist for Titanium SDK and Alloy mobile develo
|
|
|
21
21
|
|
|
22
22
|
When invoked, you research complex topics by consulting **all 7 preloaded titanium-\*** skills:
|
|
23
23
|
|
|
24
|
-
- `
|
|
24
|
+
- `ti-expert` - Architecture, patterns, conventions
|
|
25
25
|
- `alloy-guides` - Alloy MVC complete reference
|
|
26
26
|
- `alloy-howtos` - CLI, config, debugging
|
|
27
|
-
- `purgetss` - Utility-first styling classes
|
|
27
|
+
- `purgetss` - Utility-first styling classes (optional addon — use when the project already has it or the user asks about it)
|
|
28
28
|
- `ti-guides` - SDK official guides, Hyperloop, distribution
|
|
29
29
|
- `ti-howtos` - Native features, platform-specific APIs
|
|
30
30
|
- `ti-ui` - UI/UX patterns, layouts, gestures
|
|
@@ -43,7 +43,7 @@ When invoked, you research complex topics by consulting **all 7 preloaded titani
|
|
|
43
43
|
| -------------------------- | ------------------------------------------------------------------ |
|
|
44
44
|
| **Codebase analysis** | "Analyze this Alloy app's architecture and identify anti-patterns" |
|
|
45
45
|
| **Multi-feature research** | "Research how to implement location + push + background sync" |
|
|
46
|
-
| **Cross-skills questions** | "Compare ListView vs TableView performance
|
|
46
|
+
| **Cross-skills questions** | "Compare ListView vs TableView performance and styling approaches" |
|
|
47
47
|
| **Architecture review** | "Review this project's folder structure and service layer" |
|
|
48
48
|
| **Platform differences** | "Research iOS vs Android differences for this feature" |
|
|
49
49
|
|
|
@@ -51,7 +51,7 @@ When invoked, you research complex topics by consulting **all 7 preloaded titani
|
|
|
51
51
|
|
|
52
52
|
| Use Instead | Reason |
|
|
53
53
|
| -------------------------------------------- | -------------------------------------- |
|
|
54
|
-
| `/
|
|
54
|
+
| `/ti-expert` for architecture guidance | Inline consultation during development |
|
|
55
55
|
| `/purgetss` to verify a class | Quick inline reference |
|
|
56
56
|
| `/ti-howtos` for step-by-step implementation | Task-oriented guidance |
|
|
57
57
|
| Main conversation for iterative work | Sub-agents run in isolation |
|
|
@@ -72,7 +72,7 @@ Example:
|
|
|
72
72
|
Your app uses `Ti.App.fireEvent` which causes memory leaks.
|
|
73
73
|
|
|
74
74
|
## Key Points
|
|
75
|
-
- **
|
|
75
|
+
- **ti-expert/references/anti-patterns.md:45** - Ti.App.fireEvent leaks memory
|
|
76
76
|
- **alloy-howtos/references/best_practices.md:23** - Use Backbone.Events instead
|
|
77
77
|
|
|
78
78
|
## Solution
|
|
@@ -103,6 +103,6 @@ You **cannot** modify files. If the user asks for changes, provide the research
|
|
|
103
103
|
> **Tip**: Include words like "Titanium", "Alloy", "mobile app", or "architecture review" to ensure the agent is triggered for Titanium-specific analysis.
|
|
104
104
|
|
|
105
105
|
**Manual activation (always works):**
|
|
106
|
-
- "Use the ti-
|
|
107
|
-
- "Have ti-
|
|
108
|
-
- "Use ti-
|
|
106
|
+
- "Use the ti-pro agent to analyze this codebase"
|
|
107
|
+
- "Have ti-pro investigate the architecture of this project"
|
|
108
|
+
- "Use ti-pro to research platform-specific differences for this feature"
|
package/bin/titools.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { Command } from 'commander';
|
|
9
9
|
import { PACKAGE_VERSION } from '../lib/config.js';
|
|
10
|
-
import {
|
|
10
|
+
import { skillsCommand } from '../lib/commands/skills.js';
|
|
11
11
|
import { agentsCommand } from '../lib/commands/agents.js';
|
|
12
12
|
import { updateCommand } from '../lib/commands/update.js';
|
|
13
13
|
import { uninstallCommand } from '../lib/commands/uninstall.js';
|
|
@@ -16,35 +16,39 @@ const program = new Command();
|
|
|
16
16
|
|
|
17
17
|
program
|
|
18
18
|
.name('titools')
|
|
19
|
-
.description('Titanium SDK
|
|
19
|
+
.description('Titanium SDK Knowledge CLI - Manage skills and knowledge for AI coding assistants')
|
|
20
20
|
.version(PACKAGE_VERSION);
|
|
21
21
|
|
|
22
22
|
// Install command
|
|
23
23
|
program
|
|
24
24
|
.command('install')
|
|
25
|
-
.description('Install Titanium
|
|
26
|
-
.option('-
|
|
25
|
+
.description('Install Titanium knowledge packages and platform links')
|
|
26
|
+
.option('-l, --local', 'Install skills locally in the current project')
|
|
27
|
+
.option('-a, --all', 'Install all detected platforms without prompting')
|
|
27
28
|
.option('--path <path>', 'Install to a custom path (skips symlink setup)')
|
|
28
|
-
.action(
|
|
29
|
+
.action(skillsCommand);
|
|
29
30
|
|
|
30
|
-
//
|
|
31
|
+
// Sync command
|
|
31
32
|
program
|
|
32
|
-
.command('
|
|
33
|
-
.description('
|
|
33
|
+
.command('sync')
|
|
34
|
+
.description('Sync knowledge index files (AGENTS.md/CLAUDE.md/GEMINI.md) in a Titanium project')
|
|
34
35
|
.argument('[path]', 'Project path (defaults to current directory)', '.')
|
|
35
36
|
.option('-f, --force', 'Overwrite existing files without prompting')
|
|
37
|
+
.option('-v, --verbose', 'Show detailed diagnostics')
|
|
36
38
|
.action(agentsCommand);
|
|
37
39
|
|
|
38
40
|
// Update command
|
|
39
41
|
program
|
|
40
42
|
.command('update')
|
|
41
|
-
.description('Update
|
|
43
|
+
.description('Update installed knowledge packages and agent (not the CLI)')
|
|
44
|
+
.option('-l, --local', 'Update local skills in the current project')
|
|
42
45
|
.action(updateCommand);
|
|
43
46
|
|
|
44
|
-
//
|
|
47
|
+
// Remove command
|
|
45
48
|
program
|
|
46
|
-
.command('
|
|
47
|
-
.description('Remove Titanium
|
|
49
|
+
.command('remove')
|
|
50
|
+
.description('Remove Titanium knowledge packages and agent')
|
|
51
|
+
.option('-l, --local', 'Remove local skills from the current project')
|
|
48
52
|
.action(uninstallCommand);
|
|
49
53
|
|
|
50
54
|
// Parse arguments
|
package/lib/cleanup.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleanup helpers for skills, agents, and symlinks
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
SKILLS,
|
|
7
|
+
LEGACY_SKILLS,
|
|
8
|
+
AGENTS,
|
|
9
|
+
LEGACY_AGENTS,
|
|
10
|
+
getAgentsSkillsDir,
|
|
11
|
+
getClaudeAgentsDir,
|
|
12
|
+
} from './config.js';
|
|
13
|
+
import { detectPlatforms } from './platform.js';
|
|
14
|
+
import { existsSync, lstatSync, rmSync } from 'fs';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
|
|
17
|
+
export function getSkillList({ includeLegacy = true, legacyOnly = false } = {}) {
|
|
18
|
+
if (legacyOnly) return [...LEGACY_SKILLS];
|
|
19
|
+
return includeLegacy ? [...SKILLS, ...LEGACY_SKILLS] : [...SKILLS];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getAgentList({ includeLegacy = true, legacyOnly = false } = {}) {
|
|
23
|
+
if (legacyOnly) return [...LEGACY_AGENTS];
|
|
24
|
+
return includeLegacy ? [...AGENTS, ...LEGACY_AGENTS] : [...AGENTS];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function removeEntriesAtDir(dir, names, { suffix = '', recursive = true } = {}) {
|
|
28
|
+
const results = { removed: [], failed: [] };
|
|
29
|
+
if (!dir || !existsSync(dir)) return results;
|
|
30
|
+
|
|
31
|
+
for (const name of names) {
|
|
32
|
+
const target = join(dir, suffix ? `${name}${suffix}` : name);
|
|
33
|
+
try {
|
|
34
|
+
lstatSync(target);
|
|
35
|
+
rmSync(target, { recursive, force: true });
|
|
36
|
+
results.removed.push(name);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error.code && error.code !== 'ENOENT') {
|
|
39
|
+
results.failed.push(name);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return results;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function removeSkillSymlinks(platformSkillsDir, options = {}) {
|
|
48
|
+
const skillList = getSkillList(options);
|
|
49
|
+
return removeEntriesAtDir(platformSkillsDir, skillList, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function removeLegacySkillSymlinks(platformSkillsDir) {
|
|
53
|
+
return removeSkillSymlinks(platformSkillsDir, { legacyOnly: true });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function removeSkills(baseDir, options = {}) {
|
|
57
|
+
const skillsDir = getAgentsSkillsDir(baseDir);
|
|
58
|
+
const skillList = getSkillList(options);
|
|
59
|
+
return removeEntriesAtDir(skillsDir, skillList, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function removeAgents(baseDir, options = {}) {
|
|
63
|
+
const agentsDir = getClaudeAgentsDir(baseDir);
|
|
64
|
+
const agentList = getAgentList(options);
|
|
65
|
+
return removeEntriesAtDir(agentsDir, agentList, { suffix: '.md', recursive: false });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function cleanupLegacyArtifacts(baseDir) {
|
|
69
|
+
removeSkills(baseDir, { legacyOnly: true });
|
|
70
|
+
removeAgents(baseDir, { legacyOnly: true });
|
|
71
|
+
|
|
72
|
+
const platforms = detectPlatforms(baseDir);
|
|
73
|
+
for (const platform of platforms) {
|
|
74
|
+
removeLegacySkillSymlinks(platform.skillsDir);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (baseDir) {
|
|
78
|
+
removeSkills(undefined, { legacyOnly: true });
|
|
79
|
+
removeAgents(undefined, { legacyOnly: true });
|
|
80
|
+
const globalPlatforms = detectPlatforms();
|
|
81
|
+
for (const platform of globalPlatforms) {
|
|
82
|
+
removeLegacySkillSymlinks(platform.skillsDir);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
getSkillList,
|
|
89
|
+
getAgentList,
|
|
90
|
+
removeSkillSymlinks,
|
|
91
|
+
removeLegacySkillSymlinks,
|
|
92
|
+
removeSkills,
|
|
93
|
+
removeAgents,
|
|
94
|
+
cleanupLegacyArtifacts,
|
|
95
|
+
};
|
package/lib/commands/agents.js
CHANGED
|
@@ -3,21 +3,19 @@
|
|
|
3
3
|
* Adds AGENTS.md/CLAUDE.md/GEMINI.md to Titanium projects
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import inquirer from 'inquirer';
|
|
7
6
|
import chalk from 'chalk';
|
|
8
7
|
import ora from 'ora';
|
|
9
8
|
import {
|
|
10
|
-
getAgentsDir,
|
|
11
9
|
getAgentsSkillsDir,
|
|
12
|
-
|
|
13
|
-
AI_FILE_PRIORITIES,
|
|
10
|
+
SKILLS,
|
|
14
11
|
} from '../config.js';
|
|
12
|
+
import checkbox, { Separator } from '../prompts/checkboxCancel.js';
|
|
15
13
|
import {
|
|
16
14
|
isTitaniumProject,
|
|
17
15
|
detectTitaniumVersion,
|
|
18
|
-
getAIFiles,
|
|
19
|
-
determineFilesToUpdate,
|
|
20
16
|
addOrUpdateBlock,
|
|
17
|
+
blockExists,
|
|
18
|
+
removeOldBlock,
|
|
21
19
|
} from '../utils.js';
|
|
22
20
|
import { existsSync, writeFileSync } from 'fs';
|
|
23
21
|
import { join, resolve } from 'path';
|
|
@@ -28,28 +26,47 @@ import { join, resolve } from 'path';
|
|
|
28
26
|
* @param {Object} options - Command options
|
|
29
27
|
*/
|
|
30
28
|
export async function agentsCommand(projectPath, options) {
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
const effectiveOptions = options || {};
|
|
30
|
+
const inline = !!effectiveOptions.inline;
|
|
31
|
+
if (!inline) {
|
|
32
|
+
console.log('');
|
|
33
|
+
}
|
|
34
|
+
console.log(chalk.bold.blue('Titanium AI Knowledge Manager'));
|
|
33
35
|
console.log('');
|
|
34
36
|
|
|
35
37
|
// Resolve project path
|
|
36
38
|
const projectDir = resolve(projectPath);
|
|
37
39
|
|
|
38
|
-
// Verify skills are installed (needed for building index)
|
|
39
|
-
const agentsSkillsDir = getAgentsSkillsDir();
|
|
40
|
-
if (!existsSync(agentsSkillsDir)) {
|
|
41
|
-
console.log(chalk.red('Error: Skills not installed'));
|
|
42
|
-
console.log('Install titools first:');
|
|
43
|
-
console.log(' titools install');
|
|
44
|
-
console.log('');
|
|
45
|
-
console.log('This command needs access to Titanium skills to build the documentation index.');
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
40
|
// Verify this is a Titanium project
|
|
50
41
|
if (!isTitaniumProject(projectDir)) {
|
|
51
42
|
console.log(chalk.red('Error: Not a Titanium project (no tiapp.xml)'));
|
|
52
|
-
console.log('Run this command from
|
|
43
|
+
console.log('Run this command from the project root.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
// Check for local vs global skills
|
|
47
|
+
const localSkillsPaths = {
|
|
48
|
+
'CLAUDE.md': join(projectDir, '.claude', 'skills'),
|
|
49
|
+
'GEMINI.md': join(projectDir, '.gemini', 'skills'),
|
|
50
|
+
'AGENTS.md': join(projectDir, '.agents', 'skills'),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const agentsSkillsDir = getAgentsSkillsDir();
|
|
54
|
+
const hasSkillsAt = (skillsDir) =>
|
|
55
|
+
skillsDir && SKILLS.some((skill) => existsSync(join(skillsDir, skill)));
|
|
56
|
+
const hasGlobalSkills = hasSkillsAt(agentsSkillsDir);
|
|
57
|
+
const hasAnyLocalSkills = Object.values(localSkillsPaths).some(hasSkillsAt);
|
|
58
|
+
|
|
59
|
+
// Verify skills are installed (either global or local)
|
|
60
|
+
if (!hasGlobalSkills && !hasAnyLocalSkills) {
|
|
61
|
+
console.log(chalk.red('Error: Skills not installed.'));
|
|
62
|
+
console.log(`${chalk.bold('Run:')} ${chalk.cyan('titools install')}`);
|
|
63
|
+
if (options?.verbose) {
|
|
64
|
+
console.log(
|
|
65
|
+
chalk.gray(
|
|
66
|
+
`Searched: ${agentsSkillsDir} | ./.agents/skills, ./.claude/skills, ./.gemini/skills`
|
|
67
|
+
)
|
|
68
|
+
);
|
|
69
|
+
}
|
|
53
70
|
process.exit(1);
|
|
54
71
|
}
|
|
55
72
|
|
|
@@ -58,67 +75,126 @@ export async function agentsCommand(projectPath, options) {
|
|
|
58
75
|
console.log(chalk.green('✓'), `Titanium project (SDK ${tiVersion})`);
|
|
59
76
|
console.log('');
|
|
60
77
|
|
|
61
|
-
//
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
// Define potential files
|
|
79
|
+
const possibleFiles = [
|
|
80
|
+
{ name: 'AGENTS.md', value: 'AGENTS.md' },
|
|
81
|
+
{ name: 'CLAUDE.md', value: 'CLAUDE.md' },
|
|
82
|
+
{ name: 'GEMINI.md', value: 'GEMINI.md' },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// Get current state of files
|
|
86
|
+
const fileStates = possibleFiles.map(f => {
|
|
87
|
+
const filePath = join(projectDir, f.value);
|
|
88
|
+
return {
|
|
89
|
+
...f,
|
|
90
|
+
exists: existsSync(filePath),
|
|
91
|
+
hasBlock: blockExists(filePath)
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Determine which files to process
|
|
96
|
+
let selectedFiles = [];
|
|
97
|
+
|
|
98
|
+
if (effectiveOptions.onlyExisting) {
|
|
99
|
+
selectedFiles = fileStates.filter(f => f.exists).map(f => f.value);
|
|
100
|
+
} else if (effectiveOptions.force) {
|
|
101
|
+
selectedFiles = fileStates.filter(f => f.hasBlock).map(f => f.value);
|
|
102
|
+
if (selectedFiles.length === 0) selectedFiles = ['CLAUDE.md'];
|
|
103
|
+
} else {
|
|
104
|
+
try {
|
|
105
|
+
selectedFiles = await checkbox({
|
|
106
|
+
message: 'Select instruction files to sync:',
|
|
107
|
+
choices: [
|
|
108
|
+
...fileStates.map(f => ({
|
|
109
|
+
name: f.name,
|
|
110
|
+
value: f.value,
|
|
111
|
+
checked: f.hasBlock
|
|
112
|
+
})),
|
|
113
|
+
new Separator(' ')
|
|
114
|
+
],
|
|
115
|
+
shortcuts: { invert: null },
|
|
116
|
+
theme: {
|
|
117
|
+
style: {
|
|
118
|
+
renderSelectedChoices: () => '',
|
|
119
|
+
},
|
|
83
120
|
},
|
|
84
|
-
|
|
85
|
-
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.log('\nCancelled.');
|
|
124
|
+
process.exit(0);
|
|
86
125
|
}
|
|
87
126
|
}
|
|
88
127
|
|
|
89
|
-
//
|
|
128
|
+
// Handle cancellation
|
|
129
|
+
if (selectedFiles.includes('cancel')) {
|
|
130
|
+
console.log('Cancelled.');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// If nothing selected, proceed to remove knowledge from all existing files
|
|
135
|
+
if (selectedFiles.length === 0) {
|
|
136
|
+
console.log(chalk.yellow('No selection. Removing knowledge index from all files.'));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Process each file
|
|
90
140
|
const spinner = ora();
|
|
91
141
|
const updated = [];
|
|
142
|
+
const removed = [];
|
|
92
143
|
|
|
93
|
-
for (const
|
|
144
|
+
for (const f of fileStates) {
|
|
145
|
+
const filename = f.value;
|
|
94
146
|
const filePath = join(projectDir, filename);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
147
|
+
const isSelected = selectedFiles.includes(filename);
|
|
148
|
+
|
|
149
|
+
if (isSelected) {
|
|
150
|
+
// ADD or UPDATE
|
|
151
|
+
spinner.start(`${f.hasBlock ? 'Updating' : 'Adding'} knowledge index in ${filename}...`);
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
if (!f.exists && !existsSync(filePath)) {
|
|
155
|
+
writeFileSync(filePath, `# ${filename}\n\n`, 'utf8');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let rootPath = '~/.agents/skills';
|
|
159
|
+
const localPath = localSkillsPaths[filename];
|
|
160
|
+
if (localPath && existsSync(localPath)) {
|
|
161
|
+
rootPath = `./${filename === 'CLAUDE.md' ? '.claude' : filename === 'GEMINI.md' ? '.gemini' : '.agents'}/skills`;
|
|
162
|
+
} else {
|
|
163
|
+
if (filename === 'CLAUDE.md') rootPath = '~/.claude/skills';
|
|
164
|
+
if (filename === 'GEMINI.md') rootPath = '~/.gemini/skills';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
addOrUpdateBlock(filePath, rootPath);
|
|
168
|
+
spinner.succeed(`${filename} updated`);
|
|
169
|
+
updated.push(filename);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
spinner.fail(`Failed to sync ${filename}: ${error.message}`);
|
|
172
|
+
}
|
|
173
|
+
} else if (f.hasBlock) {
|
|
174
|
+
// REMOVE block if it was previously there but now unselected
|
|
175
|
+
spinner.start(`Removing knowledge index from ${filename}...`);
|
|
176
|
+
try {
|
|
177
|
+
removeOldBlock(filePath);
|
|
178
|
+
spinner.succeed(`${filename} knowledge index removed`);
|
|
179
|
+
removed.push(filename);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
spinner.fail(`Failed to clean ${filename}: ${error.message}`);
|
|
182
|
+
}
|
|
109
183
|
}
|
|
110
184
|
}
|
|
111
185
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
console.log(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
186
|
+
if (!inline) {
|
|
187
|
+
console.log('');
|
|
188
|
+
}
|
|
189
|
+
if (updated.length > 0 || removed.length > 0) {
|
|
190
|
+
const updatedText = updated.length > 0 ? ` Updated: ${updated.join(', ')}` : '';
|
|
191
|
+
const cleanedText = removed.length > 0 ? ` Cleaned: ${removed.join(', ')}` : '';
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log(chalk.green(`✓ sync complete!${updatedText}${cleanedText}`));
|
|
194
|
+
} else {
|
|
195
|
+
console.log(chalk.yellow('No changes made.'));
|
|
196
|
+
}
|
|
197
|
+
if (!inline) {
|
|
122
198
|
console.log('');
|
|
123
199
|
}
|
|
124
200
|
}
|