@chance722/dsh-inbox 0.2.4 → 0.2.5
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.md +8 -0
- package/README.zh.md +8 -0
- package/lib/client.js +9 -10
- package/lib/index.js +9 -5
- package/lib/types/client/messages.d.ts +2 -2
- package/lib/types/host/remote/merge.d.ts +9 -0
- package/lib/types/shared/panel-wire.d.ts +2 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -173,6 +173,14 @@ pnpm test # vitest
|
|
|
173
173
|
|
|
174
174
|
Client-side changes need `pnpm build` and a page reload (dsh's client-hmr reloads it for you); host-side changes need a restart. Details in [docs/help/dev-setup.md](docs/help/dev-setup.md); milestones and acceptance records in the [development bus](docs/feature/dev-bus.md).
|
|
175
175
|
|
|
176
|
+
To switch the profile you actually run between the **published package** and **this checkout** (default profile `web`; set `DSH_PROFILE` for another):
|
|
177
|
+
|
|
178
|
+
```powershell
|
|
179
|
+
pnpm dev:status # which one is in use right now
|
|
180
|
+
pnpm dev:npm # point it at the published version
|
|
181
|
+
pnpm dev:local # point it back here (builds first, then links)
|
|
182
|
+
```
|
|
183
|
+
|
|
176
184
|
## License
|
|
177
185
|
|
|
178
186
|
MIT
|
package/README.zh.md
CHANGED
|
@@ -172,6 +172,14 @@ pnpm test # vitest
|
|
|
172
172
|
|
|
173
173
|
改客户端代码:`pnpm build` 后刷新页面即可(dsh 的 client-hmr 会自己重载);改宿主代码要重启服务。细节见 [docs/help/dev-setup.md](docs/help/dev-setup.md),阶段与验收记录在[开发总线](docs/feature/dev-bus.md)。
|
|
174
174
|
|
|
175
|
+
日常想在**线上发布版**和**本地改动**之间切换(默认 profile 是 `web`,换 profile 加 `DSH_PROFILE`):
|
|
176
|
+
|
|
177
|
+
```powershell
|
|
178
|
+
pnpm dev:status # 现在用的是哪一个:本仓库 / 线上包
|
|
179
|
+
pnpm dev:npm # 切到 npm 上发布的版本(体验发布版)
|
|
180
|
+
pnpm dev:local # 切回当前仓库(会先 pnpm build 再链接)
|
|
181
|
+
```
|
|
182
|
+
|
|
175
183
|
## 许可
|
|
176
184
|
|
|
177
185
|
MIT
|
package/lib/client.js
CHANGED
|
@@ -868,11 +868,14 @@ window.__ModuleLoader__.load({
|
|
|
868
868
|
"sync.pullFailed": "\u62C9\u53D6\u5931\u8D25\uFF1A{reason}",
|
|
869
869
|
// The refresh button's tooltip: counts first, reasons only when something was
|
|
870
870
|
// skipped. The toast carries the two numbers alone.
|
|
871
|
-
|
|
871
|
+
// No number here on purpose: the push considers every row it has, tombstones
|
|
872
|
+
// included, so "26 条已是最新" next to a header saying "共 13 条" is a
|
|
873
|
+
// mismatch the reader has to resolve for themselves (2026-09-21).
|
|
874
|
+
"sync.detailPushedIdle": "\u63A8\u9001 0 \u6761\uFF08\u6CA1\u6709\u65B0\u6539\u52A8\uFF09",
|
|
872
875
|
"sync.detailPushed": "\u63A8\u9001 {records} \u6761 / {attachments} \u4E2A\u9644\u4EF6",
|
|
873
876
|
"sync.detailPulled": "\u62C9\u53D6 {count} \u6761 \xB7 \u4E91\u7AEF {records} \u6761\u8BB0\u5F55 / {files} \u4E2A\u9644\u4EF6",
|
|
874
877
|
"sync.detailAdded": "\uFF08\u5176\u4E2D {count} \u6761\u662F\u65B0\u8BB0\u5F55\uFF09",
|
|
875
|
-
"sync.
|
|
878
|
+
"sync.detailDeleted": "\uFF08\u5176\u4E2D {count} \u6761\u662F\u5220\u9664\uFF0C\u4F1A\u8FDB\u56DE\u6536\u7AD9\uFF09",
|
|
876
879
|
"sync.pullForeignSync": " \xB7 \u26A0\uFE0F \u53E6\u6709 {records} \u6761\u8BB0\u5F55\u5728\u522B\u7684\u540C\u6B65\u76EE\u5F55\uFF1A{roots}",
|
|
877
880
|
"sync.detailForeign": " \xB7 \u26A0\uFE0F \u522B\u7684\u540C\u6B65\u76EE\u5F55\uFF1A{roots}\uFF08{records} \u6761\u8BB0\u5F55\uFF1B\u672C\u673A {ours}\uFF09",
|
|
878
881
|
// The toast: two numbers, nothing else. Everything else about a sync is
|
|
@@ -1137,11 +1140,11 @@ window.__ModuleLoader__.load({
|
|
|
1137
1140
|
"sync.pushPartial": "{head} \xB7 partly failed: {reason}",
|
|
1138
1141
|
"sync.pullNoAddress": "No address configured yet",
|
|
1139
1142
|
"sync.pullFailed": "Pull failed: {reason}",
|
|
1140
|
-
"sync.detailPushedIdle": "pushed 0 (
|
|
1143
|
+
"sync.detailPushedIdle": "pushed 0 (nothing new)",
|
|
1141
1144
|
"sync.detailPushed": "pushed {records} / {attachments} attachments",
|
|
1142
1145
|
"sync.detailPulled": "pulled {count} \xB7 the cloud holds {records} records / {files} attachments",
|
|
1143
1146
|
"sync.detailAdded": " ({count} of them new)",
|
|
1144
|
-
"sync.
|
|
1147
|
+
"sync.detailDeleted": " ({count} of them deletions \u2014 they land in the recycle bin)",
|
|
1145
1148
|
"sync.pullForeignSync": " \xB7 \u26A0\uFE0F {records} records live in another sync directory: {roots}",
|
|
1146
1149
|
"sync.detailForeign": " \xB7 \u26A0\uFE0F another sync directory: {roots} ({records} records; ours is {ours})",
|
|
1147
1150
|
"sync.shortPushed": "pushed {count}",
|
|
@@ -3316,12 +3319,8 @@ window.__ModuleLoader__.load({
|
|
|
3316
3319
|
files: result.remoteAttachments ?? 0
|
|
3317
3320
|
});
|
|
3318
3321
|
const gained = (result.added ?? 0) === 0 ? "" : t("sync.detailAdded", { count: result.added ?? 0 });
|
|
3319
|
-
const
|
|
3320
|
-
|
|
3321
|
-
sync: result.skippedSync ?? 0,
|
|
3322
|
-
older: result.skippedOlder ?? 0
|
|
3323
|
-
});
|
|
3324
|
-
return `${head}${gained}${skipped}${warningsOf(result, true)}`;
|
|
3322
|
+
const deleted = (result.deletions ?? 0) === 0 ? "" : t("sync.detailDeleted", { count: result.deletions ?? 0 });
|
|
3323
|
+
return `${head}${gained}${deleted}${warningsOf(result, true)}`;
|
|
3325
3324
|
}
|
|
3326
3325
|
function EncryptionSettings({ call }) {
|
|
3327
3326
|
const [status, setStatus] = import_react8.default.useState();
|
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { defineTool as defineTool2 } from "@deepseek-ai/dsh-tools";
|
|
|
3
3
|
|
|
4
4
|
// src/shared/constants.ts
|
|
5
5
|
var PACKAGE_NAME = "@chance722/dsh-inbox";
|
|
6
|
-
var VERSION = true ? "0.2.
|
|
6
|
+
var VERSION = true ? "0.2.5" : "0.0.0-dev";
|
|
7
7
|
var DEFAULT_USER_AGENT = "dsh-inbox";
|
|
8
8
|
|
|
9
9
|
// src/shared/vocabulary.ts
|
|
@@ -1404,13 +1404,14 @@ async function mergeOnce(vault, tree, prefix, admit) {
|
|
|
1404
1404
|
const failures = [];
|
|
1405
1405
|
let merged = 0;
|
|
1406
1406
|
let added = 0;
|
|
1407
|
+
let deletions = 0;
|
|
1407
1408
|
let kept = 0;
|
|
1408
1409
|
let attachments = 0;
|
|
1409
1410
|
let objects;
|
|
1410
1411
|
try {
|
|
1411
1412
|
objects = await tree.list(`${prefix}/items/`);
|
|
1412
1413
|
} catch (error) {
|
|
1413
|
-
return { merged: 0, added: 0, kept: 0, attachments: 0, failures: [`\u5217\u8FDC\u7AEF\u540C\u6B65\u76EE\u5F55\u5931\u8D25\uFF1A${reasonOf(error)}`] };
|
|
1414
|
+
return { merged: 0, added: 0, deletions: 0, kept: 0, attachments: 0, failures: [`\u5217\u8FDC\u7AEF\u540C\u6B65\u76EE\u5F55\u5931\u8D25\uFF1A${reasonOf(error)}`] };
|
|
1414
1415
|
}
|
|
1415
1416
|
const wanted = /* @__PURE__ */ new Map();
|
|
1416
1417
|
const bytesAt = /* @__PURE__ */ new Map();
|
|
@@ -1441,6 +1442,7 @@ async function mergeOnce(vault, tree, prefix, admit) {
|
|
|
1441
1442
|
await vault.import(remote);
|
|
1442
1443
|
merged += 1;
|
|
1443
1444
|
if (local === void 0) added += 1;
|
|
1445
|
+
if (remote.deletedAt !== void 0) deletions += 1;
|
|
1444
1446
|
for (const attachmentId of remote.attachmentIds) {
|
|
1445
1447
|
if (vault.getAttachment(attachmentId) === void 0) {
|
|
1446
1448
|
wanted.set(attachmentId, remote.id);
|
|
@@ -1475,7 +1477,7 @@ async function mergeOnce(vault, tree, prefix, admit) {
|
|
|
1475
1477
|
failures.push(`\u9644\u4EF6 ${attachmentId}\uFF1A${reasonOf(error)}`);
|
|
1476
1478
|
}
|
|
1477
1479
|
}
|
|
1478
|
-
return { merged, added, kept, attachments, failures };
|
|
1480
|
+
return { merged, added, deletions, kept, attachments, failures };
|
|
1479
1481
|
}
|
|
1480
1482
|
function extensionOfName(path) {
|
|
1481
1483
|
return /\.([A-Za-z0-9]{1,8})$/.exec(nameOf2(path))?.[1]?.toLowerCase() ?? "bin";
|
|
@@ -1488,7 +1490,7 @@ async function mergeRemote(ctx, vault, attachments, extraRoots = []) {
|
|
|
1488
1490
|
const prefix = syncRoot(settings);
|
|
1489
1491
|
try {
|
|
1490
1492
|
const tree = settings.protocol === "s3" ? await s3Tree(ctx, settings) : await webdavTree(ctx, settings);
|
|
1491
|
-
if (tree === void 0) return { merged: 0, added: 0, kept: 0, attachments: 0, failures: [] };
|
|
1493
|
+
if (tree === void 0) return { merged: 0, added: 0, deletions: 0, kept: 0, attachments: 0, failures: [] };
|
|
1492
1494
|
const admit = admitWith(attachments);
|
|
1493
1495
|
const outcome = await mergeOnce(vault, tree, prefix, admit);
|
|
1494
1496
|
for (const root of extraRoots) {
|
|
@@ -1496,13 +1498,14 @@ async function mergeRemote(ctx, vault, attachments, extraRoots = []) {
|
|
|
1496
1498
|
const extra = await mergeOnce(vault, tree, root, admit);
|
|
1497
1499
|
outcome.merged += extra.merged;
|
|
1498
1500
|
outcome.added += extra.added;
|
|
1501
|
+
outcome.deletions += extra.deletions;
|
|
1499
1502
|
outcome.kept += extra.kept;
|
|
1500
1503
|
outcome.attachments += extra.attachments;
|
|
1501
1504
|
outcome.failures.push(...extra.failures);
|
|
1502
1505
|
}
|
|
1503
1506
|
return outcome;
|
|
1504
1507
|
} catch (error) {
|
|
1505
|
-
return { merged: 0, added: 0, kept: 0, attachments: 0, failures: [reasonOf(error)] };
|
|
1508
|
+
return { merged: 0, added: 0, deletions: 0, kept: 0, attachments: 0, failures: [reasonOf(error)] };
|
|
1506
1509
|
}
|
|
1507
1510
|
}
|
|
1508
1511
|
function admitWith(store) {
|
|
@@ -1609,6 +1612,7 @@ async function withMerge(ctx, vault, attachments, pulled) {
|
|
|
1609
1612
|
...pulled,
|
|
1610
1613
|
merged: outcome.merged,
|
|
1611
1614
|
added: outcome.added,
|
|
1615
|
+
deletions: outcome.deletions,
|
|
1612
1616
|
kept: outcome.kept,
|
|
1613
1617
|
attachments: outcome.attachments,
|
|
1614
1618
|
failed: pulled.failed + outcome.failures.length,
|
|
@@ -186,7 +186,7 @@ export declare const zh: {
|
|
|
186
186
|
'sync.detailPushed': string;
|
|
187
187
|
'sync.detailPulled': string;
|
|
188
188
|
'sync.detailAdded': string;
|
|
189
|
-
'sync.
|
|
189
|
+
'sync.detailDeleted': string;
|
|
190
190
|
'sync.pullForeignSync': string;
|
|
191
191
|
'sync.detailForeign': string;
|
|
192
192
|
'sync.shortPushed': string;
|
|
@@ -455,7 +455,7 @@ export declare const MESSAGES: {
|
|
|
455
455
|
'sync.detailPushed': string;
|
|
456
456
|
'sync.detailPulled': string;
|
|
457
457
|
'sync.detailAdded': string;
|
|
458
|
-
'sync.
|
|
458
|
+
'sync.detailDeleted': string;
|
|
459
459
|
'sync.pullForeignSync': string;
|
|
460
460
|
'sync.detailForeign': string;
|
|
461
461
|
'sync.shortPushed': string;
|
|
@@ -42,6 +42,15 @@ export interface SyncTree {
|
|
|
42
42
|
export interface MergeOutcome {
|
|
43
43
|
/** Records that were new here, or overwritten because the remote was newer. */
|
|
44
44
|
merged: number;
|
|
45
|
+
/**
|
|
46
|
+
* How many of {@link merged} arrived as deletions.
|
|
47
|
+
*
|
|
48
|
+
* A deleted record travels as an ordinary record with deletedAt set, so a
|
|
49
|
+
* merge that brings deletions looks exactly like one that brings updates until
|
|
50
|
+
* somebody opens the recycle bin (measured 2026-09-21: 19 merged — 6 new
|
|
51
|
+
* records and 13 tombstones, and the bin went from empty to thirteen).
|
|
52
|
+
*/
|
|
53
|
+
deletions: number;
|
|
45
54
|
/**
|
|
46
55
|
* How many of {@link merged} were ids this vault did not have at all.
|
|
47
56
|
*
|
|
@@ -175,6 +175,8 @@ export interface PullResult {
|
|
|
175
175
|
merged?: number;
|
|
176
176
|
/** How many of {@link merged} were ids this vault did not have at all. */
|
|
177
177
|
added?: number;
|
|
178
|
+
/** How many of {@link merged} were deletions (they land in the recycle bin). */
|
|
179
|
+
deletions?: number;
|
|
178
180
|
/** Attachment objects the merge had to fetch and admit locally. */
|
|
179
181
|
attachments?: number;
|
|
180
182
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chance722/dsh-inbox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Personal paste inbox for DeepSeek Harness (dsh): capture, classify, browse and retrieve.",
|
|
6
6
|
"keywords": [
|
|
@@ -64,7 +64,10 @@
|
|
|
64
64
|
"build": "node scripts/build.mjs && tsc -p tsconfig.build.json",
|
|
65
65
|
"typecheck": "tsc --noEmit",
|
|
66
66
|
"test": "vitest run",
|
|
67
|
-
"prepublishOnly": "npm run build"
|
|
67
|
+
"prepublishOnly": "npm run build",
|
|
68
|
+
"dev:status": "node scripts/dev.mjs status",
|
|
69
|
+
"dev:local": "node scripts/dev.mjs local",
|
|
70
|
+
"dev:npm": "node scripts/dev.mjs npm"
|
|
68
71
|
},
|
|
69
72
|
"dependencies": {
|
|
70
73
|
"lucide-react": "^1.47.0",
|