threadnote 0.7.1 → 0.7.2
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/dist/mcp_server.cjs +58 -25
- package/dist/threadnote.cjs +76 -31
- package/package.json +1 -1
package/dist/mcp_server.cjs
CHANGED
|
@@ -34108,10 +34108,8 @@ async function runShareSyncQuiet(config2, state, options) {
|
|
|
34108
34108
|
const git = await requiredExecutable("git");
|
|
34109
34109
|
const worktree = team.config.worktree;
|
|
34110
34110
|
const pendingChanges = state.pendingReindexes.get(team.name);
|
|
34111
|
-
if (pendingChanges) {
|
|
34112
|
-
await
|
|
34113
|
-
state.pendingReindexes.delete(team.name);
|
|
34114
|
-
await writePendingReindexes(config2, state);
|
|
34111
|
+
if (pendingChanges && pendingChanges.length > 0) {
|
|
34112
|
+
await applyAndPersistChanges(config2, team.config, state, pendingChanges, { quiet: true });
|
|
34115
34113
|
}
|
|
34116
34114
|
if (await hasUncommittedChanges(worktree)) {
|
|
34117
34115
|
return `Shared team "${team.name}" has uncommitted changes; skipped automatic sync. Run \`threadnote share sync --team ${team.name}\` to publish or resolve them.`;
|
|
@@ -34139,11 +34137,9 @@ async function runShareSyncQuiet(config2, state, options) {
|
|
|
34139
34137
|
if (beforeRev && afterRev && beforeRev !== afterRev) {
|
|
34140
34138
|
const changes = await listChangedFiles(worktree, beforeRev, afterRev);
|
|
34141
34139
|
if (changes.length > 0) {
|
|
34142
|
-
state.pendingReindexes.
|
|
34143
|
-
|
|
34144
|
-
await
|
|
34145
|
-
state.pendingReindexes.delete(team.name);
|
|
34146
|
-
await writePendingReindexes(config2, state);
|
|
34140
|
+
const stillPending = state.pendingReindexes.get(team.name) ?? [];
|
|
34141
|
+
const combined = mergeChanges(stillPending, changes);
|
|
34142
|
+
await applyAndPersistChanges(config2, team.config, state, combined, { quiet: true });
|
|
34147
34143
|
}
|
|
34148
34144
|
}
|
|
34149
34145
|
return void 0;
|
|
@@ -34339,8 +34335,9 @@ async function writeMemoryFile(config2, ov, uri, content, initialMode, dryRun, o
|
|
|
34339
34335
|
await (0, import_promises3.rm)(stagingDir, { force: true, recursive: true });
|
|
34340
34336
|
}
|
|
34341
34337
|
}
|
|
34338
|
+
var BUSY_RETRY_BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 3e4];
|
|
34342
34339
|
async function writeOvFileWithRetry(config2, ov, uri, fromFile, initialMode, options = {}) {
|
|
34343
|
-
const maxAttempts =
|
|
34340
|
+
const maxAttempts = BUSY_RETRY_BACKOFF_MS.length + 1;
|
|
34344
34341
|
const existedBeforeWrite = await vikingResourceExists(ov, config2, uri);
|
|
34345
34342
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
34346
34343
|
const existsNow = attempt === 0 ? existedBeforeWrite : await vikingResourceExists(ov, config2, uri);
|
|
@@ -34384,6 +34381,7 @@ async function writeOvFileWithRetry(config2, ov, uri, fromFile, initialMode, opt
|
|
|
34384
34381
|
}
|
|
34385
34382
|
if (isResourceBusyFailure(result.stderr, result.stdout)) {
|
|
34386
34383
|
await waitForOvQueue(ov, config2, options);
|
|
34384
|
+
await sleep(BUSY_RETRY_BACKOFF_MS[attempt] ?? 3e4);
|
|
34387
34385
|
} else {
|
|
34388
34386
|
await sleep(1e3 * (attempt + 1));
|
|
34389
34387
|
}
|
|
@@ -34461,7 +34459,7 @@ async function removeMemoryUri(config2, ov, uri, dryRun, options = {}) {
|
|
|
34461
34459
|
}
|
|
34462
34460
|
return;
|
|
34463
34461
|
}
|
|
34464
|
-
const maxAttempts =
|
|
34462
|
+
const maxAttempts = BUSY_RETRY_BACKOFF_MS.length + 1;
|
|
34465
34463
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
34466
34464
|
const result = await runCommand(ov, args, { allowFailure: true });
|
|
34467
34465
|
if (result.exitCode === 0) {
|
|
@@ -34475,6 +34473,7 @@ async function removeMemoryUri(config2, ov, uri, dryRun, options = {}) {
|
|
|
34475
34473
|
}
|
|
34476
34474
|
if (isResourceBusyFailure(result.stderr, result.stdout)) {
|
|
34477
34475
|
await waitForOvQueue(ov, config2, options);
|
|
34476
|
+
await sleep(BUSY_RETRY_BACKOFF_MS[attempt] ?? 3e4);
|
|
34478
34477
|
} else {
|
|
34479
34478
|
await sleep(1e3 * (attempt + 1));
|
|
34480
34479
|
}
|
|
@@ -34531,6 +34530,7 @@ async function listChangedFiles(worktree, beforeRev, afterRev) {
|
|
|
34531
34530
|
}
|
|
34532
34531
|
async function applyChangesToOpenViking(config2, team, changes, options = {}) {
|
|
34533
34532
|
const ov = await openVikingCliForMode(false);
|
|
34533
|
+
const failed = [];
|
|
34534
34534
|
for (const change of changes) {
|
|
34535
34535
|
if (!change.relativePath.endsWith(".md")) {
|
|
34536
34536
|
continue;
|
|
@@ -34540,24 +34540,57 @@ async function applyChangesToOpenViking(config2, team, changes, options = {}) {
|
|
|
34540
34540
|
continue;
|
|
34541
34541
|
}
|
|
34542
34542
|
const uri = workfileToVikingUri(config2, team, change.path);
|
|
34543
|
-
|
|
34544
|
-
|
|
34545
|
-
|
|
34546
|
-
|
|
34547
|
-
|
|
34548
|
-
|
|
34549
|
-
|
|
34550
|
-
|
|
34551
|
-
|
|
34552
|
-
|
|
34543
|
+
try {
|
|
34544
|
+
if (change.status === "removed") {
|
|
34545
|
+
await removeMemoryUri(config2, ov, uri, false, options);
|
|
34546
|
+
continue;
|
|
34547
|
+
}
|
|
34548
|
+
if (!await isFile(change.path)) {
|
|
34549
|
+
continue;
|
|
34550
|
+
}
|
|
34551
|
+
const ovHasResource = await vikingResourceExists(ov, config2, uri);
|
|
34552
|
+
if (ovHasResource) {
|
|
34553
|
+
const reason = change.status === "modified" ? "overwriting local with upstream (local edits to the shared subtree are not preserved across sync)" : "aligning OV to upstream (resource pre-existed in OV, likely from an earlier local publish or sync)";
|
|
34554
|
+
if (options.quiet !== true) {
|
|
34555
|
+
console.warn(`share sync: ${uri}: ${reason}.`);
|
|
34556
|
+
}
|
|
34557
|
+
}
|
|
34558
|
+
await ensureSharedDirectoryChain(config2, ov, uri, false, options);
|
|
34559
|
+
const writeMode = ovHasResource ? "replace" : "create";
|
|
34560
|
+
await ingestSingleFile(ov, config2, uri, change.path, writeMode, options);
|
|
34561
|
+
} catch (err) {
|
|
34562
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34553
34563
|
if (options.quiet !== true) {
|
|
34554
|
-
console.warn(`share sync: ${uri}: ${
|
|
34564
|
+
console.warn(`share sync: ${uri}: ingest failed \u2014 will retry on the next sync. ${message}`);
|
|
34555
34565
|
}
|
|
34566
|
+
failed.push(change);
|
|
34567
|
+
}
|
|
34568
|
+
}
|
|
34569
|
+
return { failed };
|
|
34570
|
+
}
|
|
34571
|
+
function mergeChanges(...lists) {
|
|
34572
|
+
const map3 = /* @__PURE__ */ new Map();
|
|
34573
|
+
for (const list of lists) {
|
|
34574
|
+
for (const change of list) {
|
|
34575
|
+
map3.set(change.relativePath, change);
|
|
34556
34576
|
}
|
|
34557
|
-
await ensureSharedDirectoryChain(config2, ov, uri, false, options);
|
|
34558
|
-
const writeMode = ovHasResource ? "replace" : "create";
|
|
34559
|
-
await ingestSingleFile(ov, config2, uri, change.path, writeMode, options);
|
|
34560
34577
|
}
|
|
34578
|
+
return [...map3.values()];
|
|
34579
|
+
}
|
|
34580
|
+
async function applyAndPersistChanges(config2, team, state, changes, options = {}) {
|
|
34581
|
+
if (changes.length === 0) {
|
|
34582
|
+
return { failed: [] };
|
|
34583
|
+
}
|
|
34584
|
+
state.pendingReindexes.set(team.name, changes);
|
|
34585
|
+
await writePendingReindexes(config2, state);
|
|
34586
|
+
const result = await applyChangesToOpenViking(config2, team, changes, options);
|
|
34587
|
+
if (result.failed.length > 0) {
|
|
34588
|
+
state.pendingReindexes.set(team.name, result.failed);
|
|
34589
|
+
} else {
|
|
34590
|
+
state.pendingReindexes.delete(team.name);
|
|
34591
|
+
}
|
|
34592
|
+
await writePendingReindexes(config2, state);
|
|
34593
|
+
return result;
|
|
34561
34594
|
}
|
|
34562
34595
|
|
|
34563
34596
|
// src/mcp_server.ts
|
package/dist/threadnote.cjs
CHANGED
|
@@ -7583,12 +7583,24 @@ Resolve the conflicts in-place, run \`git -C ${worktree} rebase --continue\` (or
|
|
|
7583
7583
|
);
|
|
7584
7584
|
}
|
|
7585
7585
|
const afterRev = await gitOutput(worktree, ["rev-parse", "HEAD"], dryRun);
|
|
7586
|
-
if (!dryRun
|
|
7587
|
-
const
|
|
7588
|
-
await
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7586
|
+
if (!dryRun) {
|
|
7587
|
+
const state = autoShareState(config);
|
|
7588
|
+
await loadPendingReindexes(config, state);
|
|
7589
|
+
const previouslyPending = state.pendingReindexes.get(team.name) ?? [];
|
|
7590
|
+
const newChanges = beforeRev && afterRev && beforeRev !== afterRev ? await listChangedFiles(worktree, beforeRev, afterRev) : [];
|
|
7591
|
+
const combined = mergeChanges(previouslyPending, newChanges);
|
|
7592
|
+
if (combined.length === 0) {
|
|
7593
|
+
console.log("No upstream changes to reindex.");
|
|
7594
|
+
} else {
|
|
7595
|
+
const result = await applyAndPersistChanges(config, team.config, state, combined);
|
|
7596
|
+
const succeeded = combined.length - result.failed.length;
|
|
7597
|
+
console.log(`Reindexed ${succeeded} file change(s) into OpenViking.`);
|
|
7598
|
+
if (result.failed.length > 0) {
|
|
7599
|
+
console.warn(
|
|
7600
|
+
`share sync: ${result.failed.length} file(s) could not be ingested on this run; they are persisted and will be retried on the next sync or agent recall/read.`
|
|
7601
|
+
);
|
|
7602
|
+
}
|
|
7603
|
+
}
|
|
7592
7604
|
}
|
|
7593
7605
|
if (options.push !== false) {
|
|
7594
7606
|
await maybeRun(dryRun, git, ["-C", worktree, "push", DEFAULT_GIT_REMOTE_NAME], { allowFailure: true });
|
|
@@ -7599,10 +7611,8 @@ async function runShareSyncQuiet(config, state, options) {
|
|
|
7599
7611
|
const git = await requiredExecutable("git");
|
|
7600
7612
|
const worktree = team.config.worktree;
|
|
7601
7613
|
const pendingChanges = state.pendingReindexes.get(team.name);
|
|
7602
|
-
if (pendingChanges) {
|
|
7603
|
-
await
|
|
7604
|
-
state.pendingReindexes.delete(team.name);
|
|
7605
|
-
await writePendingReindexes(config, state);
|
|
7614
|
+
if (pendingChanges && pendingChanges.length > 0) {
|
|
7615
|
+
await applyAndPersistChanges(config, team.config, state, pendingChanges, { quiet: true });
|
|
7606
7616
|
}
|
|
7607
7617
|
if (await hasUncommittedChanges(worktree)) {
|
|
7608
7618
|
return `Shared team "${team.name}" has uncommitted changes; skipped automatic sync. Run \`threadnote share sync --team ${team.name}\` to publish or resolve them.`;
|
|
@@ -7630,11 +7640,9 @@ async function runShareSyncQuiet(config, state, options) {
|
|
|
7630
7640
|
if (beforeRev && afterRev && beforeRev !== afterRev) {
|
|
7631
7641
|
const changes = await listChangedFiles(worktree, beforeRev, afterRev);
|
|
7632
7642
|
if (changes.length > 0) {
|
|
7633
|
-
state.pendingReindexes.
|
|
7634
|
-
|
|
7635
|
-
await
|
|
7636
|
-
state.pendingReindexes.delete(team.name);
|
|
7637
|
-
await writePendingReindexes(config, state);
|
|
7643
|
+
const stillPending = state.pendingReindexes.get(team.name) ?? [];
|
|
7644
|
+
const combined = mergeChanges(stillPending, changes);
|
|
7645
|
+
await applyAndPersistChanges(config, team.config, state, combined, { quiet: true });
|
|
7638
7646
|
}
|
|
7639
7647
|
}
|
|
7640
7648
|
return void 0;
|
|
@@ -8074,8 +8082,9 @@ async function writeMemoryFile(config, ov, uri, content, initialMode, dryRun, op
|
|
|
8074
8082
|
await (0, import_promises4.rm)(stagingDir, { force: true, recursive: true });
|
|
8075
8083
|
}
|
|
8076
8084
|
}
|
|
8085
|
+
var BUSY_RETRY_BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 3e4];
|
|
8077
8086
|
async function writeOvFileWithRetry(config, ov, uri, fromFile, initialMode, options = {}) {
|
|
8078
|
-
const maxAttempts =
|
|
8087
|
+
const maxAttempts = BUSY_RETRY_BACKOFF_MS.length + 1;
|
|
8079
8088
|
const existedBeforeWrite = await vikingResourceExists(ov, config, uri);
|
|
8080
8089
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
8081
8090
|
const existsNow = attempt === 0 ? existedBeforeWrite : await vikingResourceExists(ov, config, uri);
|
|
@@ -8119,6 +8128,7 @@ async function writeOvFileWithRetry(config, ov, uri, fromFile, initialMode, opti
|
|
|
8119
8128
|
}
|
|
8120
8129
|
if (isResourceBusyFailure(result.stderr, result.stdout)) {
|
|
8121
8130
|
await waitForOvQueue(ov, config, options);
|
|
8131
|
+
await sleep(BUSY_RETRY_BACKOFF_MS[attempt] ?? 3e4);
|
|
8122
8132
|
} else {
|
|
8123
8133
|
await sleep(1e3 * (attempt + 1));
|
|
8124
8134
|
}
|
|
@@ -8196,7 +8206,7 @@ async function removeMemoryUri(config, ov, uri, dryRun, options = {}) {
|
|
|
8196
8206
|
}
|
|
8197
8207
|
return;
|
|
8198
8208
|
}
|
|
8199
|
-
const maxAttempts =
|
|
8209
|
+
const maxAttempts = BUSY_RETRY_BACKOFF_MS.length + 1;
|
|
8200
8210
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
8201
8211
|
const result = await runCommand(ov, args, { allowFailure: true });
|
|
8202
8212
|
if (result.exitCode === 0) {
|
|
@@ -8210,6 +8220,7 @@ async function removeMemoryUri(config, ov, uri, dryRun, options = {}) {
|
|
|
8210
8220
|
}
|
|
8211
8221
|
if (isResourceBusyFailure(result.stderr, result.stdout)) {
|
|
8212
8222
|
await waitForOvQueue(ov, config, options);
|
|
8223
|
+
await sleep(BUSY_RETRY_BACKOFF_MS[attempt] ?? 3e4);
|
|
8213
8224
|
} else {
|
|
8214
8225
|
await sleep(1e3 * (attempt + 1));
|
|
8215
8226
|
}
|
|
@@ -8266,6 +8277,7 @@ async function listChangedFiles(worktree, beforeRev, afterRev) {
|
|
|
8266
8277
|
}
|
|
8267
8278
|
async function applyChangesToOpenViking(config, team, changes, options = {}) {
|
|
8268
8279
|
const ov = await openVikingCliForMode(false);
|
|
8280
|
+
const failed = [];
|
|
8269
8281
|
for (const change of changes) {
|
|
8270
8282
|
if (!change.relativePath.endsWith(".md")) {
|
|
8271
8283
|
continue;
|
|
@@ -8275,24 +8287,57 @@ async function applyChangesToOpenViking(config, team, changes, options = {}) {
|
|
|
8275
8287
|
continue;
|
|
8276
8288
|
}
|
|
8277
8289
|
const uri = workfileToVikingUri(config, team, change.path);
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8290
|
+
try {
|
|
8291
|
+
if (change.status === "removed") {
|
|
8292
|
+
await removeMemoryUri(config, ov, uri, false, options);
|
|
8293
|
+
continue;
|
|
8294
|
+
}
|
|
8295
|
+
if (!await isFile(change.path)) {
|
|
8296
|
+
continue;
|
|
8297
|
+
}
|
|
8298
|
+
const ovHasResource = await vikingResourceExists(ov, config, uri);
|
|
8299
|
+
if (ovHasResource) {
|
|
8300
|
+
const reason = change.status === "modified" ? "overwriting local with upstream (local edits to the shared subtree are not preserved across sync)" : "aligning OV to upstream (resource pre-existed in OV, likely from an earlier local publish or sync)";
|
|
8301
|
+
if (options.quiet !== true) {
|
|
8302
|
+
console.warn(`share sync: ${uri}: ${reason}.`);
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
await ensureSharedDirectoryChain(config, ov, uri, false, options);
|
|
8306
|
+
const writeMode = ovHasResource ? "replace" : "create";
|
|
8307
|
+
await ingestSingleFile(ov, config, uri, change.path, writeMode, options);
|
|
8308
|
+
} catch (err) {
|
|
8309
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8288
8310
|
if (options.quiet !== true) {
|
|
8289
|
-
console.warn(`share sync: ${uri}: ${
|
|
8311
|
+
console.warn(`share sync: ${uri}: ingest failed \u2014 will retry on the next sync. ${message}`);
|
|
8290
8312
|
}
|
|
8313
|
+
failed.push(change);
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8316
|
+
return { failed };
|
|
8317
|
+
}
|
|
8318
|
+
function mergeChanges(...lists) {
|
|
8319
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
8320
|
+
for (const list of lists) {
|
|
8321
|
+
for (const change of list) {
|
|
8322
|
+
map2.set(change.relativePath, change);
|
|
8291
8323
|
}
|
|
8292
|
-
await ensureSharedDirectoryChain(config, ov, uri, false, options);
|
|
8293
|
-
const writeMode = ovHasResource ? "replace" : "create";
|
|
8294
|
-
await ingestSingleFile(ov, config, uri, change.path, writeMode, options);
|
|
8295
8324
|
}
|
|
8325
|
+
return [...map2.values()];
|
|
8326
|
+
}
|
|
8327
|
+
async function applyAndPersistChanges(config, team, state, changes, options = {}) {
|
|
8328
|
+
if (changes.length === 0) {
|
|
8329
|
+
return { failed: [] };
|
|
8330
|
+
}
|
|
8331
|
+
state.pendingReindexes.set(team.name, changes);
|
|
8332
|
+
await writePendingReindexes(config, state);
|
|
8333
|
+
const result = await applyChangesToOpenViking(config, team, changes, options);
|
|
8334
|
+
if (result.failed.length > 0) {
|
|
8335
|
+
state.pendingReindexes.set(team.name, result.failed);
|
|
8336
|
+
} else {
|
|
8337
|
+
state.pendingReindexes.delete(team.name);
|
|
8338
|
+
}
|
|
8339
|
+
await writePendingReindexes(config, state);
|
|
8340
|
+
return result;
|
|
8296
8341
|
}
|
|
8297
8342
|
|
|
8298
8343
|
// src/memory.ts
|