freestyle-sync 0.1.1 → 0.1.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.md +2 -1
- package/package.json +4 -1
- package/plugins/agent-copilot/src/index.ts +21 -11
- package/src/main.ts +165 -43
- package/src/plugin-api.ts +6 -3
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Freestyle Sync
|
|
2
2
|
|
|
3
|
-
Sync your current directory, it's dependencies, and your agent context into a VM.
|
|
3
|
+
Sync your current directory, it's dependencies, and your agent context into a VM. VM snapshots ensure only changes are uploaded.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
npx freestyle-sync
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
Configure complex sync behavior using plugins.
|
|
9
10
|
```ts
|
|
10
11
|
import { defineConfig } from "freestyle-sync";
|
|
11
12
|
import { claudeAgentPlugin } from "@freestyle-sync/agent-claude";
|
package/package.json
CHANGED
|
@@ -33,11 +33,13 @@ export function copilotAgentPlugin() {
|
|
|
33
33
|
return [];
|
|
34
34
|
},
|
|
35
35
|
async beforeOpenRemoteEditor({ vm, vmId, scheme, remoteWorkspaceUri, contextCandidates, utils }) {
|
|
36
|
+
if (!isSupportedEditorScheme(scheme)) return [];
|
|
36
37
|
const result = await preseedLocalCopilotForRemoteUri(vm, vmId, contextCandidates, scheme, remoteWorkspaceUri, utils);
|
|
37
38
|
if (result.status === "copied") return [`Prepared Copilot sidebar state for ${scheme === "cursor" ? "Cursor" : "VS Code"}.`];
|
|
38
39
|
return [];
|
|
39
40
|
},
|
|
40
41
|
async afterOpenRemoteEditor({ vm, vmId, scheme, remoteWorkspaceUri, contextCandidates, utils }) {
|
|
42
|
+
if (!isSupportedEditorScheme(scheme)) return [];
|
|
41
43
|
const result = await syncLocalCopilotForRemoteUri(vm, vmId, contextCandidates, remoteWorkspaceUri, utils);
|
|
42
44
|
if (result.status === "copied") return [`Copied Copilot sidebar state to opened ${scheme === "cursor" ? "Cursor" : "VS Code"} workspace.`];
|
|
43
45
|
if (result.status === "pending") return ["Copilot sidebar state: opened the editor, but the workspace storage bucket was not created yet. Reload the window after it finishes connecting, then rerun vmpush if needed."];
|
|
@@ -166,7 +168,7 @@ async function syncLocalCopilotForRemoteUri(vm: RemoteVm, vmId: string, contextC
|
|
|
166
168
|
return { status: "pending", count: 0 };
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
async function preseedLocalCopilotForRemoteUri(vm: RemoteVm, vmId: string, contextCandidates: ContextCandidate[], scheme:
|
|
171
|
+
async function preseedLocalCopilotForRemoteUri(vm: RemoteVm, vmId: string, contextCandidates: ContextCandidate[], scheme: string, remoteWorkspaceUri: string, utils: PushvmPluginUtils): Promise<CopyResult> {
|
|
170
172
|
const sourceCopilotDir = selectedCurrentCopilotSource(contextCandidates);
|
|
171
173
|
if (!sourceCopilotDir || !(await exists(sourceCopilotDir))) return { status: "skipped", count: 0 };
|
|
172
174
|
|
|
@@ -455,17 +457,25 @@ async function ensureWorkspaceStateDb(stateDb: string) {
|
|
|
455
457
|
await execFileAsync("sqlite3", [stateDb, "CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB);"]);
|
|
456
458
|
}
|
|
457
459
|
|
|
458
|
-
function codeUserRootsForScheme(home: string, scheme:
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
460
|
+
function codeUserRootsForScheme(home: string, scheme: string) {
|
|
461
|
+
switch (scheme) {
|
|
462
|
+
case "cursor":
|
|
463
|
+
return [
|
|
464
|
+
path.join(home, "Library", "Application Support", "Cursor", "User"),
|
|
465
|
+
path.join(home, ".config", "Cursor", "User"),
|
|
466
|
+
];
|
|
467
|
+
case "vscode":
|
|
468
|
+
return [
|
|
469
|
+
path.join(home, "Library", "Application Support", "Code", "User"),
|
|
470
|
+
path.join(home, ".config", "Code", "User"),
|
|
471
|
+
];
|
|
472
|
+
default:
|
|
473
|
+
return [];
|
|
464
474
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function isSupportedEditorScheme(scheme: string): scheme is "vscode" | "cursor" {
|
|
478
|
+
return scheme === "vscode" || scheme === "cursor";
|
|
469
479
|
}
|
|
470
480
|
|
|
471
481
|
function codeUserRoots(home: string) {
|
package/src/main.ts
CHANGED
|
@@ -17,6 +17,9 @@ const execFileAsync = promisify(execFile);
|
|
|
17
17
|
const CACHE_VERSION = 1;
|
|
18
18
|
const PLUGIN_PREFERENCES_VERSION = 1;
|
|
19
19
|
const ARCHIVE_CHUNK_CHARS = 1024 * 1024;
|
|
20
|
+
const MS_PER_SECOND = 1000;
|
|
21
|
+
const USE_UNICODE_OUTPUT = process.stdout.isTTY && (process.env.TERM !== "dumb" || Boolean(process.env.TERM_PROGRAM));
|
|
22
|
+
const USE_STYLED_OUTPUT = process.stdout.isTTY && process.env.NO_COLOR !== "1";
|
|
20
23
|
let config: PushvmConfig = { plugins: [] };
|
|
21
24
|
let plugins = config.plugins;
|
|
22
25
|
const pluginUtils: PushvmPluginUtils = {
|
|
@@ -79,14 +82,33 @@ type SyncResult = {
|
|
|
79
82
|
class Progress {
|
|
80
83
|
private current = 0;
|
|
81
84
|
private readonly total: number;
|
|
85
|
+
private currentStepStartedAt = 0;
|
|
86
|
+
private currentStepMessage?: string;
|
|
82
87
|
|
|
83
88
|
constructor(total: number) {
|
|
84
89
|
this.total = total;
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
step(message: string) {
|
|
93
|
+
if (this.currentStepMessage) {
|
|
94
|
+
this.printCompletion();
|
|
95
|
+
}
|
|
88
96
|
this.current += 1;
|
|
89
|
-
|
|
97
|
+
this.currentStepMessage = message;
|
|
98
|
+
this.currentStepStartedAt = Date.now();
|
|
99
|
+
console.log(`${accent(symbol("➜", ">"))} ${bold(`[${this.current}/${this.total}]`)} ${message}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
finish() {
|
|
103
|
+
if (!this.currentStepMessage) return;
|
|
104
|
+
this.printCompletion();
|
|
105
|
+
this.currentStepMessage = undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private printCompletion() {
|
|
109
|
+
if (!this.currentStepMessage) return;
|
|
110
|
+
const elapsed = Date.now() - this.currentStepStartedAt;
|
|
111
|
+
console.log(`${success(symbol("✔", "*"))} ${dim(`[${this.current}/${this.total}]`)} ${this.currentStepMessage} ${dim(formatDuration(elapsed))}`);
|
|
90
112
|
}
|
|
91
113
|
}
|
|
92
114
|
|
|
@@ -99,6 +121,7 @@ if (isDirectCliExecution()) {
|
|
|
99
121
|
|
|
100
122
|
async function main() {
|
|
101
123
|
const options = await parseArgs(process.argv.slice(2));
|
|
124
|
+
printHeading("vmpush");
|
|
102
125
|
config = await loadConfig(options.projectRoot);
|
|
103
126
|
plugins = config.plugins;
|
|
104
127
|
const pluginPreferences = await updatePluginPreferences(options);
|
|
@@ -107,12 +130,53 @@ async function main() {
|
|
|
107
130
|
printPlugins(pluginPreferences, options);
|
|
108
131
|
return;
|
|
109
132
|
}
|
|
110
|
-
const progress = new Progress(options.dryRun ? 2 : options.install ? 12 : 11);
|
|
111
133
|
|
|
112
134
|
if (options.dryRun) {
|
|
113
135
|
console.log("vmpush dry run");
|
|
114
136
|
}
|
|
115
137
|
|
|
138
|
+
if (options.skipSync) {
|
|
139
|
+
const progress = new Progress(3);
|
|
140
|
+
progress.step("Reading sync cache");
|
|
141
|
+
const cache = await readCache(options.cachePath, options);
|
|
142
|
+
|
|
143
|
+
if (!options.vmId && !cache.snapshotId) {
|
|
144
|
+
console.warn("vmpush --skip-sync: no cached snapshot found. A new empty VM will be created. Run without --skip-sync first to create a snapshot.");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const source = options.vmId ? `existing VM ${options.vmId}` : cache.snapshotId ? `snapshot ${cache.snapshotId}` : "a new VM";
|
|
148
|
+
console.log(`Skipping sync: creating VM from ${source}`);
|
|
149
|
+
console.log(`Remote project: ${options.remoteProjectDir}`);
|
|
150
|
+
|
|
151
|
+
if (options.dryRun) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
progress.step("Preparing Freestyle VM");
|
|
156
|
+
const { vm, vmId } = await getOrCreateVm(options, cache.snapshotId);
|
|
157
|
+
console.log(`Using VM: ${vmId}`);
|
|
158
|
+
|
|
159
|
+
progress.step(`Running post-sync plugins for ${vmId}`);
|
|
160
|
+
const contextCandidates = await discoverPluginContextCandidates(options);
|
|
161
|
+
const postSyncMessages = await runAfterSyncPlugins(vm, vmId, options, contextCandidates);
|
|
162
|
+
|
|
163
|
+
console.log("");
|
|
164
|
+
console.log(`VM ready: ${vmId}`);
|
|
165
|
+
console.log(`Project: ${options.remoteProjectDir}`);
|
|
166
|
+
if (cache.snapshotId) {
|
|
167
|
+
console.log(`Snapshot cache: ${cache.snapshotId}`);
|
|
168
|
+
}
|
|
169
|
+
for (const message of postSyncMessages) console.log(message);
|
|
170
|
+
console.log(`SSH: npx freestyle vm ssh ${vmId}`);
|
|
171
|
+
if (options.autoSsh) {
|
|
172
|
+
const connected = await runConnectPlugins(vm, vmId, options, contextCandidates);
|
|
173
|
+
if (!connected) await sshIntoVm(vmId);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const progress = new Progress(options.dryRun ? 2 : options.install ? 12 : 11);
|
|
179
|
+
|
|
116
180
|
progress.step("Scanning project files");
|
|
117
181
|
const cache = await readCache(options.cachePath, options);
|
|
118
182
|
const base = cacheBaseForSync(options, cache);
|
|
@@ -132,6 +196,7 @@ async function main() {
|
|
|
132
196
|
printPlan(options, projectChanges, contextChanges, envExports, cache);
|
|
133
197
|
|
|
134
198
|
if (options.dryRun) {
|
|
199
|
+
progress.finish();
|
|
135
200
|
return;
|
|
136
201
|
}
|
|
137
202
|
|
|
@@ -162,59 +227,69 @@ async function main() {
|
|
|
162
227
|
await runInstall(vm, options.projectRoot, options.remoteProjectDir);
|
|
163
228
|
}
|
|
164
229
|
|
|
165
|
-
|
|
166
|
-
let snapshotProjectFiles = cache.snapshotProjectFiles;
|
|
167
|
-
let snapshotContextFiles = cache.snapshotContextFiles;
|
|
168
|
-
let snapshotEnvHash = cache.snapshotEnvHash;
|
|
169
|
-
if (options.snapshot) {
|
|
170
|
-
progress.step(`Creating snapshot cache for ${vmId}`);
|
|
171
|
-
await runBeforeSnapshotPlugins(vm, vmId, options);
|
|
172
|
-
try {
|
|
173
|
-
const snapshot = await vm.snapshot({ name: `vmpush-${path.basename(options.projectRoot)}-${Date.now()}` });
|
|
174
|
-
snapshotId = snapshot.snapshotId;
|
|
175
|
-
snapshotProjectFiles = projectCurrent;
|
|
176
|
-
snapshotContextFiles = contextCurrent;
|
|
177
|
-
snapshotEnvHash = envHash;
|
|
178
|
-
} catch (error) {
|
|
179
|
-
console.warn(`Snapshot cache skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
progress.step("Skipping snapshot cache");
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
progress.step("Saving local sync cache");
|
|
186
|
-
await writeCache(options.cachePath, {
|
|
230
|
+
const buildSyncCache = (snapshotOverride?: { snapshotId: string }): CacheFile => ({
|
|
187
231
|
version: CACHE_VERSION,
|
|
188
232
|
projectRoot: options.projectRoot,
|
|
189
233
|
remoteProjectDir: options.remoteProjectDir,
|
|
190
234
|
vmId,
|
|
191
|
-
snapshotId,
|
|
235
|
+
snapshotId: snapshotOverride ? snapshotOverride.snapshotId : cache.snapshotId,
|
|
192
236
|
projectFiles: projectCurrent,
|
|
193
237
|
contextFiles: contextCurrent,
|
|
194
|
-
snapshotProjectFiles,
|
|
195
|
-
snapshotContextFiles,
|
|
238
|
+
snapshotProjectFiles: snapshotOverride ? projectCurrent : cache.snapshotProjectFiles,
|
|
239
|
+
snapshotContextFiles: snapshotOverride ? contextCurrent : cache.snapshotContextFiles,
|
|
196
240
|
envHash,
|
|
197
|
-
snapshotEnvHash,
|
|
241
|
+
snapshotEnvHash: snapshotOverride ? envHash : cache.snapshotEnvHash,
|
|
198
242
|
updatedAt: new Date().toISOString(),
|
|
199
243
|
});
|
|
200
244
|
|
|
245
|
+
progress.step("Saving local sync cache");
|
|
246
|
+
await writeCache(options.cachePath, buildSyncCache());
|
|
247
|
+
|
|
248
|
+
let snapshotPromise: Promise<string | null> | null = null;
|
|
249
|
+
if (options.snapshot) {
|
|
250
|
+
progress.step(`Creating snapshot cache for ${vmId} in background`);
|
|
251
|
+
snapshotPromise = (async () => {
|
|
252
|
+
await runBeforeSnapshotPlugins(vm, vmId, options);
|
|
253
|
+
try {
|
|
254
|
+
const snapshot = await vm.snapshot({ name: `vmpush-${path.basename(options.projectRoot)}-${Date.now()}` });
|
|
255
|
+
return snapshot.snapshotId;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.warn(`Snapshot cache skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
261
|
+
} else {
|
|
262
|
+
progress.step("Skipping snapshot cache");
|
|
263
|
+
}
|
|
264
|
+
|
|
201
265
|
progress.step(`Running post-sync plugins for ${vmId}`);
|
|
202
266
|
const postSyncMessages = await runAfterSyncPlugins(vm, vmId, options, contextCandidates);
|
|
267
|
+
progress.finish();
|
|
203
268
|
|
|
204
269
|
console.log("");
|
|
205
|
-
console.log(`VM ready: ${vmId}`);
|
|
206
|
-
console.log(
|
|
207
|
-
console.log(
|
|
208
|
-
console.log(
|
|
209
|
-
if (
|
|
210
|
-
console.log(
|
|
270
|
+
console.log(`${success(symbol("✓", "*"))} ${bold(`VM ready: ${vmId}`)}`);
|
|
271
|
+
console.log(`${dim("Remote project:")} ${options.remoteProjectDir}`);
|
|
272
|
+
console.log(`${dim("Project files:")} ${projectResult.uploaded} uploaded, ${projectResult.removed} removed, ${projectResult.unchanged} unchanged`);
|
|
273
|
+
console.log(`${dim("Context files:")} ${contextResult.uploaded} uploaded, ${contextResult.unchanged} unchanged`);
|
|
274
|
+
if (snapshotPromise) {
|
|
275
|
+
console.log(`${dim("Snapshot cache:")} creating in background`);
|
|
276
|
+
} else if (cache.snapshotId) {
|
|
277
|
+
console.log(`${dim("Snapshot cache:")} ${cache.snapshotId}`);
|
|
211
278
|
}
|
|
212
279
|
for (const message of postSyncMessages) console.log(message);
|
|
213
|
-
console.log(`SSH: npx freestyle vm ssh ${vmId}`);
|
|
280
|
+
console.log(`${accent(symbol("➜", ">"))} ${bold(`SSH: npx freestyle vm ssh ${vmId}`)}`);
|
|
214
281
|
if (options.autoSsh) {
|
|
215
282
|
const connected = await runConnectPlugins(vm, vmId, options, contextCandidates);
|
|
216
283
|
if (!connected) await sshIntoVm(vmId);
|
|
217
284
|
}
|
|
285
|
+
|
|
286
|
+
if (snapshotPromise) {
|
|
287
|
+
const newSnapshotId = await snapshotPromise;
|
|
288
|
+
if (newSnapshotId) {
|
|
289
|
+
await writeCache(options.cachePath, buildSyncCache({ snapshotId: newSnapshotId }));
|
|
290
|
+
console.log(`Snapshot cache saved: ${newSnapshotId}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
218
293
|
}
|
|
219
294
|
|
|
220
295
|
function isDirectCliExecution() {
|
|
@@ -298,6 +373,7 @@ async function parseArgs(args: string[]): Promise<CliOptions> {
|
|
|
298
373
|
includeGitDir: true,
|
|
299
374
|
includeAllCopilotWorkspaces: false,
|
|
300
375
|
snapshot: true,
|
|
376
|
+
skipSync: false,
|
|
301
377
|
install: false,
|
|
302
378
|
autoSsh: true,
|
|
303
379
|
envKeys: [],
|
|
@@ -331,6 +407,8 @@ async function parseArgs(args: string[]): Promise<CliOptions> {
|
|
|
331
407
|
options.includeAllCopilotWorkspaces = true;
|
|
332
408
|
} else if (arg === "--no-snapshot" || arg === "--skip-snapshot") {
|
|
333
409
|
options.snapshot = false;
|
|
410
|
+
} else if (arg === "--skip-sync") {
|
|
411
|
+
options.skipSync = true;
|
|
334
412
|
} else if (arg === "--install") {
|
|
335
413
|
options.install = true;
|
|
336
414
|
} else if (arg === "--no-ssh") {
|
|
@@ -400,6 +478,8 @@ Options:
|
|
|
400
478
|
--all-copilot-workspaces Include Copilot chat state for every VS Code workspace.
|
|
401
479
|
--no-snapshot, --skip-snapshot
|
|
402
480
|
Do not snapshot the VM after sync.
|
|
481
|
+
--skip-sync Create a VM from the last cached snapshot without syncing current
|
|
482
|
+
files. Requires a prior sync with snapshotting enabled, or --vm-id.
|
|
403
483
|
--dry-run Show what would sync without creating or changing a VM.
|
|
404
484
|
-y, --yes Deprecated; accepted for compatibility.
|
|
405
485
|
-h, --help Show this help.
|
|
@@ -750,20 +830,62 @@ function printPlan(
|
|
|
750
830
|
cache: CacheFile,
|
|
751
831
|
) {
|
|
752
832
|
const source = options.vmId ? `existing VM ${options.vmId}` : cache.snapshotId ? `snapshot ${cache.snapshotId}` : "a new VM";
|
|
753
|
-
console.log(
|
|
754
|
-
console.log(
|
|
755
|
-
console.log(
|
|
756
|
-
console.log(
|
|
757
|
-
console.log(
|
|
833
|
+
console.log("");
|
|
834
|
+
console.log(`${bold("Sync plan")}`);
|
|
835
|
+
console.log(`${dim(" Source:")} ${source}`);
|
|
836
|
+
console.log(`${dim(" Local:")} ${options.projectRoot}`);
|
|
837
|
+
console.log(`${dim(" Remote:")} ${options.remoteProjectDir}`);
|
|
838
|
+
console.log(`${dim(" Project files:")} ${projectChanges.changed.length} changed, ${projectChanges.removed.length} removed, ${projectChanges.unchanged} unchanged`);
|
|
839
|
+
console.log(`${dim(" Context files:")} ${contextChanges.changed.length} changed, ${contextChanges.removed.length} removed, ${contextChanges.unchanged} unchanged`);
|
|
840
|
+
console.log(`${dim(" Estimated upload:")} ${formatBytes(totalEntrySize(projectChanges.changed))} project, ${formatBytes(totalEntrySize(contextChanges.changed))} context`);
|
|
758
841
|
if (Object.keys(envExports).length > 0) {
|
|
759
|
-
console.log(
|
|
842
|
+
console.log(`${dim(" Environment exports:")} ${Object.keys(envExports).length}`);
|
|
760
843
|
}
|
|
844
|
+
console.log("");
|
|
761
845
|
}
|
|
762
846
|
|
|
763
847
|
function totalEntrySize(entries: LocalEntry[]) {
|
|
764
848
|
return entries.reduce((total, entry) => total + entry.size, 0);
|
|
765
849
|
}
|
|
766
850
|
|
|
851
|
+
function printHeading(name: string) {
|
|
852
|
+
console.log(`${bold(name)} ${dim(`${symbol("→", "-")} Freestyle sync`)}`);
|
|
853
|
+
console.log("");
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
function formatDuration(milliseconds: number) {
|
|
857
|
+
if (milliseconds < MS_PER_SECOND) {
|
|
858
|
+
const rounded = Math.round(milliseconds);
|
|
859
|
+
return `${rounded === 0 && milliseconds > 0 ? 1 : rounded}ms`;
|
|
860
|
+
}
|
|
861
|
+
return `${(milliseconds / MS_PER_SECOND).toFixed(1)}s`;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
function symbol(unicode: string, ascii: string) {
|
|
865
|
+
return USE_UNICODE_OUTPUT ? unicode : ascii;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
function accent(text: string) {
|
|
869
|
+
return color(36, text);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function success(text: string) {
|
|
873
|
+
return color(32, text);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
function dim(text: string) {
|
|
877
|
+
return color(2, text);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function bold(text: string) {
|
|
881
|
+
return color(1, text);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function color(code: number, text: string) {
|
|
885
|
+
if (!USE_STYLED_OUTPUT) return text;
|
|
886
|
+
return `\u001b[${code}m${text}\u001b[0m`;
|
|
887
|
+
}
|
|
888
|
+
|
|
767
889
|
async function getOrCreateVm(options: CliOptions, snapshotId?: string) {
|
|
768
890
|
if (options.vmId) {
|
|
769
891
|
const { vm } = await freestyle.vms.get({ vmId: options.vmId });
|
|
@@ -1049,7 +1171,7 @@ async function runBeforeOpenRemoteEditorPlugins(
|
|
|
1049
1171
|
vm: Awaited<ReturnType<typeof getOrCreateVm>>["vm"],
|
|
1050
1172
|
vmId: string,
|
|
1051
1173
|
options: CliOptions,
|
|
1052
|
-
scheme:
|
|
1174
|
+
scheme: string,
|
|
1053
1175
|
remoteWorkspaceUri: string,
|
|
1054
1176
|
contextCandidates: ContextCandidate[],
|
|
1055
1177
|
) {
|
|
@@ -1073,7 +1195,7 @@ async function runAfterOpenRemoteEditorPlugins(
|
|
|
1073
1195
|
vm: Awaited<ReturnType<typeof getOrCreateVm>>["vm"],
|
|
1074
1196
|
vmId: string,
|
|
1075
1197
|
options: CliOptions,
|
|
1076
|
-
scheme:
|
|
1198
|
+
scheme: string,
|
|
1077
1199
|
remoteWorkspaceUri: string,
|
|
1078
1200
|
contextCandidates: ContextCandidate[],
|
|
1079
1201
|
) {
|
package/src/plugin-api.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type CliOptions = {
|
|
|
16
16
|
includeGitDir: boolean;
|
|
17
17
|
includeAllCopilotWorkspaces: boolean;
|
|
18
18
|
snapshot: boolean;
|
|
19
|
+
skipSync: boolean;
|
|
19
20
|
install: boolean;
|
|
20
21
|
autoSsh: boolean;
|
|
21
22
|
envKeys: string[];
|
|
@@ -68,15 +69,17 @@ export type RemoteHookContext = PushvmPluginContext & {
|
|
|
68
69
|
vmId: string;
|
|
69
70
|
};
|
|
70
71
|
|
|
72
|
+
export type EditorScheme = string;
|
|
73
|
+
|
|
71
74
|
export type EditorHookContext = RemoteHookContext & {
|
|
72
|
-
scheme:
|
|
75
|
+
scheme: EditorScheme;
|
|
73
76
|
remoteWorkspaceUri: string;
|
|
74
77
|
};
|
|
75
78
|
|
|
76
79
|
export type ConnectHookContext = RemoteHookContext & {
|
|
77
80
|
contextCandidates: ContextCandidate[];
|
|
78
|
-
runBeforeOpenRemoteEditor(args: { scheme:
|
|
79
|
-
runAfterOpenRemoteEditor(args: { scheme:
|
|
81
|
+
runBeforeOpenRemoteEditor(args: { scheme: EditorScheme; remoteWorkspaceUri: string }): Promise<string[]>;
|
|
82
|
+
runAfterOpenRemoteEditor(args: { scheme: EditorScheme; remoteWorkspaceUri: string }): Promise<string[]>;
|
|
80
83
|
};
|
|
81
84
|
|
|
82
85
|
export type PushvmPlugin = {
|