dsh-packycode-api 1.4.7 → 1.4.9

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/lib/client.js CHANGED
@@ -57,7 +57,13 @@ window.__ModuleLoader__.load({
57
57
  imagesQuality_high: "高",
58
58
  imagesQuality_xhigh: "超高(xhigh)",
59
59
  imagesQuality_max: "最高(max)",
60
- imagesQualityHint: "2.6 支持额外的 xhigh / max;质量越高,耗时和费用通常越高。网关实际支持情况需用图片 Key 验证。不会自动换型号或降低质量。",
60
+ imagesQualityHint: "GPT Image 2.6 支持额外的 xhigh / max;质量越高,耗时和费用通常越高。MiniMax H3 Image 没有质量档位,按尺寸计费,未指定尺寸时按 2K(约 400 万像素)出图、比例由模型决定。型号列表只显示当前图片 Key 的分组支持的型号。网关实际支持情况需用图片 Key 验证。不会自动换型号或降低质量。",
61
+ imagesModelUnservedMark: "(当前 Key 不支持)",
62
+ imagesModelUnserved: "当前图片 Key 的分组({groups})不支持 {model},用它生图会被网关拒绝。请换一个型号,或添加分组包含它的图片 Key。",
63
+ imagesModelRequired: "需要分组:{required}。",
64
+ imagesModelKeyRejected: "当前图片 Key 被网关拒绝,{model} 和其它图片型号都用不了。请检查这个 Key,或换用另一个图片 Key。",
65
+ imagesModelsHidden: "当前图片 Key 的分组({groups})不支持这些图片型号,已从上面的列表隐藏:{models}。",
66
+ listSeparator: "、",
61
67
  imagesAddKey: "添加图片 Key",
62
68
  imagesKeyPlaceholder: "粘贴专用的图片 API Key",
63
69
  imagesNoKey: "尚未添加图片 Key。添加后可使用图片工具;对话 Key 不会用于图片请求。",
@@ -136,7 +142,7 @@ window.__ModuleLoader__.load({
136
142
  cliPath: "位置",
137
143
  cliRecheck: "重新检测",
138
144
  cliMissing: "未检测到 Claude Code CLI",
139
- cliMissingHint: "cc 分组的 Key 需要它才能使用 Claude 模型(claude-opus-5-5、claude-sonnet-5-5、claude-haiku-5-5)。其它分组和其它模型不受影响。",
145
+ cliMissingHint: "cc 分组的 Key 需要它才能使用 Claude 模型(claude-fable-5-2、claude-opus-5-5、claude-sonnet-5-5、claude-haiku-5-5)。其它分组和其它模型不受影响。",
140
146
  cliConfiguredMissing: "设置里指定的 CLI 路径不存在:{path}",
141
147
  cliBroken: "找到了 CLI,但无法运行",
142
148
  cliInstall: "安装 Claude Code CLI",
@@ -254,7 +260,7 @@ window.__ModuleLoader__.load({
254
260
  reviewOfficialOff: "官方自动审查未开启",
255
261
  reviewEnableHint: "还没有开启:在 DSH 左侧「插件」页找到「自动授权审查」并开启,然后在输入框的权限菜单里选「自动审查」。",
256
262
  reviewModelTitle: "审查模型",
257
- reviewModelJev: "jev-latest",
263
+ reviewModelJev: "jev-1.14.0",
258
264
  reviewModelFlash: "DeepSeek Flash",
259
265
  reviewModelSession: "跟随对话模型",
260
266
  reviewModelJevHint: "TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级。需要 Key 的分组包含 typesafe-officially。",
@@ -266,7 +272,7 @@ window.__ModuleLoader__.load({
266
272
  reviewOutcomeAllowed: "放行",
267
273
  reviewOutcomeDenied: "拒绝",
268
274
  reviewOutcomeFailed: "失败",
269
- reviewMenuNote: "权限菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字;选了 jev-latest 或 DeepSeek Flash 时,实际由所选模型审查。审查失败时,官方会拒绝这次调用,不会执行。"
275
+ reviewMenuNote: "权限菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字;选了 jev-1.14.0 或 DeepSeek Flash 时,实际由所选模型审查。审查失败时,官方会拒绝这次调用,不会执行。"
270
276
  };
271
277
  const en = {
272
278
  nav: "PackyCode",
@@ -298,7 +304,13 @@ window.__ModuleLoader__.load({
298
304
  imagesQuality_high: "High",
299
305
  imagesQuality_xhigh: "Extra high (xhigh)",
300
306
  imagesQuality_max: "Maximum (max)",
301
- imagesQualityHint: "The 2.6 engines also support xhigh / max. Higher quality usually takes longer and costs more. Gateway support needs testing with an image key. Models and quality are never changed automatically.",
307
+ imagesQualityHint: "The GPT Image 2.6 engines also support xhigh / max. Higher quality usually takes longer and costs more. MiniMax H3 Image has no quality levels: it is billed by size and, when no size is given, renders at 2K (about 4 million pixels) in a shape the model picks. The model list shows only what the image key in use is served. Gateway support needs testing with an image key. Models and quality are never changed automatically.",
308
+ imagesModelUnservedMark: " (not served by this key)",
309
+ imagesModelUnserved: "The image key in use is in {groups}, which does not serve {model}: the gateway will refuse images made with it. Pick another model, or add an image key in a group that lists it.",
310
+ imagesModelRequired: " It needs: {required}.",
311
+ imagesModelKeyRejected: "The gateway rejected the image key in use, so {model} and every other image model are unavailable. Check this key, or use another image key.",
312
+ imagesModelsHidden: "The image key in use is in {groups}, which does not serve these image models; they are hidden from the list above: {models}.",
313
+ listSeparator: ", ",
302
314
  imagesAddKey: "Add an image key",
303
315
  imagesKeyPlaceholder: "Paste the dedicated image API key",
304
316
  imagesNoKey: "No image key yet. Add one to enable the image tool. Conversation keys are never used for images.",
@@ -377,7 +389,7 @@ window.__ModuleLoader__.load({
377
389
  cliPath: "Location",
378
390
  cliRecheck: "Check again",
379
391
  cliMissing: "Claude Code CLI not found",
380
- cliMissingHint: "Keys in the cc group need it to use the Claude models (claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5). Other groups and models are unaffected.",
392
+ cliMissingHint: "Keys in the cc group need it to use the Claude models (claude-fable-5-2, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5). Other groups and models are unaffected.",
381
393
  cliConfiguredMissing: "The CLI path set in settings does not exist: {path}",
382
394
  cliBroken: "The CLI was found but could not run",
383
395
  cliInstall: "Install Claude Code CLI",
@@ -487,7 +499,7 @@ window.__ModuleLoader__.load({
487
499
  reviewOfficialOff: "Official auto review is off",
488
500
  reviewEnableHint: "Not on yet: open DSH’s Plugins page in the sidebar, switch on “Auto authorization review”, then pick Auto review in the composer’s permission menu.",
489
501
  reviewModelTitle: "Reviewer",
490
- reviewModelJev: "jev-latest",
502
+ reviewModelJev: "jev-1.14.0",
491
503
  reviewModelFlash: "DeepSeek Flash",
492
504
  reviewModelSession: "Conversation model",
493
505
  reviewModelJevHint: "TypeSafe’s decision classifier: about 0.4 s per review, billed by input only; a denial names only the risk level. Needs a key whose group includes typesafe-officially.",
@@ -499,7 +511,7 @@ window.__ModuleLoader__.load({
499
511
  reviewOutcomeAllowed: "allowed",
500
512
  reviewOutcomeDenied: "denied",
501
513
  reviewOutcomeFailed: "failed",
502
- reviewMenuNote: "The description under Auto review in the permission menu comes from DSH and says the same model reviews; with jev-latest or DeepSeek Flash chosen here, that model reviews. When a review fails, DSH refuses the call instead of running it."
514
+ reviewMenuNote: "The description under Auto review in the permission menu comes from DSH and says the same model reviews; with jev-1.14.0 or DeepSeek Flash chosen here, that model reviews. When a review fails, DSH refuses the call instead of running it."
503
515
  };
504
516
  //#endregion
505
517
  //#region src/client-style.js
@@ -1255,7 +1267,36 @@ window.__ModuleLoader__.load({
1255
1267
  }
1256
1268
  //#endregion
1257
1269
  //#region src/client-images.jsx
1258
- const imageModelLabel = (id) => id.replace("gpt-image-", "GPT Image ").replace("-flare", " Flare").replace("-sunburst", " Sunburst");
1270
+ const imageModelLabel = (id) => id.startsWith("MiniMax-") ? id.replaceAll("-", " ") : id.replace("gpt-image-", "GPT Image ").replace("-flare", " Flare").replace("-sunburst", " Sunburst");
1271
+ /** An image key's groups, as the gateway named them. */
1272
+ function ImageKeyGroups({ group, descriptions, loading, t }) {
1273
+ if (group === void 0) return loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1274
+ className: "pkc-meta",
1275
+ children: t("groupsChecking")
1276
+ }) : null;
1277
+ if (group.rejected === true) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1278
+ className: "pkc-error",
1279
+ children: t("groupsRejected")
1280
+ });
1281
+ const names = Array.isArray(group.groups) ? group.groups : [];
1282
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1283
+ className: "pkc-groups",
1284
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1285
+ className: "pkc-label",
1286
+ children: t("groupsTitle")
1287
+ }), names.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1288
+ className: "pkc-meta",
1289
+ children: group.error === void 0 ? "—" : `${t("groupsUnknown")}: ${group.error}`
1290
+ }) : names.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1291
+ className: "pkc-tag",
1292
+ title: descriptions?.[name] ?? name,
1293
+ children: name
1294
+ }, name))]
1295
+ }), group.stale !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1296
+ className: "pkc-meta",
1297
+ children: t("groupsStale")
1298
+ })] });
1299
+ }
1259
1300
  /** Only projections come back from the host; the password draft is cleared on success. */
1260
1301
  function PackyCodeImagesCard({ call, t }) {
1261
1302
  const [state, setState] = react.useState();
@@ -1269,7 +1310,23 @@ window.__ModuleLoader__.load({
1269
1310
  const [balanceError, setBalanceError] = react.useState();
1270
1311
  const [balanceLoading, setBalanceLoading] = react.useState(true);
1271
1312
  const balanceGeneration = react.useRef(0);
1313
+ const [groups, setGroups] = react.useState();
1314
+ const [groupsLoading, setGroupsLoading] = react.useState(true);
1315
+ const groupsGeneration = react.useRef(0);
1272
1316
  const mounted = react.useRef(false);
1317
+ const readGroups = async (force = false) => {
1318
+ if (!mounted.current) return;
1319
+ const generation = ++groupsGeneration.current;
1320
+ setGroupsLoading(true);
1321
+ try {
1322
+ const value = await call("images/groups", { force });
1323
+ if (mounted.current && groupsGeneration.current === generation) setGroups(value);
1324
+ } catch {
1325
+ if (mounted.current && groupsGeneration.current === generation) setGroups(void 0);
1326
+ } finally {
1327
+ if (mounted.current && groupsGeneration.current === generation) setGroupsLoading(false);
1328
+ }
1329
+ };
1273
1330
  const readBalance = async (force = false) => {
1274
1331
  if (!mounted.current) return;
1275
1332
  const generation = ++balanceGeneration.current;
@@ -1292,12 +1349,14 @@ window.__ModuleLoader__.load({
1292
1349
  if (mounted.current) setError(t("imagesLoadFailed"));
1293
1350
  });
1294
1351
  readBalance();
1352
+ readGroups();
1295
1353
  const timer = window.setInterval(() => {
1296
1354
  readBalance();
1297
1355
  }, 6e4);
1298
1356
  return () => {
1299
1357
  mounted.current = false;
1300
1358
  balanceGeneration.current += 1;
1359
+ groupsGeneration.current += 1;
1301
1360
  window.clearInterval(timer);
1302
1361
  };
1303
1362
  }, [call, t]);
@@ -1310,6 +1369,7 @@ window.__ModuleLoader__.load({
1310
1369
  if (mounted.current && endpoint.startsWith("images/keys/")) {
1311
1370
  setBalance(void 0);
1312
1371
  readBalance(true);
1372
+ readGroups(endpoint === "images/keys/add" || endpoint === "images/keys/remove");
1313
1373
  }
1314
1374
  window.dispatchEvent(new Event("packycode-images-updated"));
1315
1375
  return true;
@@ -1327,6 +1387,13 @@ window.__ModuleLoader__.load({
1327
1387
  const disabled = busy || state?.writable !== true;
1328
1388
  const models = state?.models ?? [];
1329
1389
  const qualities = models.find((model) => model.id === state?.imageModel)?.qualities ?? [];
1390
+ const activeGroup = groups?.keys?.find((entry) => entry.id === (state?.keys ?? []).find((key) => key.active)?.id);
1391
+ const unserved = (id) => activeGroup?.coverage?.[id] === false;
1392
+ const groupNames = (activeGroup?.groups ?? []).join(" / ") || "—";
1393
+ const hidden = models.filter((model) => unserved(model.id) && model.id !== state?.imageModel);
1394
+ const offered = models.filter((model) => !hidden.includes(model));
1395
+ const savedUnserved = state !== void 0 && unserved(state.imageModel);
1396
+ const required = groups?.requirements?.[state?.imageModel] ?? [];
1330
1397
  const rows = (state?.keys ?? []).map((entry) => balance?.keys?.find((row) => row.id === entry.id) ?? { id: entry.id });
1331
1398
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1332
1399
  className: "pkc-card",
@@ -1344,6 +1411,7 @@ window.__ModuleLoader__.load({
1344
1411
  disabled: busy || balanceLoading,
1345
1412
  onClick: () => {
1346
1413
  readBalance(true);
1414
+ readGroups(true);
1347
1415
  },
1348
1416
  children: balanceLoading ? t("refreshing") : t("refresh")
1349
1417
  })
@@ -1390,12 +1458,26 @@ window.__ModuleLoader__.load({
1390
1458
  imageQuality: "auto"
1391
1459
  });
1392
1460
  },
1393
- children: models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1461
+ children: offered.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1394
1462
  value: model.id,
1395
- children: imageModelLabel(model.id)
1463
+ children: `${imageModelLabel(model.id)}${unserved(model.id) ? t("imagesModelUnservedMark") : ""}`
1396
1464
  }, model.id))
1397
1465
  })]
1398
1466
  }),
1467
+ savedUnserved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1468
+ className: "pkc-warn",
1469
+ children: `${fill(t(activeGroup.rejected === true ? "imagesModelKeyRejected" : "imagesModelUnserved"), {
1470
+ model: imageModelLabel(state.imageModel),
1471
+ groups: groupNames
1472
+ })}${activeGroup.rejected !== true && required.length > 0 ? fill(t("imagesModelRequired"), { required: required.join(" / ") }) : ""}`
1473
+ }),
1474
+ hidden.length > 0 && activeGroup.rejected !== true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1475
+ className: "pkc-note",
1476
+ children: fill(t("imagesModelsHidden"), {
1477
+ groups: groupNames,
1478
+ models: hidden.map((model) => imageModelLabel(model.id)).join(t("listSeparator"))
1479
+ })
1480
+ }),
1399
1481
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1400
1482
  className: "pkc-setting",
1401
1483
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -1426,58 +1508,67 @@ window.__ModuleLoader__.load({
1426
1508
  className: "pkc-list",
1427
1509
  children: (state.keys ?? []).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1428
1510
  className: "pkc-row",
1429
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1430
- className: "pkc-row-top",
1431
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1432
- className: "pkc-row-name",
1433
- children: [rename.renaming?.id === entry.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KeyRenameForm, {
1434
- rename,
1435
- busy,
1436
- t
1437
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1438
- className: "pkc-name",
1439
- children: entry.label
1440
- }), entry.active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1441
- className: "pkc-chip",
1442
- "data-tone": "success",
1443
- children: t("keyActive")
1511
+ children: [
1512
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1513
+ className: "pkc-row-top",
1514
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1515
+ className: "pkc-row-name",
1516
+ children: [rename.renaming?.id === entry.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KeyRenameForm, {
1517
+ rename,
1518
+ busy,
1519
+ t
1520
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1521
+ className: "pkc-name",
1522
+ children: entry.label
1523
+ }), entry.active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1524
+ className: "pkc-chip",
1525
+ "data-tone": "success",
1526
+ children: t("keyActive")
1527
+ })]
1528
+ }), rename.renaming?.id !== entry.id && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1529
+ className: "pkc-actions",
1530
+ children: [
1531
+ !entry.active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1532
+ className: "pkc-btn",
1533
+ type: "button",
1534
+ disabled: busy,
1535
+ onClick: () => {
1536
+ mutate("images/keys/select", { id: entry.id });
1537
+ },
1538
+ children: t("keyUse")
1539
+ }),
1540
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1541
+ className: "pkc-btn",
1542
+ "data-variant": "ghost",
1543
+ type: "button",
1544
+ disabled: busy,
1545
+ onClick: () => rename.start(entry),
1546
+ children: t("keyRename")
1547
+ }),
1548
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1549
+ className: "pkc-btn",
1550
+ "data-variant": "danger",
1551
+ type: "button",
1552
+ disabled: busy,
1553
+ onClick: () => {
1554
+ mutate("images/keys/remove", { id: entry.id });
1555
+ },
1556
+ children: t("keyRemove")
1557
+ })
1558
+ ]
1444
1559
  })]
1445
- }), rename.renaming?.id !== entry.id && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1446
- className: "pkc-actions",
1447
- children: [
1448
- !entry.active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1449
- className: "pkc-btn",
1450
- type: "button",
1451
- disabled: busy,
1452
- onClick: () => {
1453
- mutate("images/keys/select", { id: entry.id });
1454
- },
1455
- children: t("keyUse")
1456
- }),
1457
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1458
- className: "pkc-btn",
1459
- "data-variant": "ghost",
1460
- type: "button",
1461
- disabled: busy,
1462
- onClick: () => rename.start(entry),
1463
- children: t("keyRename")
1464
- }),
1465
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1466
- className: "pkc-btn",
1467
- "data-variant": "danger",
1468
- type: "button",
1469
- disabled: busy,
1470
- onClick: () => {
1471
- mutate("images/keys/remove", { id: entry.id });
1472
- },
1473
- children: t("keyRemove")
1474
- })
1475
- ]
1476
- })]
1477
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KeyBalance, {
1478
- row: rows.find((row) => row.id === entry.id),
1479
- t
1480
- })]
1560
+ }),
1561
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImageKeyGroups, {
1562
+ group: groups?.keys?.find((group) => group.id === entry.id),
1563
+ descriptions: groups?.descriptions,
1564
+ loading: groupsLoading,
1565
+ t
1566
+ }),
1567
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KeyBalance, {
1568
+ row: rows.find((row) => row.id === entry.id),
1569
+ t
1570
+ })
1571
+ ]
1481
1572
  }, entry.id))
1482
1573
  }),
1483
1574
  (state.keys ?? []).length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -1937,6 +2028,7 @@ window.__ModuleLoader__.load({
1937
2028
  /** The auto review counts are re-read this often while the page is open. */
1938
2029
  const REVIEW_POLL_MS = 5e3;
1939
2030
  const CLAUDE_MODELS = [
2031
+ "claude-fable-5-2",
1940
2032
  "claude-opus-5-5",
1941
2033
  "claude-sonnet-5-5",
1942
2034
  "claude-haiku-5-5"
@@ -1962,11 +2054,12 @@ window.__ModuleLoader__.load({
1962
2054
  ["Hunyuan", ["hy4"]],
1963
2055
  ["Gemini", ["gemini-4-argon", "gemini-3.8-flash"]],
1964
2056
  ["Claude", [
2057
+ "claude-fable-5-2",
1965
2058
  "claude-opus-5-5",
1966
2059
  "claude-sonnet-5-5",
1967
2060
  "claude-haiku-5-5"
1968
2061
  ]],
1969
- ["Jev", ["jev-latest"]]
2062
+ ["Jev", ["jev-1.14.0"]]
1970
2063
  ];
1971
2064
  /**
1972
2065
  * The one way this bundle talks to the host. The transport drops an
@@ -2652,12 +2745,12 @@ window.__ModuleLoader__.load({
2652
2745
  failed: "reviewOutcomeFailed"
2653
2746
  };
2654
2747
  const REVIEW_LABELS = {
2655
- "jev-latest": "reviewModelJev",
2748
+ "jev-1.14.0": "reviewModelJev",
2656
2749
  "deepseek-flash": "reviewModelFlash",
2657
2750
  session: "reviewModelSession"
2658
2751
  };
2659
2752
  const REVIEW_HINTS = {
2660
- "jev-latest": "reviewModelJevHint",
2753
+ "jev-1.14.0": "reviewModelJevHint",
2661
2754
  "deepseek-flash": "reviewModelFlashHint",
2662
2755
  session: "reviewModelSessionHint"
2663
2756
  };