news 2026/9/7 23:43:59

caveman TypeScript SDK(@caveman-ai/sdk)实战解析:单文件零依赖客户端的追踪、工具搜索、压缩与跨语言一致性体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
caveman TypeScript SDK(@caveman-ai/sdk)实战解析:单文件零依赖客户端的追踪、工具搜索、压缩与跨语言一致性体系

caveman TypeScript SDK(@caveman-ai/sdk)实战解析:单文件零依赖客户端的追踪、工具搜索、压缩与跨语言一致性体系

【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman

本文以packages/sdk/typescript/CLAUDE.md为核心骨架,结合src/index.ts(约 2400 行的单文件实现)、测试套件与跨语言 parity 契约,完整讲解@caveman-ai/sdk的目录布局、全部关键 API(Cave 客户端、CaveTrace 追踪、BM25 工具搜索、compress、context pack、checkpoints、runtime policy、retry loop breaker、jobs 预留面)、wire 约定与常见陷阱。读完你可以直接安装并使用该 SDK,理解它与 Caveman 网关之间的字节级契约,并知道每个"诚实性"设计(byte-safe 直通、basis: "inferred"、跨语言 parity 门禁)背后的源码依据。

1. 包概览:单文件、零运行时依赖、Node ≥ 22.13

SDK 是一个导出为 ES module 的单文件包,全部实现集中在 src/index.ts。从 package.json 可以确认其发布形态:

  • 包名@caveman-ai/sdk,当前版本 1.0.0,MIT 许可,"type": "module",入口为dist/index.js(类型声明dist/index.d.ts);
  • 零运行时依赖——devDependencies中只有typescript@5.9.3sideEffects: false
  • engines要求Node.js ≥ 22.13(依赖原生 fetch、AbortSignal、WebCrypto 的 Ed25519 验签等能力);
  • 关键脚本:buildtsc)、test:typestsc --project tsconfig.test.json,仅编译类型断言)、test:nodenode --test tests/*.runtime.mjs,运行时测试针对编译产物dist/)。

安装与最小用法(来自 README.md):

npm install @caveman-ai/sdk
import { Cave } from "@caveman-ai/sdk"; const cave = new Cave({ apiKey: process.env.CAVE_API_KEY!, baseURL: "http://127.0.0.1:8787", agent: "support-agent", }); const result = await cave.compress("large payload"); console.log(result.output, result.basis); // basis is inferred

连接类调用需要 Caveman 网关的 key;本地 Engine 压缩能力则走独立的 Caveman 运行时,与账号体系解耦。

2. 目录布局与测试双轨制

CLAUDE.md 给出的 Layout 小节是理解本包的钥匙:

文件职责
src/index.ts整个 SDK;导出CaveCaveTraceCaveOptionsCaveToolToolSearchResultCompressOptionsCompressResult及全部ContextPack*类型
tests/tool-search.test.ts纯类型级断言,由tsc --noEmit编译校验,不执行
tests/tool-search.runtime.mjs运行时测试,node:test+ 全局 fetch mock,从dist/导入
tests/runtime-policy.runtime.mjs + tests/runtime-policy.test.tsruntime-policy 客户端;驱动 packages/sdk/parity/runtime-policy.fixtures.json 的每一节:fetch wire、签名用例、全部assignment_vectors(严格浮点相等)、全部guard_cases(共享算子真值表在 fixture 里而非测试文件里)以及全部decision_cases。约定是遍历数组,永远不硬编码数量
tests/parity.runtime.mjs跨语言一致性套件;驱动 packages/sdk/parity/fixtures.json(与 sdk-python 共享)。同一份 fixture、两种语言——任何一端 SDK 多一个字段、少一个字段都会让 CI 变红
tests/trace-continuity.runtime.mjstrace/span id 铸造 + 哪些请求携带x-cave-trace-id/x-cave-parent-span-id;镜像 Python 的tests/test_trace_continuity.py
tsconfig.json / tsconfig.test.json两套配置,测试配置额外覆盖tests/;两者都继承仓库根的 tsconfig.base.json

仓库实际测试目录还包含 assembly.runtime.mjs、cave-plan.runtime.mjs、context-pack.runtime.mjs、exporter.runtime.mjs、task-profile.runtime.mjs、tool-events.runtime.mjs、transport.runtime.mjs、packaging.runtime.mjs、shared-context.runtime.mjs、structural.runtime.mjs 等,覆盖了后文各 API 面。

核心约定(Conventions 节,必须原样保留):

  • 测试双轨.test.ts只做类型断言(只编译不运行);.runtime.mjs是运行时测试(对dist/运行)。因此先构建再跑运行时测试pnpm build && pnpm test:node
  • wire 方向:请求体键名对网关一律snake_case;响应映射为camelCase(体现在ToolSearchResult上)。
  • x-cave-workflow头永不省略:默认取defaultWorkflow ?? "unlabeled-workflow"
  • 延迟工具搜索的会话交接三处联动:请求体session_id、结果sessionId、provider 请求头x-cave-tool-session。任何改动必须同步更新 sdk-python 与 parity fixtures。

3. Cave 客户端:构造与配置

new Cave(options)必填apiKeybaseURLagent,源码在 src/index.ts。完整CaveOptions类型(L4)比文档清单更细,逐字段说明:

字段说明
apiKey/baseURL/agent必填;baseURL必须是无凭据、无 query/fragment 的绝对 http(s) URL,尾部斜杠会被归一化
defaultWorkflow工作流标签;缺省时回落到CAVE_WORKFLOW环境变量,再回落到"unlabeled-workflow"
retention"metadata" \| "zdr" \| "configured"
verifyOnInit可选布尔
controlURL保留给 control-api/api/v1/*面的独立地址,同样经过严格 URL 校验
user不透明的终端用户标识,作为x-cave-user-hash转发;它是原始值透传——若含 PII,调用方须自行先哈希
timeoutMs所有 SDK HTTP 请求的有限截止时间,默认 30 秒,必须是正安全整数
signal调用方级取消信号,应用于所有 SDK HTTP 请求

从源码结构看一个有趣的细节:构造函数通过globalThis读取CAVE_WORKFLOW(而非process),保持浏览器中立;环境变量值会先小写化并按[a-z0-9_-]{1,96}校验,非法值被忽略而不是让每个请求都 400——这让cave wrap --workflow x之类的包装器无需改代码即可给 SDK 应用的所有请求打标签,且显式传入的defaultWorkflow永远优先。

4. 追踪:cave.trace 与 trace 连续性

cave.trace(opts, fn)把回调包进一个CaveTrace

  • id 铸造规则:trace 用与 OTel exporter 相同的 RNG 铸造traceId(32 位小写 hex)与根spanId(16 位小写 hex)。
  • 续接入口 traceopts.traceId/opts.spanId用于续接入站 trace;形状不是精确 hex 的值会被替换而不是上线(源码中normalizeTraceId/normalizeSpanId保证)。
  • 头注入的边界:只有通过 trace 发出的 provider 调用和 trace 作用域内的/sdk/v1/*调用才携带x-cave-trace-id+x-cave-parent-span-id;直接挂在Cave上构建的 provider 客户端与 SDK 调用两者都不带。trace-continuity.runtime.mjs 专门验证这一点。
  • 工具调用 spantrace.tool(name, options, fn)在工具执行前后向POST /sdk/v1/events上报span_type: "tool.call"事件(序列号、耗时、ok/error 结果);该上报是尽力而为的元数据——telemetry 失败绝不能替换或吞掉工具的结果/错误(源码 L807-L817 的.catch(() => undefined))。
  • CaveTrace.exporter({serviceName?}):返回按服务名 memoized 的OTelExporter,其defaultTraceId就是本 trace 的 id——SDK 自己录的 span 和网关的请求行因此并入同一条 trace。runtime-policy 的 decision span 若传入CaveTrace,也复用同一个调用方可达的默认缓冲;调用trace.exporter().flush()即可把它们发出去。此面镜像 Python 的Trace.exporter

5. 延迟工具搜索:BM25/嵌入排序 + 会话交接

这是 SDK 的核心省 token 面。两个入口共享同一契约:

  • cave.tools({ catalog, strategy })→ 返回{ initial, strategy, search(query, opts?) }
  • cave.toolSearch(catalog, query, opts?)→ 直接变体,适合你在外部管理 catalog 的场景。

关键行为(文档 + 源码 toolSearch 实现 印证):

  1. search()是异步的(返回Promise<ToolSearchResult>)——这是对 1.0 的破坏性变更(旧版同步、返回CaveTool[]),调用方必须await
  2. opts.ranker"bm25" | "embeddings")逐字透传给网关;SDK 从不算相似度(byte-safe、零依赖)。网关只有在接入了嵌入 provider 时才认"embeddings"
  3. opts.toolSessionId发送session_id,让 provider 侧回调能把已被调用过的延迟工具重新注入。交接的完整链路是:请求体session_id→ 结果sessionId→ provider 头x-cave-tool-session
  4. strategy 语义(源码 L461-L493):"all"initial即整个 catalog;"deferred"initial=alwaysLoad工具 + 至多initialToolCount个(默认 8)懒加载工具;search()再按需从网关拉取。永不带search()调用就返回全量目录。另有maxLoadedTools上限校验(必须 ≥ alwaysLoad 数量)。
  5. 结果映射:响应体sent_schema_tokens/full_schema_tokens映射为sentSchemaTokens/fullSchemaTokens(camelCase);savedTokens本地派生值full - sent),不来自网关响应;reductionPct四舍五入到一位小数(Math.round(x * 1000) / 10)。schema token 计数器是估算,tokenBasis披露用的是什么计数器,basis恒为"inferred"
  6. 防御性校验:响应里的工具名必须在本地 catalog 中存在且不重复,否则抛错——网关不能替你"发明"工具。

ToolSearchResult的完整字段(类型定义):sessionId?toolssentSchemaTokensfullSchemaTokensdeferredCountmethodtokenBasisbasis: "inferred"、只读的savedTokensreductionPct

6. 压缩与上下文:compress / context.pack / checkpoint

6.1 cave.compress —— 唯一的"变小字节"路径,且必须委托

cave.compress(payload, opts?)Promise<CompressResult>POST /sdk/v1/compress,把 Engine 的报告映射出来。文档 Gotchas 强调的第一条就是byte-safe:SDK 把请求体逐字发给网关,不允许改写;compress()是唯一能产出更小字节的路径,而它委托给 Engine,从不自己实现压缩器。

失败语义(compress 实现 逐条印证):

  • 任何传输/解析问题(非 2xx、响应缺output字符串、token 计数非法、tokensAfter > tokensBefore)一律fail-closed 直通output是原始输入、ratio: 0、无recoveryHandle
  • ratio不由服务端字段决定,而是从校验过的两个计数器重新计算——"重算而不是保留一个不一致或乐观的服务端字段";
  • tokenCountBasis披露 Engine 用的计数器(如o200k_baseapprox_chars_div_4),basis恒为"inferred"——SDK 从不发verified
  • 成功时可选带出recoveryHandle(恢复字节级原值的凭据)、method(如"toon"/"elision")、losslessToModel

CompressOptions.contentType支持"json" | "toon" | "log" | "code" | "diff" | "search-result" | "text" | "toolschema"等提示,用于 Engine 的检测器。

6.2 cave.context.pack —— 连接态、有损的选择器

cave.context.pack(query, items, options)Promise<ContextPackResult>connected-onlyPOST /sdk/v1/context/pack。文档明确其定位:它决定什么进入模型窗口,而 cache-optimal assembly 决定被选内容放在哪——两者互补而非替代。要点:

  • 它把条目字节发给网关,从不在本地 wrap 运行;是有损选择器,绝不通 CCR/ledger;
  • 返回精确的deferredIds(请求 id 减去选中 id,按请求顺序),调用方必须保留这些被延迟的条目以便补充;
  • 传输失败或报告畸形时,返回全部原始条目且tokensSaved为 0("零推断节省",而不是谎称省了多少);
  • 源码中的完整性校验相当严格(contextPack 实现):maxTokens必须为正、条目 id 不可重复、选中 id 必须属于请求集合、deferred_ids必须与期望集合逐项一致tokensUsed + tokensSaved === tokensBeforedeferredCount === deferredIds.length,任一不满足即回落到 passthrough。

ContextPackItem支持id/text/ 可选tokens/ RFC 3339timestamp/priority/pinpin为"必需上下文",钉住的条目放不下时调用返回诚实的 0);ContextPackOptionsmaxTokens(必填 > 0)、reserveTokensnowrecencyHalfLifeMsrecencyWeighterrorBoost

6.3 checkpoint 与 expand —— 可逆性是强制要求

  • CaveTrace.context.checkpoint()POST /sdk/v1/checkpoints,网关持久化(Valkey)并返回可逆的source_ref
  • CaveTrace.context.expand(sourceRef):GET 半程,GET /sdk/v1/checkpoints/{ref}/expand返回存储的{source_ref, version, messages, checkpoint}。文档的说法很直白:一个无法被 expand 的 checkpoint 就是 bug

同一 trace 下还有artifacts面:CaveTrace.artifacts.page()发送版本化的{value, options, workflow}(网关注入x-cave-artifact-envelope: value-v1头),网关只存储 JSONvalue;非 verbatim 策略存储成功后返回带artifact_id的占位包裹文本;artifacts.get(id)执行鉴权取回;strategy: "verbatim"完全绕过存储直接返回原值。

7. Provider 客户端与其他 API 面

7.1 薄 provider 客户端

cave.openai()/cave.anthropic()/cave.gemini()/cave.vertex()都是经网关代理的薄客户端(前缀分别为/openai/v1/anthropic/gemini/vertex),可选upstreamKey(Vertex 场景是 Google OAuth2 访问令牌,网关以Authorization: Bearer …转发);每个客户端都暴露.rawfetch 逃生舱(镜像 Python 的Provider.raw),且 raw 请求被约束在本 provider 前缀内。

cave.bedrock({ region, endpoint? })特殊:它是一个零网络的第一方路由描述符——endpoint 缺省"runtime"gatewayPrefix/bedrock,显式"mantle"时为/bedrock/anthropicsdkOnly: false(镜像 Python 的sdk_only),不含任何 AWS 秘密。

7.2 其余关键 API(文档 Key APIs 节逐条对应)

  • cave.prompts.internalBrevity({style, preserveErrorsVerbatim?, preserveCodeVerbatim?}):输出风格片段,style: "none"返回空串(实现 L597-L600 就是一行三元表达式);
  • CaveTrace.model.openai.responses.create(body, {cave:{latencyClass, toolSessionId}}):传latencyClass会设置x-cave-async头("interactive"之外均为"true");传toolSessionId会设置x-cave-tool-session
  • cave.exporter({serviceName?})OTelExporterrecordSpan(...)把当前 GenAI 字段映射为gen_ai.*export()以 OTLP/JSONPOST到标准/v1/traces(头来自otlpHeaders();旧路径/otlp/v1/traces仅服务端兼容保留)。SpanOptions支持inputTokens/outputTokens/cachedTokens/costUsd等 provider 报告值;
  • cave.cavePlan()GET /sdk/v1/cave-plan,以项目 key 的plan:read作用域鉴权,逐字返回 snake_case 计划——所有美元数字都是推断值且是每日费率,SDK 从不重推或按月投影;
  • cave.sharedContext.put/get:会话键化的多 agent 共享上下文(POST/GET /sdk/v1/shared-context/{key}),网关按租户命名空间隔离。

7.3 retryLoopBreaker 与 jobs 预留面

  • cave.retryLoopBreaker(threshold = 3)RetryLoopBreaker.record(name, args)连续第threshold + 1相同(名称 + 稳定序列化参数签名)工具调用时抛RetryLoopError.guard(name, args, fn)先 record 再执行fn;任何不同调用都会重置连击计数,.reset()可手动清零(实现 L664-L709)。
  • cave.jobs预留JobsClient面:submit/status/cancel/wait/submitAndWait每个方法都在网络 I/O 之前本地失败,抛出code = "cave_async_jobs_unavailable"AsyncJobsUnavailableError——在持久加密请求存储、凭据托管与可排空 worker 就位之前,不允许出现"假的已排队/已完成"。

8. runtimePolicy:签名校验、TOFU 与"永不抛异常"的路由决策

cave.runtimePolicy({publicKey?, autoRefreshSeconds?, killEnv?})RuntimePolicyClient,是 SDK 中最重安全逻辑的一面(实现),文档每条断言都能在源码找到对应:

  • refresh()是唯一网络调用GET /sdk/v1/runtime-policy,标准头减去content-type;请求挂 30 秒AbortSignal(镜像 Python 的timeout=30)。
  • 响应有界读取content-length超过 1 MiB 直接取消;流式读取累计超 1 MiB 抛oversized_response;fetch 实现没有有界可读 body 时抛bounded_response_unavailablefail closed 而不是调用无界text()
  • Ed25519 验签在解析之前:对bundle字符串的精确 UTF-8 字节验签(WebCrypto + RFC 8410 SPKI 前缀,任何异常都是false)。
  • TOFU 钉住时机:签名验证通过的那一刻就钉住公钥——早于 schema_version / sequence 检查。否则会出现降级窗口:第一个签名 bundle 因 schema 被拒后,一个无签名的 bundle 反而被接受(verifyBundle 注释 L1222-L1266 把这段推理写得很完整)。
  • schema 与单调性:只接受caveman.runtime-policy.v1sequence回退即拒(runtime policy sequence regressed);一切失败保留 last-known-good。
  • autoRefresh 不堆叠:后台 tick 落在一次进行中的 refresh 上时跳过而不是排队。
  • decide(taskFamily, {unitKey, context, trace})同步、纯本地、永不抛:内部故障降级为baselinekill()本地闩锁,killEnv(默认CAVEMAN_POLICY_KILL每次 decide 重读(运行中可翻转),state()给快照。
  • 实验语义:holdout 先切出并强制落到 fallback("抑制,而非更危险的变体");缺unitKey或实验配置非法时从不猜测 armno_unit_key/invalid_experiment);同一 family 在获胜层级有 >1 个候选时返回ambiguous_policy,宁缺毋猜。
  • 确定性分桶:导出的policyUnitFraction(...keys)是 Goshared/platform/sampling.Fraction的逐字节移植——每个 key 前缀 8 字节大端长度、SHA-256、取前 8 摘要字节做大端 uint64 右移 11 再除 2^53。导出它是为了让调用方能复现分派,也让跨语言 fixture 能按位钉住这个移植。
  • 定位声明:只做路由,"到处没有节省词汇"(no savings vocabulary);verify/budget/escalation对 SDK 是黑盒,原样透传给调用方。

其测试 runtime-policy.runtime.mjs(约 1176 行)驱动共享 fixture runtime-policy.fixtures.json 的全部用例节,是这一面"不靠口头保证"的落地方式。

9. 跨语言 parity:漂移即 CI 失败

文档 Gotchas 中最硬的一条是mirror sdk-python:每个字段/方法在两个 SDK 中都存在,由共享 parity 套件强制——"一次漂移是 CI 失败,不是约定失误;改了一个 SDK,必须同时改另一个和 fixture"。

packages/sdk/parity/CLAUDE.md 进一步说明这份契约如何执行:

  • fixtures.json 是契约本体:一个config、命名头集合(std_headers/std_headers_traced/std_headers_async_traced/otlp_headers)与有序operations列表;每个 operation 带input、预制response(或transport: "error"强制 byte-safe 直通)和expect块(wire 的 method/path/headers/body 或 body_keys + result);
  • TS 半边是 tests/parity.runtime.mjs(mock fetch),Python 半边是 sdk-python 的tests/test_parity.py(mock urlopen);每半边对每一个operation 都有 handler,缺 handler 就是失败,不是跳过;
  • 编辑规则:给一个 SDK 加字段 → 在这里加 operation → 另一个 SDK 的半边变红,"那个红色正是目的所在";
  • 头按 key 小写化比较(Python urllib 会大写化);fixture 值必须避开两语言编码不一致的字符(如! ( ) *,JSencodeURIComponent与 Pythonquote分歧);随机值不得进入断言,SDK 本该铸造的 id 通过 operationinput注入并钉在期望头集合里。

这就是 CLAUDE.md 所谓"release gate, not documentation"的含义:它不是描述行为的文档,而是行为本身的裁判。

10. 陷阱清单与适用前提

把文档 Gotchas 节整理成一张可操作清单:

  1. byte-safe 是底线:SDK 对网关的请求体逐字发送,禁止改写;唯一变小字节的路径是compress(),且它委托 Engine,任何异常直通原文。
  2. context packing 是 connected-only 且有意有损:发送条目字节到网关、从不在本地 wrap 运行、依赖调用方保留deferredIds点名的每条;它选"什么进窗口",cache-optimal assembly 管"放哪里"。
  3. mirror sdk-python:单侧改动必须双侧 + fixture 同步。
  4. npm 名称现状:发布名@caveman-ai/sdk,workspace 名在 npm 重定向方案落地前保持@caveman-ai/sdk
  5. deferred 初始集=alwaysLoad工具 + 至多initialToolCount(默认 8);不带search()调用永不返回全量 catalog。
  6. 数字语义reductionPct一位小数;savedTokens是派生值(full - sent),不是网关字段;SDK 全链路basis: "inferred"verified只属于 Cloudactive路径。

适用前提:Node ≥ 22.13、ES module 环境、连接类 API 需要网关 key;运行测试需先pnpm build && pnpm test:node。所有接口面(provider 客户端、compress、延迟工具搜索、可逆 checkpoint 与 artifacts、retry-loop 中断、runtime policy、零依赖 OTLP/JSON exporter)与 README.md 的清单一一对应,异步作业则如前所述为本地失败的预留面。

总结

@caveman-ai/sdk用约 2400 行单文件实现了一个"网关协作型" TypeScript 客户端:以Cave/CaveTrace两个入口覆盖追踪、工具延迟加载、压缩、上下文打包、checkpoint 与产物五大能力,以 byte-safe 直通、inferred基线、确定性分桶移植和 Ed25519 + TOFU 验签守住诚实性与安全性边界,再以与 Python SDK 共享的 parity fixture 把"两语言一个契约"变成 CI 门禁。对需要把 agent 接入 Caveman 网关、同时要求可观测与可验证节省语义的 TypeScript 项目,这套 API 与约定(尤其x-cave-workflow永省略除、snake_case 出/camelCase 入的 wire 方向、以及三处联动的 tool-session 交接)是完整的实现事实来源。

【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 23:41:51

mayavi+PyQt5集成实战:从环境搭建到三维可视化

如果你打算在 Python 里同时做三维科学可视化和桌面端交互界面&#xff0c;那“mayavi PyQt5”这个组合你一定绕不开。mayavi 负责把等值面、体渲染、流线这些复杂三维内容快速画出来&#xff0c;PyQt5 负责外面的窗口、控件和交互逻辑&#xff0c;两者拼在一起&#xff0c;就…

作者头像 李华
网站建设 2026/9/7 23:41:26

基于DDPG的多动作并行异步强化学习在选矿智能决策中的应用

简介&#xff1a;这是一篇来自《控制与决策》期刊的学术论文PDF&#xff0c;标题为“基于多动作并行异步深度确定性策略梯度的选矿运行指标决策方法”&#xff0c;面向工业智能、强化学习及流程工业自动化领域的研究者和工程师。论文针对深度确定性策略梯度&#xff08;DDPG&am…

作者头像 李华
网站建设 2026/9/7 23:40:50

低照度图像增强实战:从Retinex到Zero-DCE算法解析与复现

简介&#xff1a;低照度环境下的图像常因光线不足导致RGB特征信息匮乏&#xff0c;目标检测时特征提取与识别定位的难度随之上升。这份代码资料正是针对此类痛点&#xff0c;将传统算法与深度学习两类低照度增强手段合并整理&#xff0c;涵盖Retinex、EnlightenGAN、Zero-DCE等…

作者头像 李华
网站建设 2026/9/7 23:40:00

Kuikly跨端框架鸿蒙适配实践:从安全区到生命周期的分场景避坑指南

我今年接手了一个把存量Kotlin业务搬到鸿蒙上的活&#xff0c;第一反应是“鸿蒙原生ArkTS再写一遍”工作量太大&#xff0c;团队最后定了Kuikly做跨端框架。忙完几个大版本迭代后&#xff0c;我想把这几个月在分场景适配上的心得系统整理一下&#xff0c;尤其是屏幕安全区、软键…

作者头像 李华
网站建设 2026/9/7 23:39:49

个人云服务器建站+备案+小程序域名通用部署文档(脱敏版)

一、项目基础信&#xff08;全脱敏通用模板&#xff09;主域名&#xff1a;个人自定义主域名WWW子域名&#xff1a;www.自定义主域名服务器&#xff1a;阿里云ECS 华北节点公网IP&#xff1a;xxx.xxx.xxx.xxxICP备案号&#xff1a;个人备案专属编号公安备案数据码&#xff1a;x…

作者头像 李华