@backendkit-labs/agent-coding 0.14.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/dist/agents/AgentLoader.d.ts +33 -0
- package/dist/agents/AgentLoader.d.ts.map +1 -0
- package/dist/agents/AgentLoader.js +167 -0
- package/dist/agents/AgentLoader.js.map +1 -0
- package/dist/agents/profiles.d.ts +3 -0
- package/dist/agents/profiles.d.ts.map +1 -0
- package/dist/agents/profiles.js +121 -0
- package/dist/agents/profiles.js.map +1 -0
- package/dist/agents/prompts/architecture.d.ts +2 -0
- package/dist/agents/prompts/architecture.d.ts.map +1 -0
- package/dist/agents/prompts/architecture.js +151 -0
- package/dist/agents/prompts/architecture.js.map +1 -0
- package/dist/agents/prompts/backend.d.ts +2 -0
- package/dist/agents/prompts/backend.d.ts.map +1 -0
- package/dist/agents/prompts/backend.js +96 -0
- package/dist/agents/prompts/backend.js.map +1 -0
- package/dist/agents/prompts/coder.d.ts +2 -0
- package/dist/agents/prompts/coder.d.ts.map +1 -0
- package/dist/agents/prompts/coder.js +50 -0
- package/dist/agents/prompts/coder.js.map +1 -0
- package/dist/agents/prompts/data.d.ts +2 -0
- package/dist/agents/prompts/data.d.ts.map +1 -0
- package/dist/agents/prompts/data.js +123 -0
- package/dist/agents/prompts/data.js.map +1 -0
- package/dist/agents/prompts/frontend.d.ts +2 -0
- package/dist/agents/prompts/frontend.d.ts.map +1 -0
- package/dist/agents/prompts/frontend.js +91 -0
- package/dist/agents/prompts/frontend.js.map +1 -0
- package/dist/agents/prompts/general.d.ts +2 -0
- package/dist/agents/prompts/general.d.ts.map +1 -0
- package/dist/agents/prompts/general.js +93 -0
- package/dist/agents/prompts/general.js.map +1 -0
- package/dist/agents/prompts/infrastructure.d.ts +2 -0
- package/dist/agents/prompts/infrastructure.d.ts.map +1 -0
- package/dist/agents/prompts/infrastructure.js +145 -0
- package/dist/agents/prompts/infrastructure.js.map +1 -0
- package/dist/agents/prompts/project-manager.d.ts +2 -0
- package/dist/agents/prompts/project-manager.d.ts.map +1 -0
- package/dist/agents/prompts/project-manager.js +66 -0
- package/dist/agents/prompts/project-manager.js.map +1 -0
- package/dist/agents/prompts/qa.d.ts +2 -0
- package/dist/agents/prompts/qa.d.ts.map +1 -0
- package/dist/agents/prompts/qa.js +166 -0
- package/dist/agents/prompts/qa.js.map +1 -0
- package/dist/agents/prompts/security.d.ts +2 -0
- package/dist/agents/prompts/security.d.ts.map +1 -0
- package/dist/agents/prompts/security.js +129 -0
- package/dist/agents/prompts/security.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +27 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +167 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +340 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestration/capability-matrix.d.ts +10 -0
- package/dist/orchestration/capability-matrix.d.ts.map +1 -0
- package/dist/orchestration/capability-matrix.js +48 -0
- package/dist/orchestration/capability-matrix.js.map +1 -0
- package/dist/providers/AnthropicProvider.d.ts +20 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/providers/AnthropicProvider.js +185 -0
- package/dist/providers/AnthropicProvider.js.map +1 -0
- package/dist/providers/DeepSeekProvider.d.ts +11 -0
- package/dist/providers/DeepSeekProvider.d.ts.map +1 -0
- package/dist/providers/DeepSeekProvider.js +18 -0
- package/dist/providers/DeepSeekProvider.js.map +1 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts +22 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/dist/providers/OpenAICompatibleProvider.js +124 -0
- package/dist/providers/OpenAICompatibleProvider.js.map +1 -0
- package/dist/skills/builtins/global.d.ts +7 -0
- package/dist/skills/builtins/global.d.ts.map +1 -0
- package/dist/skills/builtins/global.js +208 -0
- package/dist/skills/builtins/global.js.map +1 -0
- package/dist/skills/builtins/go-pack.d.ts +7 -0
- package/dist/skills/builtins/go-pack.d.ts.map +1 -0
- package/dist/skills/builtins/go-pack.js +263 -0
- package/dist/skills/builtins/go-pack.js.map +1 -0
- package/dist/skills/builtins/java-pack.d.ts +7 -0
- package/dist/skills/builtins/java-pack.d.ts.map +1 -0
- package/dist/skills/builtins/java-pack.js +272 -0
- package/dist/skills/builtins/java-pack.js.map +1 -0
- package/dist/skills/builtins/kotlin-pack.d.ts +9 -0
- package/dist/skills/builtins/kotlin-pack.d.ts.map +1 -0
- package/dist/skills/builtins/kotlin-pack.js +292 -0
- package/dist/skills/builtins/kotlin-pack.js.map +1 -0
- package/dist/skills/builtins/node-pack.d.ts +7 -0
- package/dist/skills/builtins/node-pack.d.ts.map +1 -0
- package/dist/skills/builtins/node-pack.js +750 -0
- package/dist/skills/builtins/node-pack.js.map +1 -0
- package/dist/skills/builtins/python-pack.d.ts +7 -0
- package/dist/skills/builtins/python-pack.d.ts.map +1 -0
- package/dist/skills/builtins/python-pack.js +303 -0
- package/dist/skills/builtins/python-pack.js.map +1 -0
- package/dist/skills/index.d.ts +7 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +16 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/store/LearningRouter.d.ts +17 -0
- package/dist/store/LearningRouter.d.ts.map +1 -0
- package/dist/store/LearningRouter.js +165 -0
- package/dist/store/LearningRouter.js.map +1 -0
- package/dist/store/PersistentMemory.d.ts +10 -0
- package/dist/store/PersistentMemory.d.ts.map +1 -0
- package/dist/store/PersistentMemory.js +29 -0
- package/dist/store/PersistentMemory.js.map +1 -0
- package/dist/store/ProjectStore.d.ts +29 -0
- package/dist/store/ProjectStore.d.ts.map +1 -0
- package/dist/store/ProjectStore.js +191 -0
- package/dist/store/ProjectStore.js.map +1 -0
- package/dist/store/__tests__/PersistentMemory.test.d.ts +2 -0
- package/dist/store/__tests__/PersistentMemory.test.d.ts.map +1 -0
- package/dist/store/__tests__/PersistentMemory.test.js +46 -0
- package/dist/store/__tests__/PersistentMemory.test.js.map +1 -0
- package/dist/tools/__tests__/file-tools.test.d.ts +2 -0
- package/dist/tools/__tests__/file-tools.test.d.ts.map +1 -0
- package/dist/tools/__tests__/file-tools.test.js +144 -0
- package/dist/tools/__tests__/file-tools.test.js.map +1 -0
- package/dist/tools/__tests__/path-sandbox.test.d.ts +2 -0
- package/dist/tools/__tests__/path-sandbox.test.d.ts.map +1 -0
- package/dist/tools/__tests__/path-sandbox.test.js +45 -0
- package/dist/tools/__tests__/path-sandbox.test.js.map +1 -0
- package/dist/tools/__tests__/run-command.test.d.ts +2 -0
- package/dist/tools/__tests__/run-command.test.d.ts.map +1 -0
- package/dist/tools/__tests__/run-command.test.js +61 -0
- package/dist/tools/__tests__/run-command.test.js.map +1 -0
- package/dist/tools/append-log.d.ts +2 -0
- package/dist/tools/append-log.d.ts.map +1 -0
- package/dist/tools/append-log.js +3 -0
- package/dist/tools/append-log.js.map +1 -0
- package/dist/tools/edit-file.d.ts +2 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +45 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/list-directory.d.ts +2 -0
- package/dist/tools/list-directory.d.ts.map +1 -0
- package/dist/tools/list-directory.js +47 -0
- package/dist/tools/list-directory.js.map +1 -0
- package/dist/tools/path-sandbox.d.ts +31 -0
- package/dist/tools/path-sandbox.d.ts.map +1 -0
- package/dist/tools/path-sandbox.js +99 -0
- package/dist/tools/path-sandbox.js.map +1 -0
- package/dist/tools/read-file.d.ts +2 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +28 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/run-command.d.ts +2 -0
- package/dist/tools/run-command.d.ts.map +1 -0
- package/dist/tools/run-command.js +192 -0
- package/dist/tools/run-command.js.map +1 -0
- package/dist/tools/save-audit.d.ts +4 -0
- package/dist/tools/save-audit.d.ts.map +1 -0
- package/dist/tools/save-audit.js +42 -0
- package/dist/tools/save-audit.js.map +1 -0
- package/dist/tools/save-context.d.ts +2 -0
- package/dist/tools/save-context.d.ts.map +1 -0
- package/dist/tools/save-context.js +18 -0
- package/dist/tools/save-context.js.map +1 -0
- package/dist/tools/save-learning.d.ts +2 -0
- package/dist/tools/save-learning.d.ts.map +1 -0
- package/dist/tools/save-learning.js +41 -0
- package/dist/tools/save-learning.js.map +1 -0
- package/dist/tools/save-user-preference.d.ts +3 -0
- package/dist/tools/save-user-preference.d.ts.map +1 -0
- package/dist/tools/save-user-preference.js +22 -0
- package/dist/tools/save-user-preference.js.map +1 -0
- package/dist/tools/search-files.d.ts +2 -0
- package/dist/tools/search-files.d.ts.map +1 -0
- package/dist/tools/search-files.js +170 -0
- package/dist/tools/search-files.js.map +1 -0
- package/dist/tools/secret-scanner.d.ts +15 -0
- package/dist/tools/secret-scanner.d.ts.map +1 -0
- package/dist/tools/secret-scanner.js +44 -0
- package/dist/tools/secret-scanner.js.map +1 -0
- package/dist/tools/update-session.d.ts +3 -0
- package/dist/tools/update-session.d.ts.map +1 -0
- package/dist/tools/update-session.js +49 -0
- package/dist/tools/update-session.js.map +1 -0
- package/dist/tools/write-file.d.ts +2 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +32 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/workflows/InitWorkflow.d.ts +6 -0
- package/dist/workflows/InitWorkflow.d.ts.map +1 -0
- package/dist/workflows/InitWorkflow.js +448 -0
- package/dist/workflows/InitWorkflow.js.map +1 -0
- package/dist/workflows/__tests__/InitWorkflow.test.d.ts +2 -0
- package/dist/workflows/__tests__/InitWorkflow.test.d.ts.map +1 -0
- package/dist/workflows/__tests__/InitWorkflow.test.js +43 -0
- package/dist/workflows/__tests__/InitWorkflow.test.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KOTLIN_PACK_SKILLS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Kotlin / Android skill pack (@bk-kotlin).
|
|
6
|
+
* Activated for projects with build.gradle containing kotlin plugin,
|
|
7
|
+
* detected via 'kotlin' stack (same indicator as java but differentiated
|
|
8
|
+
* by triggers and stack field).
|
|
9
|
+
*/
|
|
10
|
+
exports.KOTLIN_PACK_SKILLS = [
|
|
11
|
+
{
|
|
12
|
+
name: 'kotlin-coroutines',
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
description: 'Kotlin coroutines: suspend functions, Flow, coroutine scopes and error handling',
|
|
15
|
+
scope: 'pack',
|
|
16
|
+
pack: '@bk-kotlin',
|
|
17
|
+
language: ['kotlin'],
|
|
18
|
+
triggers: [
|
|
19
|
+
'coroutine', 'coroutines', 'suspend', 'flow', 'stateflow', 'sharedflow',
|
|
20
|
+
'async', 'launch', 'withcontext', 'dispatcher', 'scope', 'job',
|
|
21
|
+
'concurrencia', 'concurrency', 'asincrono', 'asynchronous',
|
|
22
|
+
],
|
|
23
|
+
systemPromptAddition: `## Kotlin Coroutines
|
|
24
|
+
|
|
25
|
+
### Suspend functions — siempre en el scope correcto
|
|
26
|
+
\`\`\`kotlin
|
|
27
|
+
// Repository
|
|
28
|
+
suspend fun findById(id: String): User? = withContext(Dispatchers.IO) {
|
|
29
|
+
db.userDao().findById(id)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ViewModel
|
|
33
|
+
viewModelScope.launch {
|
|
34
|
+
_uiState.value = UiState.Loading
|
|
35
|
+
runCatching { repository.findById(id) }
|
|
36
|
+
.onSuccess { _uiState.value = UiState.Success(it) }
|
|
37
|
+
.onFailure { _uiState.value = UiState.Error(it.message) }
|
|
38
|
+
}
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
### Flow para streams de datos
|
|
42
|
+
\`\`\`kotlin
|
|
43
|
+
// Repository — expone Flow
|
|
44
|
+
fun observeUsers(): Flow<List<User>> = db.userDao().observeAll()
|
|
45
|
+
|
|
46
|
+
// ViewModel — convierte a StateFlow
|
|
47
|
+
val users: StateFlow<List<User>> = repository.observeUsers()
|
|
48
|
+
.stateIn(
|
|
49
|
+
scope = viewModelScope,
|
|
50
|
+
started = SharingStarted.WhileSubscribed(5_000),
|
|
51
|
+
initialValue = emptyList(),
|
|
52
|
+
)
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
### Manejo de errores en Flow
|
|
56
|
+
\`\`\`kotlin
|
|
57
|
+
repository.observeUsers()
|
|
58
|
+
.catch { emit(emptyList()) } // recupera de errores
|
|
59
|
+
.collect { users -> ... }
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
### Dispatchers
|
|
63
|
+
| Dispatcher | Uso |
|
|
64
|
+
|---|---|
|
|
65
|
+
| \`Dispatchers.Main\` | UI, actualizar estado |
|
|
66
|
+
| \`Dispatchers.IO\` | Red, disco, base de datos |
|
|
67
|
+
| \`Dispatchers.Default\` | CPU-intensivo (sort, parse) |
|
|
68
|
+
|
|
69
|
+
### Reglas
|
|
70
|
+
- Usa \`viewModelScope\` en ViewModels — se cancela automáticamente al limpiar
|
|
71
|
+
- Usa \`lifecycleScope\` en Activities/Fragments — respeta el lifecycle
|
|
72
|
+
- Nunca uses \`GlobalScope\` — no se cancela automáticamente
|
|
73
|
+
- Prefiere \`StateFlow\` sobre \`LiveData\` en código nuevo`,
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'compose-patterns',
|
|
77
|
+
version: '1.0.0',
|
|
78
|
+
description: 'Jetpack Compose: composable functions, state hoisting, side effects',
|
|
79
|
+
scope: 'pack',
|
|
80
|
+
pack: '@bk-kotlin',
|
|
81
|
+
language: ['kotlin'],
|
|
82
|
+
triggers: [
|
|
83
|
+
'compose', 'composable', 'jetpack compose', 'ui', 'pantalla', 'screen',
|
|
84
|
+
'remember', 'state', 'recomposition', 'launchedeffect', 'sideeffect',
|
|
85
|
+
'column', 'row', 'box', 'modifier', 'material', 'scaffold',
|
|
86
|
+
],
|
|
87
|
+
systemPromptAddition: `## Jetpack Compose
|
|
88
|
+
|
|
89
|
+
### State hoisting — separa lógica de presentación
|
|
90
|
+
\`\`\`kotlin
|
|
91
|
+
// Stateless (reutilizable, testeable)
|
|
92
|
+
@Composable
|
|
93
|
+
fun UserCard(user: User, onDelete: () -> Unit, modifier: Modifier = Modifier) {
|
|
94
|
+
Card(modifier = modifier) {
|
|
95
|
+
Text(user.name)
|
|
96
|
+
IconButton(onClick = onDelete) { Icon(Icons.Default.Delete, null) }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Stateful (pantalla completa, conectada al ViewModel)
|
|
101
|
+
@Composable
|
|
102
|
+
fun UserScreen(viewModel: UserViewModel = hiltViewModel()) {
|
|
103
|
+
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
|
104
|
+
|
|
105
|
+
when (val state = uiState) {
|
|
106
|
+
is UiState.Loading -> CircularProgressIndicator()
|
|
107
|
+
is UiState.Success -> UserCard(state.user, onDelete = viewModel::delete)
|
|
108
|
+
is UiState.Error -> Text("Error: \${state.message}")
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
### Side effects
|
|
114
|
+
\`\`\`kotlin
|
|
115
|
+
// LaunchedEffect — coroutine atada al lifecycle del composable
|
|
116
|
+
LaunchedEffect(userId) { // se relanza si userId cambia
|
|
117
|
+
viewModel.loadUser(userId)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// DisposableEffect — recursos que necesitan cleanup
|
|
121
|
+
DisposableEffect(Unit) {
|
|
122
|
+
val callback = registerCallback()
|
|
123
|
+
onDispose { callback.unregister() }
|
|
124
|
+
}
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
### Modifier — siempre como último parámetro con default
|
|
128
|
+
\`\`\`kotlin
|
|
129
|
+
@Composable
|
|
130
|
+
fun MyComponent(
|
|
131
|
+
title: String,
|
|
132
|
+
modifier: Modifier = Modifier, // convención de Compose
|
|
133
|
+
) { ... }
|
|
134
|
+
\`\`\`
|
|
135
|
+
|
|
136
|
+
### Reglas
|
|
137
|
+
- Funciones composable en PascalCase, sin retorno de valor
|
|
138
|
+
- Hoist el state tan arriba como sea necesario — no más
|
|
139
|
+
- Evita lógica de negocio en composables — solo UI
|
|
140
|
+
- Usa \`collectAsStateWithLifecycle()\` (no \`collectAsState()\`) para respetar el lifecycle`,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'android-architecture',
|
|
144
|
+
version: '1.0.0',
|
|
145
|
+
description: 'Android Clean Architecture: ViewModel + StateFlow + Repository pattern + Hilt',
|
|
146
|
+
scope: 'pack',
|
|
147
|
+
pack: '@bk-kotlin',
|
|
148
|
+
language: ['kotlin'],
|
|
149
|
+
triggers: [
|
|
150
|
+
'viewmodel', 'repository', 'usecase', 'use case', 'arquitectura',
|
|
151
|
+
'architecture', 'hilt', 'dependency injection', 'inyeccion', 'clean',
|
|
152
|
+
'room', 'retrofit', 'navigation', 'module',
|
|
153
|
+
],
|
|
154
|
+
systemPromptAddition: `## Android Clean Architecture
|
|
155
|
+
|
|
156
|
+
### Capas
|
|
157
|
+
\`\`\`
|
|
158
|
+
UI (Composables)
|
|
159
|
+
↓ observe StateFlow
|
|
160
|
+
ViewModel (viewModelScope)
|
|
161
|
+
↓ suspend fun / Flow
|
|
162
|
+
Repository (interface en domain, impl en data)
|
|
163
|
+
↓
|
|
164
|
+
DataSource (Room DAO / Retrofit API)
|
|
165
|
+
\`\`\`
|
|
166
|
+
|
|
167
|
+
### ViewModel con StateFlow
|
|
168
|
+
\`\`\`kotlin
|
|
169
|
+
@HiltViewModel
|
|
170
|
+
class UserViewModel @Inject constructor(
|
|
171
|
+
private val userRepository: UserRepository,
|
|
172
|
+
) : ViewModel() {
|
|
173
|
+
|
|
174
|
+
private val _uiState = MutableStateFlow<UiState<User>>(UiState.Loading)
|
|
175
|
+
val uiState: StateFlow<UiState<User>> = _uiState.asStateFlow()
|
|
176
|
+
|
|
177
|
+
fun loadUser(id: String) {
|
|
178
|
+
viewModelScope.launch {
|
|
179
|
+
_uiState.value = UiState.Loading
|
|
180
|
+
userRepository.findById(id)
|
|
181
|
+
.onSuccess { _uiState.value = UiState.Success(it) }
|
|
182
|
+
.onFailure { _uiState.value = UiState.Error(it.message ?: "Unknown error") }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
sealed class UiState<out T> {
|
|
188
|
+
data object Loading : UiState<Nothing>()
|
|
189
|
+
data class Success<T>(val data: T) : UiState<T>()
|
|
190
|
+
data class Error(val message: String) : UiState<Nothing>()
|
|
191
|
+
}
|
|
192
|
+
\`\`\`
|
|
193
|
+
|
|
194
|
+
### Repository
|
|
195
|
+
\`\`\`kotlin
|
|
196
|
+
// Interface en domain (sin dependencias Android)
|
|
197
|
+
interface UserRepository {
|
|
198
|
+
suspend fun findById(id: String): Result<User>
|
|
199
|
+
fun observeAll(): Flow<List<User>>
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Implementación en data
|
|
203
|
+
class UserRepositoryImpl @Inject constructor(
|
|
204
|
+
private val dao: UserDao,
|
|
205
|
+
private val api: UserApi,
|
|
206
|
+
) : UserRepository {
|
|
207
|
+
override suspend fun findById(id: String): Result<User> = runCatching {
|
|
208
|
+
dao.findById(id) ?: api.getUser(id).also { dao.insert(it) }
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
\`\`\`
|
|
212
|
+
|
|
213
|
+
### Hilt modules
|
|
214
|
+
\`\`\`kotlin
|
|
215
|
+
@Module
|
|
216
|
+
@InstallIn(SingletonComponent::class)
|
|
217
|
+
abstract class RepositoryModule {
|
|
218
|
+
@Binds @Singleton
|
|
219
|
+
abstract fun bindUserRepo(impl: UserRepositoryImpl): UserRepository
|
|
220
|
+
}
|
|
221
|
+
\`\`\`
|
|
222
|
+
|
|
223
|
+
### Reglas
|
|
224
|
+
- ViewModels no importan clases Android (Context, Activity) — solo lógica
|
|
225
|
+
- Repository oculta la fuente de datos (Room vs API) — el ViewModel no sabe de dónde vienen los datos
|
|
226
|
+
- Usa \`Result<T>\` para operaciones que pueden fallar
|
|
227
|
+
- Room: NUNCA accedas a la base de datos desde el main thread`,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: 'kotlin-testing',
|
|
231
|
+
version: '1.0.0',
|
|
232
|
+
description: 'Kotlin testing: JUnit 5, MockK, Turbine for Flow, coroutine test utilities',
|
|
233
|
+
scope: 'pack',
|
|
234
|
+
pack: '@bk-kotlin',
|
|
235
|
+
language: ['kotlin'],
|
|
236
|
+
triggers: [
|
|
237
|
+
'test', 'tests', 'testing', 'prueba', 'mockk', 'mock', 'turbine',
|
|
238
|
+
'coroutinetest', 'junit', 'coevery', 'coassert', 'coverage',
|
|
239
|
+
],
|
|
240
|
+
systemPromptAddition: `## Kotlin Testing
|
|
241
|
+
|
|
242
|
+
### Test de ViewModel con Turbine (Flow)
|
|
243
|
+
\`\`\`kotlin
|
|
244
|
+
@OptIn(ExperimentalCoroutinesApi::class)
|
|
245
|
+
class UserViewModelTest {
|
|
246
|
+
@get:Rule val mainRule = MainCoroutineRule() // reemplaza Dispatchers.Main
|
|
247
|
+
|
|
248
|
+
private val repository: UserRepository = mockk()
|
|
249
|
+
private lateinit var viewModel: UserViewModel
|
|
250
|
+
|
|
251
|
+
@BeforeEach fun setup() { viewModel = UserViewModel(repository) }
|
|
252
|
+
|
|
253
|
+
@Test fun \`loadUser emits Success when repository returns user\`() = runTest {
|
|
254
|
+
val user = User("1", "ana@example.com")
|
|
255
|
+
coEvery { repository.findById("1") } returns Result.success(user)
|
|
256
|
+
|
|
257
|
+
viewModel.uiState.test {
|
|
258
|
+
viewModel.loadUser("1")
|
|
259
|
+
assertThat(awaitItem()).isInstanceOf(UiState.Loading::class.java)
|
|
260
|
+
assertThat(awaitItem()).isEqualTo(UiState.Success(user))
|
|
261
|
+
cancelAndIgnoreRemainingEvents()
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
\`\`\`
|
|
266
|
+
|
|
267
|
+
### MainCoroutineRule (para tests con Dispatchers.Main)
|
|
268
|
+
\`\`\`kotlin
|
|
269
|
+
class MainCoroutineRule : TestWatcher() {
|
|
270
|
+
val testDispatcher = UnconfinedTestDispatcher()
|
|
271
|
+
override fun starting(d: Description) { Dispatchers.setMain(testDispatcher) }
|
|
272
|
+
override fun finished(d: Description) { Dispatchers.resetMain() }
|
|
273
|
+
}
|
|
274
|
+
\`\`\`
|
|
275
|
+
|
|
276
|
+
### Mock con MockK
|
|
277
|
+
\`\`\`kotlin
|
|
278
|
+
val repo: UserRepository = mockk()
|
|
279
|
+
coEvery { repo.findById(any()) } returns Result.success(user) // suspend fun
|
|
280
|
+
every { repo.observeAll() } returns flowOf(listOf(user)) // Flow
|
|
281
|
+
|
|
282
|
+
coVerify { repo.findById("1") }
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
### Reglas
|
|
286
|
+
- Usa \`runTest\` para tests de coroutines — maneja automáticamente los dispatchers de test
|
|
287
|
+
- Usa Turbine para testear Flow (\`flow.test { ... }\`)
|
|
288
|
+
- Usa MockK (no Mockito) para mocks en Kotlin — soporte nativo de suspend/coroutines
|
|
289
|
+
- Nombra los tests con backticks: \`\`fun \`loads user when id is valid\`()\`\``,
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
//# sourceMappingURL=kotlin-pack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kotlin-pack.js","sourceRoot":"","sources":["../../../src/skills/builtins/kotlin-pack.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACU,QAAA,kBAAkB,GAAY;IACvC;QACI,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,iFAAiF;QAC9F,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE;YACN,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY;YACvE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK;YAC9D,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc;SAC7D;QACD,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6DAkD+B;KACxD;IACD;QACI,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,qEAAqE;QAClF,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE;YACN,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ;YACtE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY;YACpE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;SAC7D;QACD,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6FAqD+D;KACxF;IACD;QACI,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,+EAA+E;QAC5F,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE;YACN,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc;YAChE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,WAAW,EAAE,OAAO;YACpE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ;SAC7C;QACD,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAyEgC;KACzD;IACD;QACI,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,4EAA4E;QACzF,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE;YACN,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;YAChE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU;SAC9D;QACD,oBAAoB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAiDkD;KAC3E;CACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Skill } from '@backendkit-labs/agent-core';
|
|
2
|
+
/**
|
|
3
|
+
* Node.js / TypeScript skill pack (@bk-node).
|
|
4
|
+
* Only activated for projects with package.json or tsconfig.json.
|
|
5
|
+
*/
|
|
6
|
+
export declare const NODE_PACK_SKILLS: Skill[];
|
|
7
|
+
//# sourceMappingURL=node-pack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-pack.d.ts","sourceRoot":"","sources":["../../../src/skills/builtins/node-pack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,EAquBnC,CAAC"}
|