prompt-skill-armory 0.9.1 → 0.9.3

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/README.en.md CHANGED
@@ -12,13 +12,13 @@
12
12
  |--|--|--|--|
13
13
  | <img src="docs/preview/preview-6.png" width="220"/> | <img src="docs/preview/preview-7.png" width="220"/> | | |
14
14
 
15
- ![version](https://img.shields.io/badge/version-0.9.1-00ff9c)
15
+ ![version](https://img.shields.io/badge/version-0.9.3-00ff9c)
16
16
  ![license](https://img.shields.io/badge/license-MIT-blue)
17
17
  ![platform](https://img.shields.io/badge/platform-web%20%2B%20desktop-00ff9c)
18
18
  ![CI](https://github.com/Qian-Ning/prompt-skill-armory/actions/workflows/ci.yml/badge.svg)
19
19
 
20
20
  ```
21
- ✦ Armory v0.9.1
21
+ ✦ Armory v0.9.3
22
22
  ┌─────────┬─────────┬─────┬────────────┬──────┬──────┐
23
23
  │ Prompts │ Skills │ MCP │ Wallpaper │ Chat │ Stats│
24
24
  │ global │ merged │ hub │ wallpaper │ sync │ usage│
@@ -111,7 +111,7 @@ Achieved via profile composition (the installer mounts the panel into each profi
111
111
 
112
112
  Every time the panel opens it queries npm for the latest `prompt-skill-armory` version; when a newer version exists a banner appears:
113
113
 
114
- > New version vX.Y.Z (current v0.9.1) [Update now]
114
+ > New version vX.Y.Z (current v0.9.3) [Update now]
115
115
 
116
116
  Clicking "Update now" makes the Host re-run the official installer in place → "Update complete, please restart the client".
117
117
 
package/README.md CHANGED
@@ -12,13 +12,13 @@
12
12
  |--|--|--|--|
13
13
  | <img src="docs/preview/preview-6.png" width="220"/> | <img src="docs/preview/preview-7.png" width="220"/> | | |
14
14
 
15
- ![version](https://img.shields.io/badge/version-0.9.1-00ff9c)
15
+ ![version](https://img.shields.io/badge/version-0.9.3-00ff9c)
16
16
  ![license](https://img.shields.io/badge/license-MIT-blue)
17
17
  ![platform](https://img.shields.io/badge/platform-web%20%2B%20desktop-00ff9c)
18
18
  ![CI](https://github.com/Qian-Ning/prompt-skill-armory/actions/workflows/ci.yml/badge.svg)
19
19
 
20
20
  ```
21
- ✦ Armory v0.9.1
21
+ ✦ Armory v0.9.3
22
22
  ┌─────────┬─────────┬─────┬────────────┬──────┬──────┐
23
23
  │ 提示词 │ 技能 │ MCP │ Wallpaper │ 对话 │ 统计 │
24
24
  │ 全局注入 │ 合并管理 │ 连接 │ 壁纸·特效 │ 导入 │ 用量 │
@@ -114,7 +114,7 @@ pnpm dsh web
114
114
 
115
115
  插件面板每次打开会自动查询 npm 上 `prompt-skill-armory` 的最新版本;发现新版本时顶部显示横幅:
116
116
 
117
- > 有新版本 vX.Y.Z(当前 v0.9.1) [一键更新]
117
+ > 有新版本 vX.Y.Z(当前 v0.9.3) [一键更新]
118
118
 
119
119
  点击「一键更新」→ Host 端运行官方安装器原地重装 → 提示「更新完成,请重启客户端生效」。
120
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prompt-skill-armory",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "One-command installer for Prompt-SkillArmory (prompts + skills manager) into the DeepSeek Harness (web + desktop)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -521,15 +521,16 @@ window.__ModuleLoader__.load({
521
521
  return [];
522
522
  }
523
523
  }
524
- async function exportConversations(ids) {
524
+ async function exportConversations(ids, projectKey) {
525
525
  try {
526
526
  const b = await (await fetch("/api/armory/export", {
527
527
  method: "POST",
528
528
  headers: { "content-type": "application/json" },
529
529
  body: JSON.stringify({
530
530
  sessionIds: ids,
531
- includeAttachments: true,
532
- includeWorkspace: true
531
+ projectKey,
532
+ includeAttachments: false,
533
+ includeWorkspace: false
533
534
  })
534
535
  })).json();
535
536
  return b.ok && b.name !== void 0 ? b.name : null;
@@ -946,7 +947,7 @@ window.__ModuleLoader__.load({
946
947
  });
947
948
  }
948
949
  /** Bump with every release; keep in sync with package.json version + CHANGELOG. */
949
- const ARMORY_VERSION = "0.9.1";
950
+ const ARMORY_VERSION = "0.9.3";
950
951
  /** Compact duration: 45.2s / 2m42s / 1h05m. */
951
952
  function fmtDuration(ms) {
952
953
  const s = ms / 1e3;
@@ -1278,6 +1279,7 @@ window.__ModuleLoader__.load({
1278
1279
  const [chatRows, setChatRows] = (0, react.useState)([]);
1279
1280
  const [chatSelected, setChatSelected] = (0, react.useState)(/* @__PURE__ */ new Set());
1280
1281
  const [chatTarget, setChatTarget] = (0, react.useState)("");
1282
+ const [chatProject, setChatProject] = (0, react.useState)("");
1281
1283
  const [chatBusy, setChatBusy] = (0, react.useState)(false);
1282
1284
  const [chatMsg, setChatMsg] = (0, react.useState)("");
1283
1285
  const [latestVer, setLatestVer] = (0, react.useState)("");
@@ -1311,6 +1313,21 @@ window.__ModuleLoader__.load({
1311
1313
  return n;
1312
1314
  });
1313
1315
  };
1316
+ const chatProjects = (0, react.useMemo)(() => {
1317
+ const byKey = /* @__PURE__ */ new Map();
1318
+ for (const row of chatRows) {
1319
+ const name = row.cwd ? row.cwd.split(/[\\/]/).filter(Boolean).pop() ?? row.projectKey : row.projectKey;
1320
+ if (!byKey.has(row.projectKey)) byKey.set(row.projectKey, name);
1321
+ }
1322
+ return [...byKey.entries()].map(([key, name]) => ({
1323
+ key,
1324
+ name
1325
+ })).sort((a, b) => a.name.localeCompare(b.name));
1326
+ }, [chatRows]);
1327
+ (0, react.useEffect)(() => {
1328
+ if (chatProject === "" && chatProjects.length > 0) setChatProject(chatProjects[0].key);
1329
+ else if (chatProject !== "" && !chatProjects.some((p) => p.key === chatProject)) setChatProject(chatProjects[0]?.key ?? "");
1330
+ }, [chatProjects, chatProject]);
1314
1331
  const doExportChat = async () => {
1315
1332
  setChatBusy(true);
1316
1333
  setChatMsg("");
@@ -1324,6 +1341,24 @@ window.__ModuleLoader__.load({
1324
1341
  setChatMsg(`已导出 ${name}`);
1325
1342
  setChatBusy(false);
1326
1343
  };
1344
+ const doExportProject = async () => {
1345
+ const key = chatProject.trim();
1346
+ if (key === "") {
1347
+ setChatMsg("请先选择项目工作区");
1348
+ return;
1349
+ }
1350
+ setChatBusy(true);
1351
+ setChatMsg("");
1352
+ const name = await exportConversations([], key);
1353
+ if (name === null) {
1354
+ setChatMsg("导出失败");
1355
+ setChatBusy(false);
1356
+ return;
1357
+ }
1358
+ await downloadExport(name);
1359
+ setChatMsg(`已导出整个项目 ${key} → ${name}`);
1360
+ setChatBusy(false);
1361
+ };
1327
1362
  const doUpdate = async () => {
1328
1363
  setUpdating(true);
1329
1364
  setUpdateMsg("");
@@ -1564,6 +1599,31 @@ window.__ModuleLoader__.load({
1564
1599
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1565
1600
  style: CSS.versionBadge,
1566
1601
  children: ["v", ARMORY_VERSION]
1602
+ }),
1603
+ latestVer !== "" && isOlder(ARMORY_VERSION, latestVer) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1604
+ style: {
1605
+ display: "inline-flex",
1606
+ alignItems: "center",
1607
+ gap: "6px",
1608
+ marginLeft: "8px"
1609
+ },
1610
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1611
+ style: {
1612
+ ...CSS.actionBtn,
1613
+ ...CSS.badgeEnabled,
1614
+ fontSize: "11px",
1615
+ padding: "2px 8px"
1616
+ },
1617
+ disabled: updating,
1618
+ onClick: () => void doUpdate(),
1619
+ children: updating ? "更新中…" : `↑ v${latestVer} 更新`
1620
+ }), updateMsg !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1621
+ style: {
1622
+ ...CSS.hint,
1623
+ whiteSpace: "nowrap"
1624
+ },
1625
+ children: updateMsg.slice(0, 60)
1626
+ })]
1567
1627
  })
1568
1628
  ]
1569
1629
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1581,47 +1641,6 @@ window.__ModuleLoader__.load({
1581
1641
  state.message
1582
1642
  ]
1583
1643
  }),
1584
- latestVer !== "" && isOlder(ARMORY_VERSION, latestVer) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1585
- style: {
1586
- display: "flex",
1587
- alignItems: "center",
1588
- gap: "10px",
1589
- padding: "8px 12px",
1590
- marginBottom: "10px",
1591
- borderRadius: "8px",
1592
- border: "1px solid #58a6ff",
1593
- background: "rgba(88,166,255,.08)"
1594
- },
1595
- children: [
1596
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1597
- style: {
1598
- fontSize: "12px",
1599
- color: "#58a6ff",
1600
- flex: 1
1601
- },
1602
- children: [
1603
- "有新版本 v",
1604
- latestVer,
1605
- "(当前 v",
1606
- ARMORY_VERSION,
1607
- ")"
1608
- ]
1609
- }),
1610
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1611
- style: {
1612
- ...CSS.actionBtn,
1613
- ...CSS.badgeEnabled
1614
- },
1615
- disabled: updating,
1616
- onClick: () => void doUpdate(),
1617
- children: updating ? "更新中…" : "一键更新"
1618
- }),
1619
- updateMsg !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1620
- style: { ...CSS.hint },
1621
- children: updateMsg
1622
- })
1623
- ]
1624
- }),
1625
1644
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1626
1645
  style: CSS.tabs,
1627
1646
  children: [
@@ -2484,7 +2503,7 @@ window.__ModuleLoader__.load({
2484
2503
  ...CSS.desc,
2485
2504
  lineHeight: "1.5"
2486
2505
  },
2487
- children: "勾选要导出的对话,打成一个 zip;在另一台机器选该 zip 导入即可还原(含附件与工作区)。"
2506
+ children: "可导出选中的对话,也可下拉选择某个项目工作区整体导出;导入后项目工作区名会尽量与导出端保持一致。"
2488
2507
  }),
2489
2508
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2490
2509
  style: CSS.actions,
@@ -2499,6 +2518,32 @@ window.__ModuleLoader__.load({
2499
2518
  ")"
2500
2519
  ]
2501
2520
  }),
2521
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2522
+ style: CSS.actionBtn,
2523
+ disabled: chatBusy || chatProject === "",
2524
+ onClick: () => void doExportProject(),
2525
+ title: "导出该项目工作区下的全部对话,导入后可保留项目名",
2526
+ children: "导出整个项目"
2527
+ }),
2528
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2529
+ style: CSS.input,
2530
+ value: chatProject,
2531
+ onChange: (e) => setChatProject(e.target.value),
2532
+ disabled: chatBusy || chatProjects.length === 0,
2533
+ title: "选择要整体导出的项目工作区",
2534
+ children: [chatProjects.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2535
+ value: "",
2536
+ children: "(无项目)"
2537
+ }), chatProjects.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
2538
+ value: p.key,
2539
+ children: [
2540
+ p.name,
2541
+ "(",
2542
+ chatRows.filter((r) => r.projectKey === p.key).length,
2543
+ " 个对话)"
2544
+ ]
2545
+ }, p.key))]
2546
+ }),
2502
2547
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2503
2548
  style: {
2504
2549
  ...CSS.actionBtn,