mindwire 0.1.32 → 0.1.34
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/{chunk-5X5PAFM7.js → chunk-3QFDSYKC.js} +178 -10
- package/dist/chunk-3QFDSYKC.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/computer/lifecycle.d.ts +3 -0
- package/dist/computer/relay-health.d.ts +21 -5
- package/dist/{controller-CHJ5MMZS.js → controller-AGT6MCJG.js} +88 -15
- package/dist/controller-AGT6MCJG.js.map +1 -0
- package/dist/{controller-handoff-7S6SKFHX.js → controller-handoff-3LAYBJUL.js} +3 -3
- package/dist/{controller-handoff-7S6SKFHX.js.map → controller-handoff-3LAYBJUL.js.map} +1 -1
- package/dist/index.cjs +171 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +169 -2
- package/dist/index.js.map +1 -1
- package/dist/project-sync.d.ts +101 -0
- package/dist/types.d.ts +2 -0
- package/dist/workspace.d.ts +6 -0
- package/package.json +1 -1
- package/dist/chunk-5X5PAFM7.js.map +0 -1
- package/dist/controller-CHJ5MMZS.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -555,6 +555,172 @@ var Run = class _Run {
|
|
|
555
555
|
}
|
|
556
556
|
};
|
|
557
557
|
|
|
558
|
+
// src/project-sync.ts
|
|
559
|
+
init_errors();
|
|
560
|
+
var ProjectSyncError = class extends exports.MindwireError {
|
|
561
|
+
constructor(operation) {
|
|
562
|
+
super(operation.error ?? (operation.status === "conflicts" ? "Changes conflict. Both workspace copies and their checkpoints are preserved." : `Project synchronization ${operation.status}.`));
|
|
563
|
+
this.operation = operation;
|
|
564
|
+
this.name = "ProjectSyncError";
|
|
565
|
+
}
|
|
566
|
+
operation;
|
|
567
|
+
};
|
|
568
|
+
var active = (o) => ["queued", "exporting", "preparing", "applying"].includes(o.status);
|
|
569
|
+
var prefix = "/workspace/sync";
|
|
570
|
+
function delay(ms, signal) {
|
|
571
|
+
signal?.throwIfAborted();
|
|
572
|
+
return new Promise((resolve, reject) => {
|
|
573
|
+
const done = () => {
|
|
574
|
+
signal?.removeEventListener("abort", abort);
|
|
575
|
+
resolve();
|
|
576
|
+
};
|
|
577
|
+
const timer = setTimeout(done, ms);
|
|
578
|
+
const abort = () => {
|
|
579
|
+
clearTimeout(timer);
|
|
580
|
+
signal?.removeEventListener("abort", abort);
|
|
581
|
+
reject(signal?.reason);
|
|
582
|
+
};
|
|
583
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
var ProjectSyncApi = class {
|
|
587
|
+
constructor(mw) {
|
|
588
|
+
this.mw = mw;
|
|
589
|
+
}
|
|
590
|
+
mw;
|
|
591
|
+
flights = /* @__PURE__ */ new Map();
|
|
592
|
+
export(request, options = {}) {
|
|
593
|
+
return this.mw.http.request("POST", `${prefix}/exports`, { body: request, ...options });
|
|
594
|
+
}
|
|
595
|
+
import(request, options = {}) {
|
|
596
|
+
return this.mw.http.request("POST", `${prefix}/imports`, { body: request, ...options });
|
|
597
|
+
}
|
|
598
|
+
async list(options = {}) {
|
|
599
|
+
const response = await this.mw.http.request("GET", `${prefix}/operations`, options);
|
|
600
|
+
return response.operations;
|
|
601
|
+
}
|
|
602
|
+
get(id, options = {}) {
|
|
603
|
+
return this.mw.http.request("GET", `${prefix}/operations/${encodeURIComponent(id)}`, options);
|
|
604
|
+
}
|
|
605
|
+
retry(id, options = {}) {
|
|
606
|
+
return this.mw.http.request("POST", `${prefix}/operations/${encodeURIComponent(id)}/retry`, options);
|
|
607
|
+
}
|
|
608
|
+
cancel(id) {
|
|
609
|
+
return this.mw.http.request("POST", `${prefix}/operations/${encodeURIComponent(id)}/cancel`);
|
|
610
|
+
}
|
|
611
|
+
checkpoint(id, options = {}) {
|
|
612
|
+
return this.mw.http.request("GET", `${prefix}/checkpoints/${encodeURIComponent(id)}`, options);
|
|
613
|
+
}
|
|
614
|
+
acceptCheckpoint(checkpoint, options = {}) {
|
|
615
|
+
return this.mw.http.request("PUT", `${prefix}/checkpoints/${encodeURIComponent(checkpoint.id)}`, { body: checkpoint, ...options });
|
|
616
|
+
}
|
|
617
|
+
objects(id, cursor = 0, options = {}) {
|
|
618
|
+
return this.mw.http.request("GET", `${prefix}/checkpoints/${encodeURIComponent(id)}/objects`, { query: { cursor }, ...options });
|
|
619
|
+
}
|
|
620
|
+
async missing(objects, options = {}) {
|
|
621
|
+
const response = await this.mw.http.request("POST", `${prefix}/objects/missing`, { body: { objects }, ...options });
|
|
622
|
+
return response.objects;
|
|
623
|
+
}
|
|
624
|
+
/** Base64 chunk, at most 256 KiB before encoding. */
|
|
625
|
+
async getObject(id, options = {}) {
|
|
626
|
+
const response = await this.mw.http.request("GET", `${prefix}/objects/${encodeURIComponent(id)}`, options);
|
|
627
|
+
return response.data;
|
|
628
|
+
}
|
|
629
|
+
async putObject(id, data, options = {}) {
|
|
630
|
+
await this.mw.http.request("PUT", `${prefix}/objects/${encodeURIComponent(id)}`, { body: { data }, ...options });
|
|
631
|
+
}
|
|
632
|
+
async wait(id, options = {}) {
|
|
633
|
+
for (; ; ) {
|
|
634
|
+
const o = await this.get(id, { signal: options.signal });
|
|
635
|
+
options.onUpdate?.(o);
|
|
636
|
+
if (!active(o)) return o;
|
|
637
|
+
await delay(500, options.signal);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
/** Repeating this relay skips acknowledged checkpoints and verified chunks.
|
|
641
|
+
* Aborting detaches the relay; daemon export/apply operations remain durable.
|
|
642
|
+
*/
|
|
643
|
+
async relayCheckpoint(target, id, options = {}) {
|
|
644
|
+
const visited = /* @__PURE__ */ new Set();
|
|
645
|
+
const visit = async (checkpointId) => {
|
|
646
|
+
options.signal?.throwIfAborted();
|
|
647
|
+
if (visited.has(checkpointId)) return;
|
|
648
|
+
visited.add(checkpointId);
|
|
649
|
+
try {
|
|
650
|
+
await target.checkpoint(checkpointId, options);
|
|
651
|
+
return;
|
|
652
|
+
} catch (error) {
|
|
653
|
+
if (!(error instanceof exports.ApiError) || error.status !== 404) throw error;
|
|
654
|
+
}
|
|
655
|
+
const checkpoint = await this.checkpoint(checkpointId, options);
|
|
656
|
+
for (const parent of checkpoint.parents) await visit(parent);
|
|
657
|
+
let cursor = 0;
|
|
658
|
+
do {
|
|
659
|
+
const page = await this.objects(checkpointId, cursor, options);
|
|
660
|
+
const missing = await target.missing(page.objects, options);
|
|
661
|
+
for (const object of missing) {
|
|
662
|
+
const data = await this.getObject(object, options);
|
|
663
|
+
await target.putObject(object, data, options);
|
|
664
|
+
const padding = data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0;
|
|
665
|
+
options.onBytes?.(Math.floor(data.length * 3 / 4) - padding);
|
|
666
|
+
}
|
|
667
|
+
cursor = page.next ?? 0;
|
|
668
|
+
} while (cursor);
|
|
669
|
+
await target.acceptCheckpoint(checkpoint, options);
|
|
670
|
+
};
|
|
671
|
+
await visit(id);
|
|
672
|
+
}
|
|
673
|
+
/** Safe X → Y and Y → X. Persist request.id until acknowledged. A conflict
|
|
674
|
+
* throws ProjectSyncError carrying the complete conflict/recovery operation.
|
|
675
|
+
*/
|
|
676
|
+
switchTo(target, request, options = {}) {
|
|
677
|
+
const intent = JSON.stringify(request);
|
|
678
|
+
const old = this.flights.get(request.id);
|
|
679
|
+
if (old) {
|
|
680
|
+
if (old.intent !== intent || old.target !== target) return Promise.reject(new exports.MindwireError("This sync ID already belongs to a different request or destination."));
|
|
681
|
+
return old.result;
|
|
682
|
+
}
|
|
683
|
+
const work = async () => {
|
|
684
|
+
if (target === this || target.mw.http === this.mw.http) throw new exports.MindwireError("Choose another workspace for this project.");
|
|
685
|
+
let accepted;
|
|
686
|
+
try {
|
|
687
|
+
accepted = await target.get(`${request.id}-import`, options);
|
|
688
|
+
} catch (error) {
|
|
689
|
+
if (!(error instanceof exports.ApiError) || error.status !== 404) throw error;
|
|
690
|
+
}
|
|
691
|
+
if (accepted) {
|
|
692
|
+
if ((accepted.path ?? "") !== (request.path ?? "")) throw new exports.MindwireError("This sync ID belongs to a different destination folder.");
|
|
693
|
+
const operation = await target.wait(accepted.id, {
|
|
694
|
+
signal: options.signal,
|
|
695
|
+
onUpdate: (operation2) => options.onProgress?.({ phase: "apply", transferredBytes: 0, operation: operation2 })
|
|
696
|
+
});
|
|
697
|
+
if (operation.status !== "succeeded") throw new ProjectSyncError(operation);
|
|
698
|
+
return operation;
|
|
699
|
+
}
|
|
700
|
+
const health = await Promise.all([this.mw.health(), target.mw.health()]);
|
|
701
|
+
if (health.some((h) => (h.projectSyncVersion ?? 0) < 1)) throw new exports.MindwireError("Update Mindwire on both workspaces to switch this project.");
|
|
702
|
+
let bytes = 0;
|
|
703
|
+
const emit2 = (phase, operation) => options.onProgress?.({ phase, transferredBytes: bytes, operation });
|
|
704
|
+
emit2("checkpoint");
|
|
705
|
+
let o = await this.export({ id: `${request.id}-export`, projectId: request.projectId }, options);
|
|
706
|
+
o = await this.wait(o.id, { signal: options.signal, onUpdate: (value) => emit2("checkpoint", value) });
|
|
707
|
+
if (o.status !== "succeeded" || !o.resultCheckpointId) throw new ProjectSyncError(o);
|
|
708
|
+
emit2("transfer");
|
|
709
|
+
await this.relayCheckpoint(target, o.resultCheckpointId, { signal: options.signal, onBytes: (n) => {
|
|
710
|
+
bytes += n;
|
|
711
|
+
emit2("transfer");
|
|
712
|
+
} });
|
|
713
|
+
o = await target.import({ id: `${request.id}-import`, checkpointId: o.resultCheckpointId, path: request.path }, options);
|
|
714
|
+
o = await target.wait(o.id, { signal: options.signal, onUpdate: (value) => emit2("apply", value) });
|
|
715
|
+
if (o.status !== "succeeded") throw new ProjectSyncError(o);
|
|
716
|
+
return o;
|
|
717
|
+
};
|
|
718
|
+
const result = work().finally(() => this.flights.delete(request.id));
|
|
719
|
+
this.flights.set(request.id, { intent, target, result });
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
|
|
558
724
|
// src/workspace.ts
|
|
559
725
|
var ProjectOperationsApi = class {
|
|
560
726
|
constructor(mw) {
|
|
@@ -626,6 +792,7 @@ var WorkspaceCollection = class {
|
|
|
626
792
|
var WorkspaceApi = class {
|
|
627
793
|
constructor(mw) {
|
|
628
794
|
this.mw = mw;
|
|
795
|
+
this.sync = new ProjectSyncApi(mw);
|
|
629
796
|
this.git = new GitAccessApi(mw);
|
|
630
797
|
this.operations = new ProjectOperationsApi(mw);
|
|
631
798
|
this.agents = new WorkspaceCollection(mw, "agents");
|
|
@@ -633,6 +800,7 @@ var WorkspaceApi = class {
|
|
|
633
800
|
this.chats = new WorkspaceCollection(mw, "chats");
|
|
634
801
|
}
|
|
635
802
|
mw;
|
|
803
|
+
sync;
|
|
636
804
|
git;
|
|
637
805
|
operations;
|
|
638
806
|
agents;
|
|
@@ -971,7 +1139,7 @@ init_errors();
|
|
|
971
1139
|
init_errors();
|
|
972
1140
|
|
|
973
1141
|
// src/version.ts
|
|
974
|
-
var SDK_VERSION = "0.1.
|
|
1142
|
+
var SDK_VERSION = "0.1.34" ;
|
|
975
1143
|
function versionAtLeast(actual, desired) {
|
|
976
1144
|
if (actual === desired) return true;
|
|
977
1145
|
if (!actual || !/^\d+\.\d+\.\d+$/.test(actual) || !/^\d+\.\d+\.\d+$/.test(desired)) return false;
|
|
@@ -2991,6 +3159,8 @@ exports.McpApi = McpApi;
|
|
|
2991
3159
|
exports.Mindwire = Mindwire;
|
|
2992
3160
|
exports.NotifyApi = NotifyApi;
|
|
2993
3161
|
exports.ProjectOperationsApi = ProjectOperationsApi;
|
|
3162
|
+
exports.ProjectSyncApi = ProjectSyncApi;
|
|
3163
|
+
exports.ProjectSyncError = ProjectSyncError;
|
|
2994
3164
|
exports.PromptsApi = PromptsApi;
|
|
2995
3165
|
exports.ProvidersApi = ProvidersApi;
|
|
2996
3166
|
exports.Run = Run;
|