Token导航 LogoToken导航TokenDH.com
开发敏感数据github未标认证来源可访问许可证需确认审计通过

kmp-networkingKMP 网络

Agent Skill

kmp-networking 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

380

周安装

16

GitHub Stars

42

下载量

133
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:kmp-networking(KMP 网络)
来源仓库:https://github.com/ahmed3elshaer/everything-claude-code-mobile
仓库路径:skills/kmp-networking
安装命令:
npx skills add https://github.com/ahmed3elshaer/everything-claude-code-mobile --skill kmp-networking
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ahmed3elshaer/everything-claude-code-mobile --skill kmp-networking

简介

kmp-networking 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中围绕仓库状态、代码变更或协作事项进行整理。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装,需结合原始 README 确认具体用法。
  • 安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写操作。
  • 注意该技能当前无底部简介,功能以实际仓库内容为准。

SKILL.md

KMP Networking with Ktor

Configure Ktor client for cross-platform networking with platform-optimized engines.

Dependencies

// build.gradle.kts (shared module)
plugins {
    kotlin("multiplatform")
    kotlin("plugin.serialization")
}

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:2.3.7")
                implementation("io.ktor:ktor-client-content-negotiation:2.3.7")
                implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
                implementation("io.ktor:ktor-client-logging:2.3.7")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:2.3.7")
            }
        }
        val iosMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-darwin:2.3.7")
            }
        }
    }
}

HttpClient Factory

// commonMain/kotlin/network/HttpClientFactory.kt
object HttpClientFactory {
    fun create(
        platform: Platform,
        isDebug: Boolean = false
    ): HttpClient {
        return HttpClient(createEngine(platform)) {
            install(ContentNegotiation) {
                json(Json {
                    ignoreUnknownKeys = true
                    isLenient = true
                    encodeDefaults = false
                })
            }

            if (isDebug) {
                install(Logging) {
                    level = LogLevel.INFO
                    logger = object : Logger {
                        override fun log(message: String) {
                            println("Ktor: $message")
                        }
                    }
                }
            }

            install(Auth) {
                bearer {
                    loadTokens {
                        // Access Token from secure storage
                        BearerTokens(
                            accessTokenStorage.get() ?: "",
                            refreshTokenStorage.get() ?: ""
                        )
                    }
                    refreshTokens {
                        // Refresh token logic
                        val newTokens = authApi.refreshToken()
                        accessTokenStorage.save(newTokens.accessToken)
                        refreshTokenStorage.save(newTokens.refreshToken)
                        BearerTokens(newTokens.accessToken, newTokens.refreshToken)
                    }
                }
            }

            defaultRequest {
                url {
                    protocol = URLProtocol.HTTPS
                    host = "api.example.com"
                }
                header("X-API-Version", "1.0")
                header("X-Platform", platform.name)
            }

            expectSuccess = true
            HttpResponseValidator {
                handleResponseExceptionWithRequest { exception, request ->
                    when (exception) {
                        is ClientRequestException -> {
                            val statusCode = exception.response.status.value
                            when (statusCode) {
                                401 -> throw UnauthorizedException()
                                403 -> throw ForbiddenException()
                                404 -> throw NotFoundException()
                                in 500..599 -> throw ServerException()
                            }
                        }
                        is ServerResponseException -> throw ServerException()
                    }
                }
            }

            install(ResponseObserver) {
                onResponse { response ->
                    // Track response times, errors
                }
            }
        }
    }

    private fun createEngine(platform: Platform): HttpClientEngine {
        return when (platform) {
            Platform.ANDROID -> createOkhttpEngine()
            Platform.IOS -> createDarwinEngine()
        }
    }
}

Platform-Specific Engines

Android (OkHttp)

// androidMain/kotlin/network/OkHttpEngineFactory.kt
fun createOkhttpEngine(): OkHttpEngine {
    val config = OkHttpConfig {
        preconfigured = OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .addInterceptor { chain ->
                val request = chain.request().newBuilder()
                    .header("User-Agent", "Android App/1.0")
                    .build()
                chain.proceed(request)
            }
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = if (BuildConfig.DEBUG) {
                    HttpLoggingInterceptor.Level.BODY
                } else {
                    HttpLoggingInterceptor.Level.NONE
                }
            })
            .cache(
                Cache(
                    File(context.cacheDir, "http_cache"),
                    10 * 1024 * 1024 // 10MB
                )
            )
            .build()
    }
    return OkHttpEngine(config)
}

iOS (Darwin)

// iosMain/kotlin/network/DarwinEngineFactory.kt
fun createDarwinEngine(): DarwinEngine {
    val config = DarwinClientConfig {
        configureSession {
            setAllowsCellularAccess(true)
            setAllowsExpensiveNetworkAccess(true)
            setAllowsConstrainedNetworkAccess(true)

            // Configure timeout
            setTimeoutIntervalForRequest(30.0)
            setTimeoutIntervalForResource(60.0)

            // Configure cache
            URLCache(
                sharedCacheDirectory,
                10 * 1024 * 1024 // 10MB
            ).let {
                URLCache.setSharedURLCache(it)
            }
        }
    }
    return DarwinEngine(config)
}

API Service Pattern

// commonMain/kotlin/network/api/UserApi.kt
class UserApi(
    private val client: HttpClient
) {
    suspend fun getUsers(page: Int = 1): PaginatedResponse<User> {
        return client.get("/users") {
            parameter("page", page)
            parameter("limit", 20)
        }.body()
    }

    suspend fun getUser(id: String): User {
        return client.get("/users/$id").body()
    }

    suspend fun createUser(request: CreateUserRequest): User {
        return client.post("/users") {
            setBody(request)
            contentType(ContentType.Application.Json)
        }.body()
    }

    suspend fun updateUser(id: String, request: UpdateUserRequest): User {
        return client.put("/users/$id") {
            setBody(request)
            contentType(ContentType.Application.Json)
        }.body()
    }

    suspend fun deleteUser(id: String) {
        return client.delete("/users/$id")
    }

    suspend fun uploadAvatar(userId: String, file: ByteArray): String {
        return client.submitFormWithBinaryData(
            url = "https://api.example.com/users/$userId/avatar",
            formData = formData {
                append("avatar", file, Headers.build {
                    append(HttpHeaders.ContentDisposition, "filename=avatar.jpg")
                })
            }
        ).body()
    }
}

Network Exceptions

// commonMain/kotlin/network/NetworkExceptions.kt
sealed class NetworkException(message: String? = null) : Exception(message)

class UnauthorizedException : NetworkException("User not authenticated")
class ForbiddenException : NetworkException("Access forbidden")
class NotFoundException : NetworkException("Resource not found")
class ServerException : NetworkException("Server error occurred")
class NetworkUnavailableException : NetworkException("Network unavailable")
class TimeoutException : NetworkException("Request timeout")

// Wrap Ktor exceptions
fun Throwable.toNetworkException(): NetworkException {
    return when (this) {
        is NetworkException -> this
        is ClientRequestException -> when (response.status.value) {
            401 -> UnauthorizedException()
            403 -> ForbiddenException()
            404 -> NotFoundException()
            else -> NetworkException(message)
        }
        is ServerResponseException -> ServerException()
        is HttpRequestTimeoutException -> TimeoutException()
        is UnreachableAddressException,
        is ConnectTimeoutException -> NetworkUnavailableException()
        else -> NetworkException(message ?: "Unknown network error")
    }
}

Result Wrapper

// commonMain/kotlin/network/ApiResult.kt
sealed class ApiResult<out T> {
    data class Success<T>(val data: T) : ApiResult<T>()
    data class Error(val error: NetworkException) : ApiResult<Nothing>()

    suspend fun <R> map(transform: (T) -> R): ApiResult<R> = when (this) {
        is Success -> Success(transform(data))
        is Error -> this
    }

    suspend fun <R> flatMap(transform: (T) -> ApiResult<R>): ApiResult<R> = when (this) {
        is Success -> transform(data)
        is Error -> this
    }

    fun getOrNull(): T? = when (this) {
        is Success -> data
        is Error -> null
    }

    fun getOrElse(defaultValue: T): T = when (this) {
        is Success -> data
        is Error -> defaultValue
    }
}

suspend fun <T> apiCall(block: suspend () -> T): ApiResult<T> = try {
    ApiResult.Success(block())
} catch (e: Exception) {
    ApiResult.Error(e.toNetworkException())
}

// Usage
val result: ApiResult<User> = apiCall { userApi.getUser("123") }
when (result) {
    is ApiResult.Success -> showUser(result.data)
    is ApiResult.Error -> showError(result.error)
}

Retry Logic

// commonMain/kotlin/network/Retry.kt
suspend fun <T> retryApiCall(
    maxRetries: Int = 3,
    delayMs: Long = 1000,
    block: suspend () -> T
): T {
    var lastException: Exception? = null
    repeat(maxRetries) { attempt ->
        try {
            return block()
        } catch (e: Exception) {
            lastException = e
            if (e is NetworkUnavailableException || e is TimeoutException) {
                if (attempt < maxRetries - 1) {
                    delay(delayMs * (attempt + 1))
                }
            } else {
                throw e
            }
        }
    }
    throw lastException ?: RuntimeException("Max retries exceeded")
}

Offline Support

// commonMain/kotlin/network/OfflineCapableApi.kt
class OfflineCapableApi<T : Any>(
    private val api: T,
    private val cache: DatabaseCache
) : OfflineCapableApi<T> by api {

    suspend fun <R> withCache(
        key: String,
        ttl: Duration,
        block: suspend () -> R
    ): R = withContext(Dispatchers.IO) {
        // Try cache first
        cache.get<R>(key)?.let { cached ->
            if (cached.timestamp + ttl.toMillisMilliseconds() > Clock.System.now()) {
                return@withContext cached.data
            }
        }

        // Fetch from network
        try {
            val result = block()
            cache.put(key, CachedData(result, Clock.System.now()))
            result
        } catch (e: NetworkException) {
            // Return stale cache if network fails
            cache.get<R>(key)?.data ?: throw e
        }
    }
}

Dependency Injection Setup

// commonMain/kotlin/di/NetworkModule.kt
val networkModule = module {
    single { HttpClientFactory.create(get(), get()) }
    single { UserApi(get()) }
    single { AuthApi(get()) }
    factory { ConnectivityMonitor(get()) }
}

Best Practices

✅ DO

// ✅ Use typed API services
class UserApi(private val client: HttpClient)

// ✅ Wrap calls in result types
suspend fun getUser(): ApiResult<User>

// ✅ Configure timeouts
config { setTimeoutIntervalForRequest(30.0) }

// ✅ Add logging for debug builds
if (isDebug) { install(Logging) }

// ✅ Handle exceptions at boundaries
try { api.call() } catch (e: NetworkException) { /* handle */ }

❌ DON'T

// ❌ Don't create multiple HttpClient instances
// Use singleton via DI

// ❌ Don't block on suspend calls
runBlocking { api.call() }  // ❌

// ❌ Don't ignore exceptions
try { api.call() } catch (e: Exception) { }  // ❌

// ❌ Don't hardcode URLs
client.get("https://api.example.com/users")  // ❌
// Configure base URL in defaultRequest

Remember: Networking is the bridge between your app and the world. Make it robust, testable, and platform-optimized.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

33.2%
按下载量换算44

Claude

31%
按下载量换算41

Cursor

20.47%
按下载量换算27

Gemini CLI

8.87%
按下载量换算12

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills