androjack-mcp 1.3.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.
Files changed (70) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
  3. package/.github/pull_request_template.md +16 -0
  4. package/CONTRIBUTING.md +27 -0
  5. package/LICENSE +21 -0
  6. package/README.md +592 -0
  7. package/SECURITY.md +26 -0
  8. package/assets/AndroJack banner.png +0 -0
  9. package/assets/killer_argument.png +0 -0
  10. package/build/constants.js +412 -0
  11. package/build/http-server.js +163 -0
  12. package/build/http.js +151 -0
  13. package/build/index.js +553 -0
  14. package/build/install.js +379 -0
  15. package/build/logger.js +57 -0
  16. package/build/tools/api-level.js +170 -0
  17. package/build/tools/api36-compliance.js +282 -0
  18. package/build/tools/architecture.js +75 -0
  19. package/build/tools/build-publish.js +362 -0
  20. package/build/tools/component.js +90 -0
  21. package/build/tools/debugger.js +82 -0
  22. package/build/tools/gradle.js +234 -0
  23. package/build/tools/kmp.js +348 -0
  24. package/build/tools/kotlin-patterns.js +500 -0
  25. package/build/tools/large-screen.js +366 -0
  26. package/build/tools/m3-expressive.js +447 -0
  27. package/build/tools/navigation3.js +331 -0
  28. package/build/tools/ondevice-ai.js +283 -0
  29. package/build/tools/permissions.js +404 -0
  30. package/build/tools/play-policy.js +221 -0
  31. package/build/tools/scalability.js +621 -0
  32. package/build/tools/search.js +89 -0
  33. package/build/tools/testing.js +439 -0
  34. package/build/tools/wear.js +337 -0
  35. package/build/tools/xr.js +274 -0
  36. package/config/antigravity_mcp.json +32 -0
  37. package/config/claude_desktop_config.json +17 -0
  38. package/config/cursor_mcp.json +21 -0
  39. package/config/jetbrains_mcp.json +28 -0
  40. package/config/kiro_mcp.json +40 -0
  41. package/config/vscode_mcp.json +24 -0
  42. package/config/windsurf_mcp.json +18 -0
  43. package/package.json +51 -0
  44. package/src/constants.ts +436 -0
  45. package/src/http-server.ts +186 -0
  46. package/src/http.ts +190 -0
  47. package/src/index.ts +702 -0
  48. package/src/install.ts +441 -0
  49. package/src/logger.ts +67 -0
  50. package/src/tools/api-level.ts +198 -0
  51. package/src/tools/api36-compliance.ts +289 -0
  52. package/src/tools/architecture.ts +94 -0
  53. package/src/tools/build-publish.ts +379 -0
  54. package/src/tools/component.ts +106 -0
  55. package/src/tools/debugger.ts +111 -0
  56. package/src/tools/gradle.ts +288 -0
  57. package/src/tools/kmp.ts +352 -0
  58. package/src/tools/kotlin-patterns.ts +534 -0
  59. package/src/tools/large-screen.ts +391 -0
  60. package/src/tools/m3-expressive.ts +473 -0
  61. package/src/tools/navigation3.ts +338 -0
  62. package/src/tools/ondevice-ai.ts +287 -0
  63. package/src/tools/permissions.ts +445 -0
  64. package/src/tools/play-policy.ts +229 -0
  65. package/src/tools/scalability.ts +646 -0
  66. package/src/tools/search.ts +112 -0
  67. package/src/tools/testing.ts +460 -0
  68. package/src/tools/wear.ts +343 -0
  69. package/src/tools/xr.ts +278 -0
  70. package/tsconfig.json +17 -0
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Tool 6 – android_api_level_check
3
+ *
4
+ * Maps API levels to version names, SDK integers, and market share.
5
+ * Prevents writing code that uses APIs unavailable at the project's minSdk.
6
+ * Zero network required — all data is embedded (fast + reliable).
7
+ */
8
+
9
+ interface ApiLevelEntry {
10
+ versionName: string;
11
+ codename: string;
12
+ apiLevel: number;
13
+ releasedYear: number;
14
+ marketShareApprox?: string; // sourced from Android Studio distribution data
15
+ notableFeatures: string[];
16
+ }
17
+
18
+ // Source: https://developer.android.com/tools/releases/platforms
19
+ // Updated through API 36 (Android 16, 2025)
20
+ const API_LEVELS: ApiLevelEntry[] = [
21
+ {
22
+ versionName: "Android 16",
23
+ codename: "Baklava",
24
+ apiLevel: 36,
25
+ releasedYear: 2025,
26
+ notableFeatures: ["Predictive back gesture stable", "Health Connect updates", "Large screen optimizations"],
27
+ },
28
+ {
29
+ versionName: "Android 15",
30
+ codename: "VanillaIceCream",
31
+ apiLevel: 35,
32
+ releasedYear: 2024,
33
+ notableFeatures: ["Edge-to-edge enforcement", "NFC improvements", "Partial screen sharing"],
34
+ },
35
+ {
36
+ versionName: "Android 14",
37
+ codename: "UpsideDownCake",
38
+ apiLevel: 34,
39
+ releasedYear: 2023,
40
+ marketShareApprox: "~35%",
41
+ notableFeatures: ["Health Connect", "Photo picker", "Credential Manager"],
42
+ },
43
+ {
44
+ versionName: "Android 13",
45
+ codename: "Tiramisu",
46
+ apiLevel: 33,
47
+ releasedYear: 2022,
48
+ marketShareApprox: "~20%",
49
+ notableFeatures: ["Per-app language prefs", "Themed app icons", "Media permissions"],
50
+ },
51
+ {
52
+ versionName: "Android 12",
53
+ codename: "SnowCone",
54
+ apiLevel: 31,
55
+ releasedYear: 2021,
56
+ marketShareApprox: "~15%",
57
+ notableFeatures: ["Material You", "Splash screen API", "App hibernation"],
58
+ },
59
+ {
60
+ versionName: "Android 11",
61
+ codename: "RedVelvetCake",
62
+ apiLevel: 30,
63
+ releasedYear: 2020,
64
+ marketShareApprox: "~10%",
65
+ notableFeatures: ["One-time permissions", "Scoped storage enforced", "AsyncTask deprecated"],
66
+ },
67
+ {
68
+ versionName: "Android 10",
69
+ codename: "QuinceTart",
70
+ apiLevel: 29,
71
+ releasedYear: 2019,
72
+ marketShareApprox: "~8%",
73
+ notableFeatures: ["Dark theme", "Scoped storage", "Gesture navigation"],
74
+ },
75
+ {
76
+ versionName: "Android 9",
77
+ codename: "Pie",
78
+ apiLevel: 28,
79
+ releasedYear: 2018,
80
+ notableFeatures: ["Wi-Fi RTT", "Display cutout support", "Neural Networks API 1.1"],
81
+ },
82
+ {
83
+ versionName: "Android 8.0",
84
+ codename: "Oreo",
85
+ apiLevel: 26,
86
+ releasedYear: 2017,
87
+ notableFeatures: ["Notification channels (REQUIRED)", "Picture-in-picture", "Autofill"],
88
+ },
89
+ {
90
+ versionName: "Android 7.0",
91
+ codename: "Nougat",
92
+ apiLevel: 24,
93
+ releasedYear: 2016,
94
+ notableFeatures: ["Multi-window", "Direct reply notifications", "Doze improvements"],
95
+ },
96
+ {
97
+ versionName: "Android 6.0",
98
+ codename: "Marshmallow",
99
+ apiLevel: 23,
100
+ releasedYear: 2015,
101
+ notableFeatures: ["Runtime permissions (REQUIRED)", "Fingerprint API", "Doze mode"],
102
+ },
103
+ {
104
+ versionName: "Android 5.0",
105
+ codename: "Lollipop",
106
+ apiLevel: 21,
107
+ releasedYear: 2014,
108
+ notableFeatures: ["Material Design", "ART runtime default", "Vector drawables"],
109
+ },
110
+ ];
111
+
112
+ function findByApiLevel(level: number): ApiLevelEntry | undefined {
113
+ return API_LEVELS.find((e) => e.apiLevel === level);
114
+ }
115
+
116
+ function findByName(name: string): ApiLevelEntry | undefined {
117
+ const lower = name.toLowerCase();
118
+ return API_LEVELS.find(
119
+ (e) =>
120
+ e.versionName.toLowerCase().includes(lower) ||
121
+ e.codename.toLowerCase().includes(lower)
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Checks what APIs are available at a given minSdk level and warns about
127
+ * common pitfalls.
128
+ */
129
+ function getMinSdkWarnings(minSdk: number): string[] {
130
+ const warnings: string[] = [];
131
+
132
+ if (minSdk < 26) warnings.push("⚠️ API < 26: Notification channels not available (required for foreground services on Android 8+)");
133
+ if (minSdk < 23) warnings.push("⚠️ API < 23: Runtime permissions not available — you must handle permission dialogs manually");
134
+ if (minSdk < 21) warnings.push("⚠️ API < 21: Material Design components and VectorDrawable support limited");
135
+ if (minSdk >= 21) warnings.push("✅ API 21+: Jetpack Compose minimum supported");
136
+ if (minSdk >= 23) warnings.push("✅ API 23+: Safe to use runtime permissions API directly");
137
+ if (minSdk >= 26) warnings.push("✅ API 26+: Notification channels required and available");
138
+
139
+ return warnings;
140
+ }
141
+
142
+ /**
143
+ * Core handler for android_api_level_check tool.
144
+ */
145
+ export function androidApiLevelCheck(input: string): string {
146
+ const trimmed = input.trim();
147
+
148
+ // Numeric API level input
149
+ const numeric = parseInt(trimmed, 10);
150
+ if (!isNaN(numeric)) {
151
+ const entry = findByApiLevel(numeric);
152
+ if (!entry) {
153
+ const closest = API_LEVELS.reduce((prev, curr) =>
154
+ Math.abs(curr.apiLevel - numeric) < Math.abs(prev.apiLevel - numeric) ? curr : prev
155
+ );
156
+ return (
157
+ `## AndroJack API Level Check\n**Input:** API ${numeric}\n\n` +
158
+ `❓ API level ${numeric} not in local registry.\n` +
159
+ `Closest known: **${closest.versionName} (API ${closest.apiLevel})**\n\n` +
160
+ `Check: https://developer.android.com/tools/releases/platforms`
161
+ );
162
+ }
163
+
164
+ const warnings = getMinSdkWarnings(numeric);
165
+ return (
166
+ `## AndroJack API Level Check\n\n` +
167
+ `| Field | Value |\n|---|---|\n` +
168
+ `| Version | ${entry.versionName} |\n` +
169
+ `| Codename | ${entry.codename} |\n` +
170
+ `| API Level | ${entry.apiLevel} |\n` +
171
+ `| Released | ${entry.releasedYear} |\n` +
172
+ (entry.marketShareApprox ? `| Market Share | ${entry.marketShareApprox} |\n` : "") +
173
+ `\n**Notable Features:**\n${entry.notableFeatures.map((f) => `- ${f}`).join("\n")}\n\n` +
174
+ `**minSdk Guidance:**\n${warnings.join("\n")}\n\n` +
175
+ `**Official Reference:** https://developer.android.com/tools/releases/platforms\n\n` +
176
+ `> ℹ️ Use \`compileSdk ${Math.max(entry.apiLevel, 35)}\` and set \`minSdk\` based on your audience.`
177
+ );
178
+ }
179
+
180
+ // Text input (version name or codename)
181
+ const entry = findByName(trimmed);
182
+ if (entry) {
183
+ return androidApiLevelCheck(String(entry.apiLevel));
184
+ }
185
+
186
+ // Full table fallback
187
+ const table =
188
+ `## Android API Level Reference\n\n` +
189
+ `| Version | Codename | API | Year | Market Share |\n|---|---|---|---|---|\n` +
190
+ API_LEVELS.map(
191
+ (e) =>
192
+ `| ${e.versionName} | ${e.codename} | ${e.apiLevel} | ${e.releasedYear} | ${e.marketShareApprox ?? "—"} |`
193
+ ).join("\n") +
194
+ `\n\n**Recommended minSdk for new apps:** API 26+ (covers ~90%+ of active devices)\n` +
195
+ `**Official Reference:** https://developer.android.com/tools/releases/platforms`;
196
+
197
+ return table;
198
+ }
@@ -0,0 +1,289 @@
1
+ // Tool 15: Android 16 / API 36 Compliance Checker
2
+ // Google Play mandate: all apps must target API 36 by August 2026.
3
+ // Android 16 removed the ability to lock orientation or restrict resizability on ≥600dp devices.
4
+
5
+ export async function androidApi36Compliance(topic: string): Promise<string> {
6
+ const t = topic.toLowerCase().trim();
7
+
8
+ const overview = `
9
+ # Android 16 / API 36 Compliance Reference
10
+ Source: https://developer.android.com/about/versions/16/behavior-changes-all
11
+
12
+ ## The Mandate
13
+
14
+ Google Play requires all apps to **target API 36 by August 2026**.
15
+ Android 16 (API 36) introduced breaking changes for large-screen device behavior.
16
+ Apps that fail compliance checks will receive warning badges in Play Store listings
17
+ and may be demoted in search results.
18
+
19
+ ## What Changed in Android 16 — The Breaking Rules
20
+
21
+ ### 1. Mandatory Resizability on Large Screens (≥600dp)
22
+ On devices with width ≥600dp (tablets, foldables, ChromeOS), apps can NO LONGER:
23
+ - Lock screen orientation
24
+ - Restrict aspect ratio
25
+ - Disable multi-window/resizability
26
+
27
+ The platform **overrides** these flags on ≥600dp devices. Apps must handle any aspect ratio.
28
+
29
+ ### 2. Predictive Back — Required for API 36 Targets
30
+ Apps targeting API 36 must implement Predictive Back Gesture.
31
+ The legacy \`OnBackPressedCallback\` alone is insufficient — use \`BackHandler\` in Compose
32
+ or the \`OnBackPressedDispatcher\` with \`createOnBackPressedCallback { }\`.
33
+
34
+ ### 3. 16 KB Page Size — Native Code
35
+ Apps with native (NDK/JNI) libraries must be compiled for 16 KB memory page alignment.
36
+ Android Studio shows a lint warning for non-compliant APKs. Failure = crash on affected hardware.
37
+
38
+ ## ❌ Manifest Flags That Now FAIL on Large Screens
39
+
40
+ \`\`\`xml
41
+ <!-- ❌ ILLEGAL on ≥600dp devices in Android 16 -->
42
+ <activity
43
+ android:screenOrientation="portrait"
44
+ android:screenOrientation="landscape"
45
+ android:screenOrientation="sensorPortrait"
46
+ android:resizeableActivity="false"
47
+ android:maxAspectRatio="1.86" <!-- Restricts to phone ratio — illegal on large screens -->
48
+ />
49
+ \`\`\`
50
+
51
+ ## ✅ Correct Manifest for API 36 Compliance
52
+
53
+ \`\`\`xml
54
+ <activity
55
+ android:name=".MainActivity"
56
+ android:exported="true"
57
+ android:windowSoftInputMode="adjustResize"
58
+ <!-- NO screenOrientation — let the system decide -->
59
+ <!-- NO resizeableActivity="false" -->
60
+ <!-- NO maxAspectRatio restriction -->
61
+ >
62
+ \`\`\`
63
+
64
+ ## Games Exception
65
+
66
+ Games are exempt from the mandatory resizability requirement if declared:
67
+ \`\`\`xml
68
+ <application android:appCategory="game">
69
+ \`\`\`
70
+ Users can also opt individual apps into their preferred behavior via device settings.
71
+
72
+ Source: https://developer.android.com/about/versions/16/behavior-changes-all#large-screen
73
+ `;
74
+
75
+ const layouts = `
76
+ # Android 16 — Canonical Adaptive Layout Patterns
77
+ Source: https://developer.android.com/guide/topics/large-screens/support-different-screen-sizes
78
+
79
+ ## The Four Canonical Layouts (Google's Reference Implementations)
80
+
81
+ ### 1. List-Detail (Gmail, Messages)
82
+ \`\`\`kotlin
83
+ // Use Navigation 3 + Scenes API for List-Detail
84
+ // Or use ListDetailPaneScaffold from Material3 Adaptive
85
+ implementation("androidx.compose.material3.adaptive:adaptive:1.1.0")
86
+ implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.1.0")
87
+
88
+ @Composable
89
+ fun MailApp() {
90
+ val navigator = rememberListDetailPaneScaffoldNavigator<String>()
91
+ ListDetailPaneScaffold(
92
+ directive = navigator.scaffoldDirective,
93
+ value = navigator.scaffoldValue,
94
+ listPane = {
95
+ InboxPane(onEmailClick = { id ->
96
+ navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, id)
97
+ })
98
+ },
99
+ detailPane = {
100
+ val emailId = navigator.currentDestination?.content
101
+ if (emailId != null) EmailDetailPane(emailId)
102
+ else EmptyDetailPane()
103
+ }
104
+ )
105
+ }
106
+ \`\`\`
107
+
108
+ ### 2. Feed (Photos, Play Store)
109
+ \`\`\`kotlin
110
+ // Adaptive grid — columns based on WindowWidthSizeClass
111
+ @Composable
112
+ fun AdaptiveFeed(items: List<Item>) {
113
+ val windowInfo = currentWindowAdaptiveInfo()
114
+ val columns = when (windowInfo.windowSizeClass.windowWidthSizeClass) {
115
+ WindowWidthSizeClass.COMPACT -> 1
116
+ WindowWidthSizeClass.MEDIUM -> 2
117
+ WindowWidthSizeClass.EXPANDED -> 3
118
+ else -> 1
119
+ }
120
+ LazyVerticalGrid(columns = GridCells.Fixed(columns)) {
121
+ items(items) { item -> FeedCard(item) }
122
+ }
123
+ }
124
+ \`\`\`
125
+
126
+ ### 3. Supporting Pane (Docs, Sheets)
127
+ \`\`\`kotlin
128
+ // Primary content + persistent tool panel on large screens
129
+ // SupportingPaneScaffold from Material3 Adaptive
130
+ @Composable
131
+ fun DocumentEditor() {
132
+ val navigator = rememberSupportingPaneScaffoldNavigator()
133
+ SupportingPaneScaffold(
134
+ directive = navigator.scaffoldDirective,
135
+ value = navigator.scaffoldValue,
136
+ mainPane = { DocumentContent() },
137
+ supportingPane = { FormattingPanel() }
138
+ )
139
+ }
140
+ \`\`\`
141
+
142
+ ### 4. Navigation Suite Scaffold (automatic chrome switching)
143
+ \`\`\`kotlin
144
+ // Single API — auto-switches BottomBar → Rail → Drawer based on window size
145
+ @Composable
146
+ fun AppWithAdaptiveNav(content: @Composable () -> Unit) {
147
+ NavigationSuiteScaffold(
148
+ navigationSuiteItems = {
149
+ AppDestination.entries.forEach { destination ->
150
+ item(
151
+ icon = { Icon(destination.icon, contentDescription = destination.label) },
152
+ label = { Text(destination.label) },
153
+ selected = currentDestination == destination,
154
+ onClick = { /* navigate */ }
155
+ )
156
+ }
157
+ }
158
+ ) {
159
+ content()
160
+ }
161
+ }
162
+ \`\`\`
163
+
164
+ Source: https://developer.android.com/guide/topics/large-screens/canonical-app-layouts
165
+ `;
166
+
167
+ const checklist = `
168
+ # Android 16 Compliance Checklist — Play Store Large-Screen Quality Tiers
169
+ Source: https://developer.android.com/docs/quality-guidelines/large-screen-app-quality
170
+
171
+ ## Tier 3: Large Screen Ready (Minimum — required to avoid warning badge)
172
+ - [ ] No fixed orientation locks (no \`screenOrientation\` in manifest)
173
+ - [ ] No \`resizeableActivity="false"\`
174
+ - [ ] No hardcoded aspect ratio restrictions (\`maxAspectRatio\`)
175
+ - [ ] App does not crash or lose data on configuration change (rotation, resize)
176
+ - [ ] Keyboard/mouse basic support (for ChromeOS)
177
+ - [ ] Multi-window does not break app functionality
178
+
179
+ ## Tier 2: Large Screen Optimized
180
+ Everything in Tier 3, plus:
181
+ - [ ] Adaptive layouts using WindowSizeClass breakpoints
182
+ - [ ] NavigationSuiteScaffold (auto-switches nav chrome by window size)
183
+ - [ ] No content clipped or unreachable in landscape/large screen
184
+ - [ ] Proper inset handling (\`WindowInsets\`, \`safeDrawing\`, \`imePadding\`)
185
+
186
+ ## Tier 1: Large Screen Differentiated (Editors' Choice eligible)
187
+ Everything in Tier 2, plus:
188
+ - [ ] Multi-pane layout using ListDetailPaneScaffold or Nav3 Scenes
189
+ - [ ] Foldable hinge awareness (FoldingFeature API)
190
+ - [ ] Drag-and-drop support between panes
191
+ - [ ] App-level keyboard shortcuts
192
+ - [ ] Contextual menus on right-click
193
+
194
+ ## Critical Code Patterns for Compliance
195
+
196
+ ### Configuration Change Survival
197
+ \`\`\`kotlin
198
+ // ViewModel automatically survives rotation — use it
199
+ class MyViewModel : ViewModel() {
200
+ val uiState: StateFlow<MyUiState> = ...
201
+ }
202
+
203
+ // For non-ViewModel state, use rememberSaveable
204
+ var selectedId by rememberSaveable { mutableStateOf<String?>(null) }
205
+ \`\`\`
206
+
207
+ ### Inset Handling (Required — no content behind nav bars)
208
+ \`\`\`kotlin
209
+ Scaffold(
210
+ modifier = Modifier.fillMaxSize()
211
+ ) { paddingValues ->
212
+ LazyColumn(
213
+ contentPadding = paddingValues, // ALWAYS pass scaffold padding
214
+ modifier = Modifier.imePadding() // keyboard avoidance
215
+ ) { ... }
216
+ }
217
+ \`\`\`
218
+
219
+ ### WindowSizeClass — The Correct Import (not the deprecated one)
220
+ \`\`\`kotlin
221
+ // ✅ Correct — currentWindowAdaptiveInfo() from WindowManager
222
+ val adaptiveInfo = currentWindowAdaptiveInfo()
223
+ val widthClass = adaptiveInfo.windowSizeClass.windowWidthSizeClass
224
+
225
+ // ❌ Deprecated — calculateWindowSizeClass(activity) is the old API
226
+ \`\`\`
227
+
228
+ Source: https://developer.android.com/docs/quality-guidelines/large-screen-app-quality
229
+ `;
230
+
231
+ const predictiveBack = `
232
+ # Android 16 — Predictive Back Gesture (Required for API 36)
233
+ Source: https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture
234
+
235
+ ## What Changed
236
+
237
+ Predictive Back is mandatory for apps targeting API 36. The system now previews
238
+ the "behind" screen during a back swipe before the user completes it.
239
+
240
+ ## Implementation in Compose
241
+
242
+ \`\`\`kotlin
243
+ // In AndroidManifest.xml — opt in (required for API 33-35, automatic for API 36)
244
+ <application android:enableOnBackInvokedCallback="true">
245
+
246
+ // In Compose — BackHandler handles predictive back correctly
247
+ @Composable
248
+ fun ScreenWithCustomBack(onBack: () -> Unit) {
249
+ BackHandler(enabled = true) {
250
+ // Custom back logic — e.g., close drawer before popping screen
251
+ onBack()
252
+ }
253
+ }
254
+ \`\`\`
255
+
256
+ ## Predictive Back for Multi-Step Flows
257
+ \`\`\`kotlin
258
+ @Composable
259
+ fun MultiStepForm(currentStep: Int, onStepBack: () -> Unit, onExit: () -> Unit) {
260
+ BackHandler(enabled = currentStep > 0) {
261
+ onStepBack() // Go to previous step, not previous screen
262
+ }
263
+ // When currentStep == 0, BackHandler is disabled → system handles back → pops screen
264
+ }
265
+ \`\`\`
266
+
267
+ ## Navigation 3 — Predictive Back is Automatic
268
+ When using Navigation 3 (rememberNavBackStack + NavDisplay), predictive back works
269
+ out of the box — NavDisplay registers a BackHandler that removes the last entry.
270
+ No extra setup required.
271
+
272
+ Source: https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture
273
+ `;
274
+
275
+ if (t.includes("layout") || t.includes("pane") || t.includes("adaptive") || t.includes("canonical")) {
276
+ return layouts;
277
+ }
278
+ if (t.includes("checklist") || t.includes("quality") || t.includes("tier") || t.includes("play store")) {
279
+ return checklist;
280
+ }
281
+ if (t.includes("back") || t.includes("predictive")) {
282
+ return predictiveBack;
283
+ }
284
+
285
+ return overview + "\n\n---\n\n" +
286
+ "**Query topics:** 'layouts' (canonical adaptive patterns), 'checklist' (Play Store quality tiers), " +
287
+ "'predictive back' (API 36 back gesture requirement), 'page size' (16 KB native alignment)\n\n" +
288
+ "Source: https://developer.android.com/about/versions/16";
289
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Tool 3 – architecture_reference
3
+ *
4
+ * Retrieves official Android architecture guide content for a given topic.
5
+ * The AI MUST call this before suggesting project structure, patterns,
6
+ * or Jetpack component relationships.
7
+ */
8
+
9
+ import { ARCHITECTURE_GUIDES } from "../constants.js";
10
+ import { secureFetch, extractPageText } from "../http.js";
11
+
12
+ function findGuideUrl(topic: string): string | null {
13
+ const lower = topic.toLowerCase().trim();
14
+
15
+ // Exact key match
16
+ if (ARCHITECTURE_GUIDES[lower]) return ARCHITECTURE_GUIDES[lower];
17
+
18
+ // Partial key match
19
+ for (const [key, url] of Object.entries(ARCHITECTURE_GUIDES)) {
20
+ if (lower.includes(key) || key.includes(lower)) return url;
21
+ }
22
+
23
+ return null;
24
+ }
25
+
26
+ /**
27
+ * Core handler for architecture_reference tool.
28
+ */
29
+ export async function architectureReference(topic: string): Promise<string> {
30
+ if (!topic || topic.trim().length < 2) {
31
+ return "ERROR: Topic must be at least 2 characters.";
32
+ }
33
+
34
+ const sanitized = topic.trim().slice(0, 200);
35
+ const guideUrl = findGuideUrl(sanitized);
36
+
37
+ const header =
38
+ `## AndroJack Architecture Reference\n` +
39
+ `**Topic:** "${sanitized}"\n\n`;
40
+
41
+ if (!guideUrl) {
42
+ // Fallback: search developer.android.com
43
+ const searchUrl = `https://developer.android.com/s/results?q=${encodeURIComponent(sanitized)}`;
44
+ try {
45
+ const html = await secureFetch(searchUrl);
46
+ const text = extractPageText(html, 2500);
47
+ return (
48
+ header +
49
+ `**No direct guide mapped. Showing search results from developer.android.com:**\n` +
50
+ `**URL:** ${searchUrl}\n\n` +
51
+ text +
52
+ `\n\n> 📐 GROUNDING GATE: Review the architecture guide above before proposing any structure.`
53
+ );
54
+ } catch (err) {
55
+ return (
56
+ header +
57
+ `Could not fetch guide. Search manually: ${searchUrl}\n` +
58
+ `Error: ${err instanceof Error ? err.message : String(err)}`
59
+ );
60
+ }
61
+ }
62
+
63
+ try {
64
+ const html = await secureFetch(guideUrl);
65
+ const text = extractPageText(html, 3000);
66
+
67
+ return (
68
+ header +
69
+ `**Official Guide:** ${guideUrl}\n\n` +
70
+ text +
71
+ `\n\n---\n` +
72
+ `> 📐 GROUNDING GATE: Architecture code must align with the official guide above.`
73
+ );
74
+ } catch (err) {
75
+ return (
76
+ header +
77
+ `**Official Guide:** ${guideUrl}\n` +
78
+ `**Fetch failed:** ${err instanceof Error ? err.message : String(err)}\n\n` +
79
+ `Please open the guide manually: ${guideUrl}`
80
+ );
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Returns the full list of supported architecture topics for discovery.
86
+ */
87
+ export function listArchitectureTopics(): string {
88
+ const topics = Object.keys(ARCHITECTURE_GUIDES).sort();
89
+ return (
90
+ `## Supported Architecture Topics\n\n` +
91
+ topics.map((t) => `- \`${t}\``).join("\n") +
92
+ `\n\nPass any of these to \`architecture_reference\` for official guide content.`
93
+ );
94
+ }