@chance722/dsh-inbox 0.2.2 → 0.2.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/lib/client.js +39 -9
- package/lib/index.js +70 -40
- package/lib/types/client/messages.d.ts +8 -2
- package/lib/types/host/remote/pull.d.ts +3 -1
- package/lib/types/shared/panel-wire.d.ts +45 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -624,6 +624,14 @@ window.__ModuleLoader__.load({
|
|
|
624
624
|
var INBOX_ENDPOINT_TAGS = "tags";
|
|
625
625
|
var INBOX_ENDPOINT_SECRET = "secret";
|
|
626
626
|
var INBOX_ENDPOINT_PUSH = "push";
|
|
627
|
+
var DEFAULT_SYNC_DIRECTORY = "inbox";
|
|
628
|
+
function syncDirectory(raw) {
|
|
629
|
+
const trimmed = (raw ?? "").trim().replace(/^\/+|\/+$/g, "");
|
|
630
|
+
return trimmed.length === 0 ? DEFAULT_SYNC_DIRECTORY : trimmed;
|
|
631
|
+
}
|
|
632
|
+
function syncRootFor(raw) {
|
|
633
|
+
return `${syncDirectory(raw)}/sync`;
|
|
634
|
+
}
|
|
627
635
|
function isSuccess(status) {
|
|
628
636
|
return status >= 200 && status < 300;
|
|
629
637
|
}
|
|
@@ -816,6 +824,7 @@ window.__ModuleLoader__.load({
|
|
|
816
824
|
"settings.save": "\u4FDD\u5B58",
|
|
817
825
|
"settings.probe": "\u81EA\u68C0",
|
|
818
826
|
"settings.details": "\u8BE6\u60C5\uFF08{count} \u6B21\u8BF7\u6C42\uFF09",
|
|
827
|
+
"settings.syncRootNow": "\u540C\u6B65\u6839\uFF1A{root}",
|
|
819
828
|
"settings.noServiceBody": "\u8FD9\u4E2A\u7EC4\u5408\u91CC\u6CA1\u6709\u8BBE\u7F6E\u670D\u52A1\uFF0C\u5730\u5740\u6539\u4E0D\u4E86\u2014\u2014\u4F60\u591A\u534A\u5728\u7528 headless \u5F62\u6001\u5F00\u53D1\u3002",
|
|
820
829
|
"settings.bucketHint": "\u522B\u7684\u8BBE\u5907\u5F80\u8FD9\u91CC\u6254\u4E1C\u897F",
|
|
821
830
|
// Notices (the one-line status under the toolbar).
|
|
@@ -858,7 +867,9 @@ window.__ModuleLoader__.load({
|
|
|
858
867
|
"sync.pullMerged": "\u4ECE\u4E91\u7AEF\u5408\u5E76 {count} \u6761{attachments}",
|
|
859
868
|
"sync.pullAttachments": " / {count} \u4E2A\u9644\u4EF6",
|
|
860
869
|
"sync.pullDone": "\u62C9\u53D6\u5B8C\u6210\uFF1A\u8FDC\u7AEF\u5217\u51FA {listed} \u9879\uFF0C\u65B0\u5165\u5E93 {pulled} \u6761\uFF0C\u8DF3\u8FC7 {skipped} \u6761{tail}",
|
|
861
|
-
"sync.
|
|
870
|
+
"sync.pullSkipWhy": "\uFF08\u81EA\u5DF1\u7684\u540C\u6B65\u5BF9\u8C61 {sync} \u9879\u3001\u6BD4\u4E0A\u6B21\u62C9\u53D6\u66F4\u65E7 {older} \u9879\uFF09",
|
|
871
|
+
"sync.pullForeignSync": " \xB7 \u26A0\uFE0F \u8FD8\u53D1\u73B0\u53E6\u4E00\u5957\u540C\u6B65\u524D\u7F00 {roots}\uFF08\u672C\u673A\u662F {ours}\uFF09\uFF1A\u4E24\u53F0\u673A\u5668\u7684\u300C\u76EE\u5F55\u300D\u8BBE\u7F6E\u4E0D\u4E00\u81F4\uFF0C\u5148\u628A\u4E24\u8FB9\u6539\u6210\u540C\u4E00\u4E2A",
|
|
872
|
+
"sync.pullFailures": " \xB7 \u5931\u8D25 {count}\uFF1A{reason}",
|
|
862
873
|
"sync.thisPage": " \xB7 \u672C\u9875 {count} \u6761",
|
|
863
874
|
"settings.status": "{settings} \xB7 {webdav} \xB7 {s3}",
|
|
864
875
|
"settings.statusOn": "\u8BBE\u7F6E\u670D\u52A1\u5728",
|
|
@@ -1072,6 +1083,7 @@ window.__ModuleLoader__.load({
|
|
|
1072
1083
|
"settings.save": "Save",
|
|
1073
1084
|
"settings.probe": "Test",
|
|
1074
1085
|
"settings.details": "Details ({count} requests)",
|
|
1086
|
+
"settings.syncRootNow": "sync root: {root}",
|
|
1075
1087
|
"settings.noServiceBody": "this composition has no settings service, so the address cannot be changed \u2014 you are most likely running the headless shape.",
|
|
1076
1088
|
"settings.bucketHint": "other devices drop things here",
|
|
1077
1089
|
"notice.listFailed": "Could not read the list: {reason}",
|
|
@@ -1112,7 +1124,9 @@ window.__ModuleLoader__.load({
|
|
|
1112
1124
|
"sync.pullMerged": "Merged {count} from the cloud{attachments}",
|
|
1113
1125
|
"sync.pullAttachments": " / {count} attachment(s)",
|
|
1114
1126
|
"sync.pullDone": "Pull done: {listed} listed remotely, {pulled} filed, {skipped} skipped{tail}",
|
|
1115
|
-
"sync.
|
|
1127
|
+
"sync.pullSkipWhy": " ({sync} of our own sync objects, {older} older than the last pull)",
|
|
1128
|
+
"sync.pullForeignSync": " \xB7 \u26A0\uFE0F another sync prefix exists: {roots} (this machine: {ours}) \u2014 two machines have different directory settings; make them match",
|
|
1129
|
+
"sync.pullFailures": " \xB7 {count} failed: {reason}",
|
|
1116
1130
|
"sync.thisPage": " \xB7 {count} on this page",
|
|
1117
1131
|
"settings.status": "{settings} \xB7 {webdav} \xB7 {s3}",
|
|
1118
1132
|
"settings.statusOn": "settings service present",
|
|
@@ -3217,11 +3231,20 @@ window.__ModuleLoader__.load({
|
|
|
3217
3231
|
attachments: attachments === 0 ? "" : t("sync.pullAttachments", { count: attachments })
|
|
3218
3232
|
});
|
|
3219
3233
|
if (result.pulled === 0 && result.skipped === 0 && result.failed === 0) return syncPart;
|
|
3234
|
+
const skippedWhy = result.skippedSync === void 0 ? "" : t("sync.pullSkipWhy", { sync: result.skippedSync, older: result.skippedOlder ?? 0 });
|
|
3235
|
+
const foreignWhy = result.foreignSyncRoots === void 0 || result.foreignSyncRoots.length === 0 ? "" : t("sync.pullForeignSync", {
|
|
3236
|
+
roots: result.foreignSyncRoots.join("\u3001"),
|
|
3237
|
+
ours: result.syncRoot ?? ""
|
|
3238
|
+
});
|
|
3239
|
+
const failedWhy = result.failed > 0 ? t("sync.pullFailures", {
|
|
3240
|
+
count: result.failed,
|
|
3241
|
+
reason: result.reason ?? t("sync.pushUnknown")
|
|
3242
|
+
}) : "";
|
|
3220
3243
|
return t("sync.pullDone", {
|
|
3221
3244
|
listed: result.listed,
|
|
3222
3245
|
pulled: result.pulled,
|
|
3223
3246
|
skipped: result.skipped,
|
|
3224
|
-
tail: `${syncPart}${
|
|
3247
|
+
tail: `${skippedWhy}${syncPart}${foreignWhy}${failedWhy}`
|
|
3225
3248
|
});
|
|
3226
3249
|
}
|
|
3227
3250
|
function EncryptionSettings({ call }) {
|
|
@@ -3581,12 +3604,19 @@ window.__ModuleLoader__.load({
|
|
|
3581
3604
|
}
|
|
3582
3605
|
)
|
|
3583
3606
|
] }),
|
|
3584
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("
|
|
3585
|
-
t("settings.
|
|
3586
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3607
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
3608
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { opacity: 0.7, minWidth: 64 }, children: t("settings.bucketDir") }),
|
|
3609
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3610
|
+
"input",
|
|
3611
|
+
{
|
|
3612
|
+
value: directory,
|
|
3613
|
+
disabled: busy,
|
|
3614
|
+
onChange: (event) => setDirectory(event.target.value),
|
|
3615
|
+
placeholder: "/inbox",
|
|
3616
|
+
style: { ...inputStyle, flex: 1 }
|
|
3617
|
+
}
|
|
3618
|
+
),
|
|
3619
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { opacity: 0.6 }, children: t("settings.syncRootNow", { root: syncRootFor(directory) }) })
|
|
3590
3620
|
] })
|
|
3591
3621
|
] }),
|
|
3592
3622
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, children: [
|
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.3" : "0.0.0-dev";
|
|
7
7
|
var DEFAULT_USER_AGENT = "dsh-inbox";
|
|
8
8
|
|
|
9
9
|
// src/shared/vocabulary.ts
|
|
@@ -933,6 +933,42 @@ async function readFile(path, deps, absoluteUrl) {
|
|
|
933
933
|
return { bytes, contentType: declared.split(";")[0] ?? "application/octet-stream" };
|
|
934
934
|
}
|
|
935
935
|
|
|
936
|
+
// src/shared/panel-wire.ts
|
|
937
|
+
var INBOX_API_PREFIX = "/api/inbox";
|
|
938
|
+
var INBOX_ENDPOINT_CAPTURE = "capture";
|
|
939
|
+
var INBOX_ENDPOINT_LIST = "list";
|
|
940
|
+
var INBOX_ENDPOINT_DETAIL = "detail";
|
|
941
|
+
var INBOX_ENDPOINT_UPDATE = "update";
|
|
942
|
+
var INBOX_ENDPOINT_DELETE = "delete";
|
|
943
|
+
var INBOX_ENDPOINT_RESTORE = "restore";
|
|
944
|
+
var INBOX_ENDPOINT_PURGE = "purge";
|
|
945
|
+
var INBOX_ENDPOINT_ATTACHMENT = "attachment";
|
|
946
|
+
var INBOX_ENDPOINT_WEBDAV = "webdav";
|
|
947
|
+
var INBOX_ENDPOINT_PULL = "pull";
|
|
948
|
+
var INBOX_ENDPOINT_PROBE = "probe";
|
|
949
|
+
var INBOX_ENDPOINT_UI = "ui";
|
|
950
|
+
var INBOX_ENDPOINT_TAGS = "tags";
|
|
951
|
+
var INBOX_ENDPOINT_SECRET = "secret";
|
|
952
|
+
var INBOX_ENDPOINT_PUSH = "push";
|
|
953
|
+
var DEFAULT_SYNC_DIRECTORY = "inbox";
|
|
954
|
+
function syncDirectory(raw) {
|
|
955
|
+
const trimmed = (raw ?? "").trim().replace(/^\/+|\/+$/g, "");
|
|
956
|
+
return trimmed.length === 0 ? DEFAULT_SYNC_DIRECTORY : trimmed;
|
|
957
|
+
}
|
|
958
|
+
function syncRootFor(raw) {
|
|
959
|
+
return `${syncDirectory(raw)}/sync`;
|
|
960
|
+
}
|
|
961
|
+
var INBOX_IMAGE_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
962
|
+
var LIST_LIMIT = 50;
|
|
963
|
+
var UI_LIST_MODES = ["grid", "compact"];
|
|
964
|
+
var PREVIEW_CHARS = 140;
|
|
965
|
+
var MAX_ATTACHMENTS_PER_SUBMISSION = 20;
|
|
966
|
+
var MAX_NOTE_CHARS = 2e3;
|
|
967
|
+
var MAX_TAGS = 20;
|
|
968
|
+
var MAX_TAG_CHARS = 40;
|
|
969
|
+
var MAX_FILTER_CHARS = 200;
|
|
970
|
+
var MAX_TITLE_CHARS = 300;
|
|
971
|
+
|
|
936
972
|
// src/host/webdav/config.ts
|
|
937
973
|
import z from "@deepseek-ai/schemastery";
|
|
938
974
|
var SETTINGS_NAMESPACE = "dsh-inbox-webdav";
|
|
@@ -1070,36 +1106,6 @@ async function saveWebdav(ctx, vault, base, patch) {
|
|
|
1070
1106
|
|
|
1071
1107
|
// src/host/remote/pull.ts
|
|
1072
1108
|
import { admitEncodedFile, admitEncodedImages } from "@deepseek-ai/dsh-attachment";
|
|
1073
|
-
|
|
1074
|
-
// src/shared/panel-wire.ts
|
|
1075
|
-
var INBOX_API_PREFIX = "/api/inbox";
|
|
1076
|
-
var INBOX_ENDPOINT_CAPTURE = "capture";
|
|
1077
|
-
var INBOX_ENDPOINT_LIST = "list";
|
|
1078
|
-
var INBOX_ENDPOINT_DETAIL = "detail";
|
|
1079
|
-
var INBOX_ENDPOINT_UPDATE = "update";
|
|
1080
|
-
var INBOX_ENDPOINT_DELETE = "delete";
|
|
1081
|
-
var INBOX_ENDPOINT_RESTORE = "restore";
|
|
1082
|
-
var INBOX_ENDPOINT_PURGE = "purge";
|
|
1083
|
-
var INBOX_ENDPOINT_ATTACHMENT = "attachment";
|
|
1084
|
-
var INBOX_ENDPOINT_WEBDAV = "webdav";
|
|
1085
|
-
var INBOX_ENDPOINT_PULL = "pull";
|
|
1086
|
-
var INBOX_ENDPOINT_PROBE = "probe";
|
|
1087
|
-
var INBOX_ENDPOINT_UI = "ui";
|
|
1088
|
-
var INBOX_ENDPOINT_TAGS = "tags";
|
|
1089
|
-
var INBOX_ENDPOINT_SECRET = "secret";
|
|
1090
|
-
var INBOX_ENDPOINT_PUSH = "push";
|
|
1091
|
-
var INBOX_IMAGE_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
1092
|
-
var LIST_LIMIT = 50;
|
|
1093
|
-
var UI_LIST_MODES = ["grid", "compact"];
|
|
1094
|
-
var PREVIEW_CHARS = 140;
|
|
1095
|
-
var MAX_ATTACHMENTS_PER_SUBMISSION = 20;
|
|
1096
|
-
var MAX_NOTE_CHARS = 2e3;
|
|
1097
|
-
var MAX_TAGS = 20;
|
|
1098
|
-
var MAX_TAG_CHARS = 40;
|
|
1099
|
-
var MAX_FILTER_CHARS = 200;
|
|
1100
|
-
var MAX_TITLE_CHARS = 300;
|
|
1101
|
-
|
|
1102
|
-
// src/host/remote/pull.ts
|
|
1103
1109
|
var DEFAULT_DIRECTORY = "/inbox";
|
|
1104
1110
|
var TEXT_TYPES = ["text/", "application/json"];
|
|
1105
1111
|
var TEXT_SUFFIXES = [".txt", ".md", ".url", ".json"];
|
|
@@ -1108,8 +1114,11 @@ function looksTextual(name2, contentType) {
|
|
|
1108
1114
|
if (TEXT_SUFFIXES.some((suffix) => lower.endsWith(suffix))) return true;
|
|
1109
1115
|
return contentType !== void 0 && TEXT_TYPES.some((prefix) => contentType.startsWith(prefix));
|
|
1110
1116
|
}
|
|
1111
|
-
function
|
|
1112
|
-
|
|
1117
|
+
function syncPrefixOf(path) {
|
|
1118
|
+
const parts = path.split("/").filter((part) => part.length > 0);
|
|
1119
|
+
const at = parts.lastIndexOf("sync");
|
|
1120
|
+
if (at === -1) return void 0;
|
|
1121
|
+
return parts.slice(0, at + 1).slice(-2).join("/");
|
|
1113
1122
|
}
|
|
1114
1123
|
function laterOf(current, candidate) {
|
|
1115
1124
|
if (candidate === void 0) return current;
|
|
@@ -1128,7 +1137,7 @@ function isNewer(entry, lastPullAt) {
|
|
|
1128
1137
|
if (Number.isNaN(seen) || Number.isNaN(remote)) return true;
|
|
1129
1138
|
return remote > seen;
|
|
1130
1139
|
}
|
|
1131
|
-
async function ingestFrom(vault, source, attachments) {
|
|
1140
|
+
async function ingestFrom(vault, source, attachments, syncRoot3 = syncRootFor(void 0)) {
|
|
1132
1141
|
const lastPullAt = vault.global.sync.lastPullAt;
|
|
1133
1142
|
let entries;
|
|
1134
1143
|
try {
|
|
@@ -1141,15 +1150,28 @@ async function ingestFrom(vault, source, attachments) {
|
|
|
1141
1150
|
let pulled = 0;
|
|
1142
1151
|
let failed2 = 0;
|
|
1143
1152
|
let skipped = 0;
|
|
1153
|
+
let skippedSync = 0;
|
|
1154
|
+
let skippedOlder = 0;
|
|
1155
|
+
let skippedForeign = 0;
|
|
1156
|
+
const foreignSyncRoots = /* @__PURE__ */ new Set();
|
|
1144
1157
|
let newestSuccess;
|
|
1145
1158
|
const failures = [];
|
|
1146
1159
|
for (const entry of entries) {
|
|
1147
|
-
|
|
1160
|
+
const prefix = syncPrefixOf(entry.path);
|
|
1161
|
+
if (prefix !== void 0 && prefix !== syncRoot3) {
|
|
1162
|
+
skipped += 1;
|
|
1163
|
+
skippedForeign += 1;
|
|
1164
|
+
foreignSyncRoots.add(prefix);
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
if (prefix !== void 0) {
|
|
1148
1168
|
skipped += 1;
|
|
1169
|
+
skippedSync += 1;
|
|
1149
1170
|
continue;
|
|
1150
1171
|
}
|
|
1151
1172
|
if (!isNewer(entry, lastPullAt)) {
|
|
1152
1173
|
skipped += 1;
|
|
1174
|
+
skippedOlder += 1;
|
|
1153
1175
|
continue;
|
|
1154
1176
|
}
|
|
1155
1177
|
const name2 = nameOf(entry.path);
|
|
@@ -1207,6 +1229,11 @@ async function ingestFrom(vault, source, attachments) {
|
|
|
1207
1229
|
pulled,
|
|
1208
1230
|
failed: failed2,
|
|
1209
1231
|
skipped,
|
|
1232
|
+
skippedSync,
|
|
1233
|
+
skippedOlder,
|
|
1234
|
+
skippedForeign,
|
|
1235
|
+
syncRoot: syncRoot3,
|
|
1236
|
+
...foreignSyncRoots.size === 0 ? {} : { foreignSyncRoots: [...foreignSyncRoots] },
|
|
1210
1237
|
listed,
|
|
1211
1238
|
lastPullAt: cursor,
|
|
1212
1239
|
...failures.length === 0 ? {} : { reason: failures.slice(0, 3).join("\uFF1B") }
|
|
@@ -1224,7 +1251,7 @@ async function pullRemote(vault, config, deps) {
|
|
|
1224
1251
|
listed: 0
|
|
1225
1252
|
};
|
|
1226
1253
|
}
|
|
1227
|
-
const directory = config.directory ?? DEFAULT_DIRECTORY
|
|
1254
|
+
const directory = `/${syncDirectory(config.directory ?? DEFAULT_DIRECTORY)}`;
|
|
1228
1255
|
return ingestFrom(
|
|
1229
1256
|
vault,
|
|
1230
1257
|
{
|
|
@@ -1235,7 +1262,9 @@ async function pullRemote(vault, config, deps) {
|
|
|
1235
1262
|
})),
|
|
1236
1263
|
read: async (entry) => readFile(entry.path, deps, entry.path.startsWith("http") ? entry.path : void 0)
|
|
1237
1264
|
},
|
|
1238
|
-
deps.attachments
|
|
1265
|
+
deps.attachments,
|
|
1266
|
+
// WebDAV resolves the sync root from the same directory rule the writer uses.
|
|
1267
|
+
syncRootFor(config.directory)
|
|
1239
1268
|
);
|
|
1240
1269
|
}
|
|
1241
1270
|
async function pullS3(vault, config, prefix, deps) {
|
|
@@ -1258,7 +1287,9 @@ async function pullS3(vault, config, prefix, deps) {
|
|
|
1258
1287
|
})),
|
|
1259
1288
|
read: async (entry) => readObject(config, entry.path, deps)
|
|
1260
1289
|
},
|
|
1261
|
-
deps.attachments
|
|
1290
|
+
deps.attachments,
|
|
1291
|
+
// S3 is handed the prefix by its caller — that prefix *is* the sync root.
|
|
1292
|
+
prefix
|
|
1262
1293
|
);
|
|
1263
1294
|
}
|
|
1264
1295
|
|
|
@@ -1570,8 +1601,7 @@ async function pullDropFolder(ctx, vault, attachments) {
|
|
|
1570
1601
|
|
|
1571
1602
|
// src/host/remote/writer.ts
|
|
1572
1603
|
function syncRoot(settings) {
|
|
1573
|
-
|
|
1574
|
-
return prefix.length === 0 ? "sync" : `${prefix}/sync`;
|
|
1604
|
+
return syncRootFor(settings.directory);
|
|
1575
1605
|
}
|
|
1576
1606
|
async function remoteWriter(ctx) {
|
|
1577
1607
|
const settings = readSettings(ctx);
|
|
@@ -144,6 +144,7 @@ export declare const zh: {
|
|
|
144
144
|
'settings.save': string;
|
|
145
145
|
'settings.probe': string;
|
|
146
146
|
'settings.details': string;
|
|
147
|
+
'settings.syncRootNow': string;
|
|
147
148
|
'settings.noServiceBody': string;
|
|
148
149
|
'settings.bucketHint': string;
|
|
149
150
|
'notice.listFailed': string;
|
|
@@ -184,7 +185,9 @@ export declare const zh: {
|
|
|
184
185
|
'sync.pullMerged': string;
|
|
185
186
|
'sync.pullAttachments': string;
|
|
186
187
|
'sync.pullDone': string;
|
|
187
|
-
'sync.
|
|
188
|
+
'sync.pullSkipWhy': string;
|
|
189
|
+
'sync.pullForeignSync': string;
|
|
190
|
+
'sync.pullFailures': string;
|
|
188
191
|
'sync.thisPage': string;
|
|
189
192
|
'settings.status': string;
|
|
190
193
|
'settings.statusOn': string;
|
|
@@ -401,6 +404,7 @@ export declare const MESSAGES: {
|
|
|
401
404
|
'settings.save': string;
|
|
402
405
|
'settings.probe': string;
|
|
403
406
|
'settings.details': string;
|
|
407
|
+
'settings.syncRootNow': string;
|
|
404
408
|
'settings.noServiceBody': string;
|
|
405
409
|
'settings.bucketHint': string;
|
|
406
410
|
'notice.listFailed': string;
|
|
@@ -441,7 +445,9 @@ export declare const MESSAGES: {
|
|
|
441
445
|
'sync.pullMerged': string;
|
|
442
446
|
'sync.pullAttachments': string;
|
|
443
447
|
'sync.pullDone': string;
|
|
444
|
-
'sync.
|
|
448
|
+
'sync.pullSkipWhy': string;
|
|
449
|
+
'sync.pullForeignSync': string;
|
|
450
|
+
'sync.pullFailures': string;
|
|
445
451
|
'sync.thisPage': string;
|
|
446
452
|
'settings.status': string;
|
|
447
453
|
'settings.statusOn': string;
|
|
@@ -43,7 +43,9 @@ export interface RemoteSource {
|
|
|
43
43
|
* @param attachments - the store that owns pulled bytes.
|
|
44
44
|
* @returns what happened.
|
|
45
45
|
*/
|
|
46
|
-
export declare function ingestFrom(vault: Vault, source: RemoteSource, attachments: AttachmentStore
|
|
46
|
+
export declare function ingestFrom(vault: Vault, source: RemoteSource, attachments: AttachmentStore,
|
|
47
|
+
/** This machine's own sync root; anything else under `sync/` is a stranger. */
|
|
48
|
+
syncRoot?: string): Promise<PullResult>;
|
|
47
49
|
/** What the user configures for WebDAV. */
|
|
48
50
|
export interface WebdavConfig {
|
|
49
51
|
baseUrl: string;
|
|
@@ -123,6 +123,33 @@ export interface WebdavStatus {
|
|
|
123
123
|
credentialsAvailable: boolean;
|
|
124
124
|
}
|
|
125
125
|
/** What one pull did, for the panel and for the log. */
|
|
126
|
+
/** The directory a sync uses when the user never named one. */
|
|
127
|
+
export declare const DEFAULT_SYNC_DIRECTORY = "inbox";
|
|
128
|
+
/**
|
|
129
|
+
* The directory a sync actually uses, decided in one place.
|
|
130
|
+
*
|
|
131
|
+
* `/`, an empty string and "never named one" all mean the default. They used to
|
|
132
|
+
* mean different things depending on which path read them: `syncRoot()` turned a
|
|
133
|
+
* stripped-empty directory into the *bucket root* (`sync/`) while the
|
|
134
|
+
* drop-folder ingest defaulted to `/inbox`, so two machines set up through the
|
|
135
|
+
* same dialog could write to `sync/` and `inbox/sync/` respectively — and the
|
|
136
|
+
* merge, which reads its own prefix, then found nothing and reported nothing new
|
|
137
|
+
* (measured 2026-09-20).
|
|
138
|
+
*
|
|
139
|
+
* @param raw - whatever the settings hold, if anything.
|
|
140
|
+
* @returns the directory without leading or trailing slashes; never empty.
|
|
141
|
+
*/
|
|
142
|
+
export declare function syncDirectory(raw: string | undefined): string;
|
|
143
|
+
/**
|
|
144
|
+
* Where the vault's own objects live: `<directory>/sync`.
|
|
145
|
+
*
|
|
146
|
+
* Shared by the writer, the drop-folder ingest and the display, so "which
|
|
147
|
+
* prefix is mine" has one answer on both sides of the wire.
|
|
148
|
+
*
|
|
149
|
+
* @param raw - the configured directory, if any.
|
|
150
|
+
* @returns the sync root, e.g. `inbox/sync`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function syncRootFor(raw: string | undefined): string;
|
|
126
153
|
export interface PullResult {
|
|
127
154
|
status: 'ok' | 'unconfigured' | 'failed';
|
|
128
155
|
reason?: string;
|
|
@@ -137,6 +164,24 @@ export interface PullResult {
|
|
|
137
164
|
failed: number;
|
|
138
165
|
/** Files the server listed but we skipped as already-seen. */
|
|
139
166
|
skipped: number;
|
|
167
|
+
/**
|
|
168
|
+
* How many of {@link skipped} were the vault's own upload queue (`sync/…`).
|
|
169
|
+
*
|
|
170
|
+
* Optional because the older shape of this result (and every test that builds
|
|
171
|
+
* one by hand) predates the split.
|
|
172
|
+
*/
|
|
173
|
+
skippedSync?: number;
|
|
174
|
+
/** How many of {@link skipped} were older than the last pull's cursor. */
|
|
175
|
+
skippedOlder?: number;
|
|
176
|
+
/**
|
|
177
|
+
* How many of {@link skipped} sat under a `…/sync/` prefix that is **not**
|
|
178
|
+
* ours — another machine syncing under a different directory.
|
|
179
|
+
*/
|
|
180
|
+
skippedForeign?: number;
|
|
181
|
+
/** Those other prefixes, e.g. `['inbox/sync']`; the panel warns about them. */
|
|
182
|
+
foreignSyncRoots?: string[];
|
|
183
|
+
/** This machine's own sync root, so the warning can name both sides. */
|
|
184
|
+
syncRoot?: string;
|
|
140
185
|
/** How many entries the remote listed at all: distinguishes "empty folder"
|
|
141
186
|
* from "everything already ingested". */
|
|
142
187
|
listed: number;
|