karin-plugin-kkk 2.45.0-beta.1 → 2.45.0-beta.4

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/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [2.45.0-beta.4](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.0-beta.3...v2.45.0-beta.4) (2026-10-06)
6
+
7
+
8
+ ### 🐛 错误修复
9
+
10
+ * 优化更新检测逻辑,支持逐渠道版本锁定与提醒 ([ddfd011](https://github.com/ikenxuan/karin-plugin-kkk/commit/ddfd011ac3bcd49789870a2e154003973c52cea9))
11
+ * 优化更新逻辑以支持金丝雀用户的版本解锁和范围起点解析 ([4a28ce5](https://github.com/ikenxuan/karin-plugin-kkk/commit/4a28ce55b82115683713ad6985d456751f151c23))
12
+
13
+ ## [2.45.0-beta.3](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.0-beta.2...v2.45.0-beta.3) (2026-10-06)
14
+
15
+
16
+ ### 🐛 错误修复
17
+
18
+ * 更新发布脚本以正确引用 package.json 文件 ([499ef1d](https://github.com/ikenxuan/karin-plugin-kkk/commit/499ef1d824a4b34b09101accd6988929569d0354))
19
+
20
+ ## [2.45.0-beta.2](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.45.0-beta.1...v2.45.0-beta.2) (2026-10-06)
21
+
22
+
23
+ ### 🐛 错误修复
24
+
25
+ * 添加 @clack/prompts 依赖并更新发版脚本以使用交互式版本选择 ([dd18fc2](https://github.com/ikenxuan/karin-plugin-kkk/commit/dd18fc23993d6b9ca6185cb4a75190a16f9c3dab))
26
+ * 移除不必要的 bumpp 依赖,并优化本地发版脚本 ([4123512](https://github.com/ikenxuan/karin-plugin-kkk/commit/4123512b404009daa34512cc57a375c3de0c8462))
27
+ * ci ([5767211](https://github.com/ikenxuan/karin-plugin-kkk/commit/57672119b6502ba9717eaf3a45dcf0b65ec9d36f))
28
+ * 规范化短哈希长度为 7 位,以避免构建指纹误判 ([de02dcc](https://github.com/ikenxuan/karin-plugin-kkk/commit/de02dcc39bf4d75178e21f2c947d827f43b11e14))
29
+ * ci ([d38ef28](https://github.com/ikenxuan/karin-plugin-kkk/commit/d38ef28a1c17717ea42341b10a6bcbf2b60849ae))
30
+ * ci ([c7ddce5](https://github.com/ikenxuan/karin-plugin-kkk/commit/c7ddce59ae8b60fc4c120b79cd3d191f96a69e1b))
31
+ * 回退版本号至 2.44.1,并修复 dry 模式下版本号验证逻辑 ([eabd9aa](https://github.com/ikenxuan/karin-plugin-kkk/commit/eabd9aa457d5ad098d7967304990ad8648073956))
32
+ * 优化版本比较逻辑,支持金丝雀用户的构建时间线判定 ([d811024](https://github.com/ikenxuan/karin-plugin-kkk/commit/d811024eeff8dfa28b70be7ecb0443011b2176e0))
33
+ * release 发布前剥离 devDeps,修复 GPR 报告步骤路径 ([2f02b22](https://github.com/ikenxuan/karin-plugin-kkk/commit/2f02b2294ade62b7b336363462e3cc8785d75217))
34
+ * 金丝雀用户的面板比较改为构建时间线判定 ([7aa712d](https://github.com/ikenxuan/karin-plugin-kkk/commit/7aa712dcf22113c58602629cec13115c62eefb9d))
35
+
5
36
  ## [2.45.0-beta.1](https://github.com/ikenxuan/karin-plugin-kkk/compare/v2.44.0...v2.45.0-beta.1) (2026-10-06)
6
37
 
7
38
 
@@ -1,10 +1,10 @@
1
1
  {
2
- "version": "2.45.0-beta.1",
3
- "buildTime": "2026-10-06T02:14:05.625Z",
4
- "buildTimestamp": 1791252845626,
2
+ "version": "2.45.0-beta.4",
3
+ "buildTime": "2026-10-06T07:34:14.563Z",
4
+ "buildTimestamp": 1791272054563,
5
5
  "name": "karin-plugin-kkk",
6
6
  "description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
7
7
  "homepage": "https://github.com/ikenxuan/karin-plugin-kkk",
8
- "commitHash": "292844e1ea45d460c6a677436ae4aa49655419c9",
9
- "shortCommitHash": "292844e1"
8
+ "commitHash": "e6ff6df77f6305256a35f531a2f0c26f95fa3341",
9
+ "shortCommitHash": "e6ff6df7"
10
10
  }
@@ -7841,8 +7841,17 @@ var Render = async (event, path, data) => {
7841
7841
  const templateType = path.split("/")[0];
7842
7842
  let hasUpdate = false;
7843
7843
  try {
7844
- const lockedVersion = await db.get("kkk:update:lock");
7845
- if (typeof lockedVersion === "string" && lockedVersion.length > 0) hasUpdate = isSemverGreater(lockedVersion, Root.pluginVersion);
7844
+ for (const channel of [
7845
+ "stable",
7846
+ "beta",
7847
+ "rc"
7848
+ ]) {
7849
+ const lockedVersion = await db.get(`kkk:update:lock:${channel}`);
7850
+ if (typeof lockedVersion === "string" && lockedVersion.length > 0 && isSemverGreater(lockedVersion, Root.pluginVersion)) {
7851
+ hasUpdate = true;
7852
+ break;
7853
+ }
7854
+ }
7846
7855
  } catch {}
7847
7856
  const useDarkTheme = await resolveUseDarkTheme(path, data);
7848
7857
  const result = await renderTemplate(path, data, {
@@ -24551,12 +24560,25 @@ var updateHelp_default = defineTemplate({
24551
24560
  text: "获取失败",
24552
24561
  active: false
24553
24562
  };
24554
- if (channel.status === "canary") return {
24563
+ if (channel.status === "canary") return channel.hasUpdate ? {
24564
+ dot: palette.success,
24565
+ text: "有新构建可升级",
24566
+ active: true
24567
+ } : {
24555
24568
  dot: palette.accentText,
24556
24569
  text: "main 分支构建",
24557
24570
  active: true
24558
24571
  };
24559
24572
  const order = semverCompare(channel.version ?? "0.0.0", data.currentVersion);
24573
+ if (channel.hasUpdate !== void 0) return channel.hasUpdate ? {
24574
+ dot: palette.success,
24575
+ text: "有更新可升级",
24576
+ active: true
24577
+ } : {
24578
+ dot: palette.faint,
24579
+ text: order < 0 ? "低于当前版本" : "已是最新",
24580
+ active: false
24581
+ };
24560
24582
  if (order > 0) return {
24561
24583
  dot: palette.success,
24562
24584
  text: "有更新可升级",
@@ -40317,6 +40339,23 @@ var getLagVersionCount = (changelog, localVersion, remoteVersion) => {
40317
40339
  }).length;
40318
40340
  };
40319
40341
  /**
40342
+ * 金丝雀用户的 range 起点解析:semver 的 ASCII 序(beta < canary)无法表达
40343
+ * 「发布晚于本机构建」——改按 pkg.pr.new 发布历史的时间线,取本机构建时间
40344
+ * 之前的最后一个发布版本作为 range 起点。失败返回 undefined(回退 semver)。
40345
+ */
40346
+ var resolveCanaryRangeStart = async (buildTimestamp) => {
40347
+ if (!buildTimestamp) return void 0;
40348
+ try {
40349
+ const nodes = (await axios.get("https://pkg.pr.new/api/repo/commits?owner=ikenxuan&repo=karin-plugin-kkk", { timeout: 1e4 })).data?.target?.history?.nodes;
40350
+ if (!Array.isArray(nodes)) return void 0;
40351
+ for (const n of nodes) {
40352
+ const t = n.authoredDate ? new Date(n.authoredDate).getTime() : 0;
40353
+ const v = /v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)/.exec(n.message ?? "")?.[1];
40354
+ if (t > 0 && t <= buildTimestamp && v) return v;
40355
+ }
40356
+ } catch {}
40357
+ };
40358
+ /**
40320
40359
  * 获取远程构建元数据
40321
40360
  * @param version 远程版本号
40322
40361
  * @returns 构建元数据对象,如果获取失败则返回 null
@@ -40389,9 +40428,10 @@ var getChangelogImage = async (ctx, props) => {
40389
40428
  lagVersionCount = getLagVersionCount(changelog, props.localVersion, props.remoteVersion);
40390
40429
  const remoteMeta = await getRemoteBuildMetadata(props.remoteVersion);
40391
40430
  if (remoteMeta?.buildTime) buildTime = formatBuildTime(remoteMeta.buildTime);
40431
+ const rangeStart = parseReleaseChannel(props.localVersion) === "Canary" ? await resolveCanaryRangeStart(getBuildMetadata()?.buildTimestamp) ?? props.localVersion : props.localVersion;
40392
40432
  changelog = range({
40393
40433
  data: changelog,
40394
- startVersion: props.localVersion,
40434
+ startVersion: rangeStart,
40395
40435
  endVersion: versionCore(props.remoteVersion),
40396
40436
  compare: "semver"
40397
40437
  });
@@ -40399,9 +40439,10 @@ var getChangelogImage = async (ctx, props) => {
40399
40439
  try {
40400
40440
  changelog = fs.readFileSync(Root.pluginPath + "/CHANGELOG.md", "utf8");
40401
40441
  lagVersionCount = getLagVersionCount(changelog, props.localVersion, props.remoteVersion);
40442
+ const rangeStart = parseReleaseChannel(props.localVersion) === "Canary" ? await resolveCanaryRangeStart(getBuildMetadata()?.buildTimestamp) ?? props.localVersion : props.localVersion;
40402
40443
  changelog = range({
40403
40444
  data: changelog,
40404
- startVersion: props.localVersion,
40445
+ startVersion: rangeStart,
40405
40446
  endVersion: versionCore(props.remoteVersion),
40406
40447
  compare: "semver"
40407
40448
  });
@@ -40424,36 +40465,55 @@ var getChangelogImage = async (ctx, props) => {
40424
40465
  };
40425
40466
  //#endregion
40426
40467
  //#region src/apps/update.ts
40427
- var UPDATE_LOCK_KEY = "kkk:update:lock";
40468
+ /** 更新提醒的订阅渠道(与面板 UpdateNotifyChannels 可选项一致) */
40469
+ var UPDATE_CHANNELS = [
40470
+ "stable",
40471
+ "beta",
40472
+ "rc"
40473
+ ];
40474
+ /** 各渠道更新提醒锁:记录该渠道上次已推送的版本,检测到新版本推送一次后上锁 */
40475
+ var updateLockKey = (channel) => `kkk:update:lock:${channel}`;
40428
40476
  var UPDATE_MSGID_KEY = "kkk:update:msgid";
40429
40477
  /**
40430
40478
  * 定时更新检测处理器
40431
- * 按订阅渠道检查远程版本(latest 恒参与 —— 装 prerelease 的用户也要收到转正提醒),
40432
- * 候选取 semver 最大且大于本地者,渲染变更日志并私聊通知所有主人。
40479
+ * 逐渠道检查远程 dist-tag 版本:检测到该渠道有新版本就推送一次然后上锁,
40480
+ * 各渠道锁相互独立、互不挤占;金丝雀安装按构建时间线判定新版本。
40433
40481
  *
40434
40482
  * @returns 是否继续后续任务
40435
40483
  */
40436
40484
  var Handler = async () => {
40437
- const tags = ["latest", ...(Config.app.UpdateNotifyChannels?.length ? Config.app.UpdateNotifyChannels : ["stable"]).filter((c) => c !== "stable")];
40438
- const remotes = await Promise.all(tags.map(async (tag) => {
40485
+ const channels = Config.app.UpdateNotifyChannels?.length ? Config.app.UpdateNotifyChannels : ["stable"];
40486
+ const tagOf = (c) => c === "stable" ? "latest" : c;
40487
+ const installedIsCanary = parseReleaseChannel(Root.pluginVersion) === "Canary";
40488
+ const installedBuildTime = getBuildMetadata()?.buildTimestamp;
40489
+ const tagVersions = /* @__PURE__ */ new Map();
40490
+ await Promise.all([...new Set(channels.map(tagOf))].map(async (tag) => {
40439
40491
  try {
40440
- return await getRemotePkgVersion(Root.pluginName, tag) || null;
40492
+ tagVersions.set(tag, await getRemotePkgVersion(Root.pluginName, tag) || null);
40441
40493
  } catch {
40442
- return null;
40494
+ tagVersions.set(tag, null);
40443
40495
  }
40444
40496
  }));
40445
- const remote = [...new Set(remotes.filter((v) => !!v))].filter((v) => isSemverGreater(v, Root.pluginVersion)).sort((a, b) => isSemverGreater(b, a) ? 1 : -1)[0];
40446
- if (!remote) return true;
40447
- try {
40448
- const lockedVersion = await db.get(UPDATE_LOCK_KEY);
40449
- if (typeof lockedVersion === "string" && lockedVersion.length > 0) {
40450
- if (!isSemverGreater(lockedVersion, Root.pluginVersion)) await db.del(UPDATE_LOCK_KEY);
40451
- else if (!isSemverGreater(remote, lockedVersion)) return true;
40497
+ const canaryInfo = installedIsCanary ? await fetchCanaryInfo() : null;
40498
+ const isNewVersion = (version) => {
40499
+ if (installedIsCanary && installedBuildTime !== void 0) {
40500
+ const releaseNode = canaryInfo?.nodes.find((n) => n.message.includes(version));
40501
+ if (releaseNode) return releaseNode.time > installedBuildTime;
40452
40502
  }
40453
- } catch {}
40454
- try {
40455
- await db.set(UPDATE_LOCK_KEY, remote);
40456
- } catch {}
40503
+ return isSemverGreater(version, Root.pluginVersion);
40504
+ };
40505
+ const pending = /* @__PURE__ */ new Set();
40506
+ for (const channel of channels) {
40507
+ const version = tagVersions.get(tagOf(channel)) ?? null;
40508
+ if (!version || !isNewVersion(version)) continue;
40509
+ try {
40510
+ const locked = await db.get(updateLockKey(channel));
40511
+ if (typeof locked === "string" && locked === version) continue;
40512
+ await db.set(updateLockKey(channel), version);
40513
+ } catch {}
40514
+ pending.add(version);
40515
+ }
40516
+ if (pending.size === 0) return true;
40457
40517
  const masters = config.master().filter((id) => id !== "console");
40458
40518
  if (masters.length === 0) return true;
40459
40519
  const botItems = karin.getAllBotList().filter((b) => b.bot.account.name !== "console");
@@ -40473,12 +40533,16 @@ var Handler = async () => {
40473
40533
  const botToImage = /* @__PURE__ */ new Map();
40474
40534
  for (const item of botItems) {
40475
40535
  if (!Array.from(masterToBot.entries()).some(([, b]) => b.account.selfId === item.bot.account.selfId)) continue;
40476
- const img = await getChangelogImage({ bot: item.bot }, {
40477
- localVersion: Root.pluginVersion,
40478
- remoteVersion: remote,
40479
- Tip: true
40480
- });
40481
- if (img && img.length > 0) botToImage.set(item.bot.account.selfId, [segment.text("karin-plugin-kkk 有新的更新!"), ...img]);
40536
+ const elements = [segment.text("karin-plugin-kkk 有新的更新!")];
40537
+ for (const version of pending) {
40538
+ const img = await getChangelogImage({ bot: item.bot }, {
40539
+ localVersion: Root.pluginVersion,
40540
+ remoteVersion: version,
40541
+ Tip: true
40542
+ });
40543
+ if (img && img.length > 0) elements.push(...img);
40544
+ }
40545
+ if (elements.length > 1) botToImage.set(item.bot.account.selfId, elements);
40482
40546
  }
40483
40547
  let storedMsgId;
40484
40548
  for (const owner of masters) {
@@ -40503,7 +40567,7 @@ var handleUpdateHook = wrapWithErrorHandler(async (e) => {
40503
40567
  const msgResult = await e.reply(`${Root.pluginName} 更新成功!\n${result.local} -> ${result.remote}\n开始执行重启......`);
40504
40568
  if (msgResult.messageId) try {
40505
40569
  await db.del(UPDATE_MSGID_KEY);
40506
- await db.del(UPDATE_LOCK_KEY);
40570
+ for (const ch of UPDATE_CHANNELS) await db.del(updateLockKey(ch));
40507
40571
  } catch {}
40508
40572
  await restart(e.selfId, e.contact, msgResult.messageId);
40509
40573
  } else e.reply(`${Root.pluginName} 更新失败: ${result.data ?? "更新执行失败"}`);
@@ -40573,29 +40637,36 @@ var installAndRestart = async (e, version) => {
40573
40637
  const msgResult = await e.reply(`${Root.pluginName} 更新成功!→ ${version}\n开始执行重启......`);
40574
40638
  if (msgResult.messageId) try {
40575
40639
  await db.del(UPDATE_MSGID_KEY);
40576
- await db.del(UPDATE_LOCK_KEY);
40640
+ for (const ch of UPDATE_CHANNELS) await db.del(updateLockKey(ch));
40577
40641
  } catch {}
40578
40642
  await restart(e.selfId, e.contact, msgResult.messageId);
40579
40643
  };
40580
40644
  /** pkg.pr.new 仓库(金丝雀数据源,只跟踪 main 分支构建) */
40581
40645
  var PKG_PR_NEW_REPO = "ikenxuan/karin-plugin-kkk";
40582
- /** 拉取 pkg.pr.new 上 main 分支的最新金丝雀构建(失败返回 null,由调用方降级展示) */
40583
- var fetchLatestCanary = async () => {
40646
+ /** 拉取 pkg.pr.new 的发布历史与 main 分支最新构建(失败返回 null,由调用方降级展示) */
40647
+ var fetchCanaryInfo = async () => {
40584
40648
  try {
40585
40649
  const [owner, repo] = PKG_PR_NEW_REPO.split("/");
40586
40650
  const nodes = (await axios.get(`https://pkg.pr.new/api/repo/commits?owner=${owner}&repo=${repo}`, { timeout: 1e4 })).data?.target?.history?.nodes;
40587
40651
  if (!Array.isArray(nodes)) return null;
40588
- const node = nodes.find((n) => n.branch === "main" && n.statusCheckRollup?.contexts?.nodes?.some((c) => c.packages?.some((pkg) => pkg.installUrl)));
40589
- const pkg = node?.statusCheckRollup?.contexts?.nodes?.flatMap((c) => c.packages ?? []).find((p) => p.installUrl);
40590
- if (!node?.abbreviatedOid || !pkg?.installUrl) return null;
40652
+ const history = nodes.map((n) => ({
40653
+ sha: (n.abbreviatedOid ?? "").slice(0, 7),
40654
+ time: n.authoredDate ? new Date(n.authoredDate).getTime() : 0,
40655
+ message: n.message ?? ""
40656
+ }));
40657
+ const mainNode = nodes.find((n) => n.branch === "main" && n.statusCheckRollup?.contexts?.nodes?.some((c) => c.packages?.some((pkg) => pkg.installUrl)));
40658
+ const pkg = mainNode?.statusCheckRollup?.contexts?.nodes?.flatMap((c) => c.packages ?? []).find((p) => p.installUrl);
40659
+ if (!mainNode?.abbreviatedOid || !pkg?.installUrl) return null;
40591
40660
  return {
40592
- label: "金丝雀",
40593
- tag: "pkg.pr.new · main",
40594
- status: "canary",
40595
- version: node.abbreviatedOid.slice(0, 7),
40596
- installCommand: `pnpm add ${pkg.installUrl} -w`,
40597
- publishedAt: node.authoredDate,
40598
- commitMessage: node.message?.slice(0, 40)
40661
+ channel: {
40662
+ label: "金丝雀",
40663
+ tag: "pkg.pr.new · main",
40664
+ status: "canary",
40665
+ version: mainNode.abbreviatedOid.slice(0, 7),
40666
+ installCommand: `pnpm add ${pkg.installUrl} -w`,
40667
+ publishedAt: mainNode.authoredDate
40668
+ },
40669
+ nodes: history
40599
40670
  };
40600
40671
  } catch {
40601
40672
  return null;
@@ -40608,6 +40679,10 @@ var getUpdateHelpImage = async (e) => {
40608
40679
  if (status) try {
40609
40680
  distTags = JSON.parse(stdout.toString());
40610
40681
  } catch {}
40682
+ const canaryInfo = await fetchCanaryInfo();
40683
+ const installedIsCanary = parseReleaseChannel(Root.pluginVersion) === "Canary";
40684
+ const build = getBuildMetadata();
40685
+ const installedBuildTime = build?.buildTimestamp;
40611
40686
  const channels = [
40612
40687
  {
40613
40688
  label: "正式版",
@@ -40634,6 +40709,15 @@ var getUpdateHelpImage = async (e) => {
40634
40709
  ...def,
40635
40710
  status: "missing"
40636
40711
  };
40712
+ if (installedIsCanary && installedBuildTime !== void 0) {
40713
+ const releaseNode = canaryInfo?.nodes.find((n) => n.message.includes(version));
40714
+ if (releaseNode) return {
40715
+ ...def,
40716
+ status: "ok",
40717
+ version,
40718
+ hasUpdate: releaseNode.time > installedBuildTime
40719
+ };
40720
+ }
40637
40721
  return {
40638
40722
  ...def,
40639
40723
  status: "ok",
@@ -40641,11 +40725,14 @@ var getUpdateHelpImage = async (e) => {
40641
40725
  hasUpdate: isSemverGreater(version, Root.pluginVersion)
40642
40726
  };
40643
40727
  });
40644
- channels.push(await fetchLatestCanary() ?? {
40728
+ const canaryChannel = canaryInfo?.channel ?? {
40645
40729
  label: "金丝雀",
40646
40730
  tag: "pkg.pr.new · main",
40647
40731
  status: "error"
40648
- });
40732
+ };
40733
+ const installedSha = (build?.shortCommitHash ?? "").slice(0, 7);
40734
+ if (installedIsCanary && canaryChannel.status === "canary" && installedSha) canaryChannel.hasUpdate = installedSha !== canaryChannel.version;
40735
+ channels.push(canaryChannel);
40649
40736
  return await Render(e, "other/updateHelp", {
40650
40737
  currentVersion: Root.pluginVersion,
40651
40738
  currentChannel: RELEASE_CHANNEL_LABEL[parseReleaseChannel(Root.pluginVersion)],
@@ -40707,7 +40794,7 @@ var kkkUpdateCommand = karin.command(/^#?kkk更新(?:\s*(\S+))?$/, handleKkkUpda
40707
40794
  });
40708
40795
  var kkkUpdateTest = process.env.NODE_ENV === "development" && karin.command("test", async (_e, next) => {
40709
40796
  await db.del(UPDATE_MSGID_KEY);
40710
- await db.del(UPDATE_LOCK_KEY);
40797
+ for (const ch of UPDATE_CHANNELS) await db.del(updateLockKey(ch));
40711
40798
  await Handler();
40712
40799
  next();
40713
40800
  }, { name: "kkk-更新检测-测试" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karin-plugin-kkk",
3
- "version": "2.45.0-beta.1",
3
+ "version": "2.45.0-beta.4",
4
4
  "description": "Karin 的「抖音」「B 站」视频解析/动态推送插件",
5
5
  "keywords": [
6
6
  "karin",
@@ -57,47 +57,6 @@
57
57
  "access": "public",
58
58
  "registry": "https://registry.npmjs.org"
59
59
  },
60
- "dependencies": {
61
- "@ikenxuan/qrcode": "1.5.0",
62
- "@lobehub/webfont-geist-mono": "^1.0.0",
63
- "@lobehub/webfont-harmony-sans-sc": "^1.0.0",
64
- "emoji-datasource-apple": "16.0.0"
65
- },
66
- "devDependencies": {
67
- "@heroui/react": "3.2.5",
68
- "@icons-pack/react-simple-icons": "^13.15.1",
69
- "@ikenxuan/amagi": "7.0.0-beta.7",
70
- "@karinjs/adapter-qqbot": "3.3.0",
71
- "@karinjs/plugin-adapter-milky": "^1.3.3",
72
- "@karinjs/plugin-basic": "1.4.13",
73
- "@karinjs/plugin-ffmpeg": "^0.1.3",
74
- "@karinjs/plugin-shotium": "^0.3.2",
75
- "@karinjs/template-react": "^0.2.0",
76
- "@kkk/richtext": "0.1.0",
77
- "@outpacelabs/avatars": "^0.6.0",
78
- "@phosphor-icons/react": "^2.1.10",
79
- "@thesvg/icons": "^3.3.7",
80
- "@types/heic-decode": "^2.0.0",
81
- "@types/react": "19.3.0",
82
- "@types/react-dom": "19.3.0",
83
- "clsx": "^2.1.1",
84
- "date-fns": "^4.4.0",
85
- "echarts": "^6.1.0",
86
- "heic-decode": "^2.1.0",
87
- "highlight.js": "^11.12.0",
88
- "jpeg-js": "^0.4.4",
89
- "lucide-react": "^1.46.0",
90
- "react": "^19.3.0",
91
- "react-dom": "^19.3.0",
92
- "react-icons": "^5.7.0",
93
- "react-markdown": "^10.1.0",
94
- "rehype-highlight": "^7.0.2",
95
- "tailwind-merge": "3.7.0",
96
- "vitest": "^5.0.1"
97
- },
98
- "engines": {
99
- "node": ">=18.0.0"
100
- },
101
60
  "karin": {
102
61
  "engines": ">=1.14.0",
103
62
  "main": "src/index.ts",
@@ -118,17 +77,14 @@
118
77
  "web": "./lib/web.config.js",
119
78
  "ts-web": "./src/web.config.ts"
120
79
  },
121
- "timestamp": "2026-10-06T01:55:55.084Z",
122
- "scripts": {
123
- "build": "cross-env NODE_ENV=production vite build",
124
- "build:check": "ktr sync && tsc --noEmit && pnpm build",
125
- "dev": "ktr sync && cross-env EBV_FILE=\"development.env\" node --import tsx src/app.ts --trace-deprecation",
126
- "template": "ktr sync && ktr dev",
127
- "typecheck": "ktr sync && tsc --noEmit",
128
- "gen:emoji": "node scripts/gen-emoji-assets.mjs",
129
- "pub": "npm publish --access public",
130
- "sort": "sort-package-json",
131
- "sync": "curl -X PUT \"https://registry-direct.npmmirror.com/-/package/karin-plugin-kkk/syncs\"",
132
- "watch": "ktr sync && cross-env EBV_FILE=\"development.env\" tsx watch --include \"src/**/*.ts\" --include \"ktr/**/*.ts\" --include \"ktr/**/*.tsx\" src/app.ts --trace-deprecation"
80
+ "dependencies": {
81
+ "@ikenxuan/qrcode": "1.5.0",
82
+ "@lobehub/webfont-geist-mono": "^1.0.0",
83
+ "@lobehub/webfont-harmony-sans-sc": "^1.0.0",
84
+ "emoji-datasource-apple": "16.0.0"
85
+ },
86
+ "timestamp": "2026-10-06T07:32:55.907Z",
87
+ "engines": {
88
+ "node": ">=18.0.0"
133
89
  }
134
90
  }