@relayfile/sdk 0.10.43 → 0.10.45

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.
@@ -265,7 +265,11 @@ function normalizeMountLocalLayout(layout) {
265
265
  return layout === "scoped" ? "scoped" : "exact";
266
266
  }
267
267
  function normalizeMountSyncMode(mode) {
268
- return mode === "write-only" ? "write-only" : "mirror";
268
+ return mode === "pull-only"
269
+ ? "pull-only"
270
+ : mode === "write-only"
271
+ ? "write-only"
272
+ : "mirror";
269
273
  }
270
274
  function resolveMountLocalDir(localDir, remotePath, localLayout) {
271
275
  const root = path.resolve(localDir);
@@ -68,7 +68,7 @@ export interface WorkspaceMountEnvOptions {
68
68
  export type WorkspaceMountEnv = Record<string, string>;
69
69
  export type MountMode = "poll" | "fuse";
70
70
  export type MountLocalLayout = "exact" | "scoped";
71
- export type MountSyncMode = "mirror" | "write-only";
71
+ export type MountSyncMode = "mirror" | "pull-only" | "write-only";
72
72
  export interface MountSessionRequest {
73
73
  localDir: string;
74
74
  remotePath?: string;
package/dist/setup.js CHANGED
@@ -1227,14 +1227,19 @@ function normalizeMountWorkspaceInput(input) {
1227
1227
  if (!localDir) {
1228
1228
  throw new InvalidLocalDirError(String(input.localDir ?? ""));
1229
1229
  }
1230
+ const mode = normalizeMountModeInput(input.mode);
1231
+ const syncMode = normalizeMountSyncModeInput(input.syncMode);
1232
+ if (mode === "fuse" && syncMode === "pull-only") {
1233
+ throw new MountSessionInputError('Mount syncMode "pull-only" requires mode "poll"; FUSE mutation handlers are not read-only.');
1234
+ }
1230
1235
  return {
1231
1236
  workspace: input.workspace,
1232
1237
  workspaceId: normalizeNonEmptyString(input.workspaceId),
1233
1238
  localDir: resolveLocalDir(localDir),
1234
1239
  remotePath: normalizeMountRemotePath(input.remotePath),
1235
- mode: normalizeMountModeInput(input.mode),
1240
+ mode,
1236
1241
  localLayout: normalizeMountLocalLayoutInput(input.localLayout),
1237
- syncMode: normalizeMountSyncModeInput(input.syncMode),
1242
+ syncMode,
1238
1243
  background: input.background !== false,
1239
1244
  agentName: normalizeNonEmptyString(input.agentName),
1240
1245
  scopes: input.scopes && input.scopes.length > 0 ? [...input.scopes] : undefined,
@@ -1278,7 +1283,9 @@ function normalizeMountLocalLayoutInput(layout) {
1278
1283
  }
1279
1284
  function normalizeMountSyncModeInput(mode) {
1280
1285
  const normalized = normalizeNonEmptyString(mode) ?? DEFAULT_MOUNT_SYNC_MODE;
1281
- if (normalized !== "mirror" && normalized !== "write-only") {
1286
+ if (normalized !== "mirror" &&
1287
+ normalized !== "pull-only" &&
1288
+ normalized !== "write-only") {
1282
1289
  throw new MountSessionInputError(`Invalid syncMode "${normalized}" for mount session.`);
1283
1290
  }
1284
1291
  return normalized;
@@ -203,6 +203,14 @@ export async function createWorkspaceIfNeeded(baseUrl, token, workspaceId) {
203
203
  { id: workspace },
204
204
  ];
205
205
  let lastFailure = null;
206
+ // A 404 on the collection route means this deployment has no workspace-create
207
+ // endpoint — not that creation failed. relayfile-cloud addresses each workspace
208
+ // as a Durable Object by name (`WORKSPACE_DO.idFromName(workspaceId)`), so the
209
+ // workspace comes into existence on the first request addressed to it and there
210
+ // is nothing to pre-create. Treating that as fatal made every caller that seeds
211
+ // a workspace (notably relayflows' per-agent permission provisioning) fail
212
+ // before doing any work.
213
+ let sawRouteMissing = false;
206
214
  for (const body of bodyCandidates) {
207
215
  try {
208
216
  const response = await fetch(endpoint, {
@@ -220,6 +228,11 @@ export async function createWorkspaceIfNeeded(baseUrl, token, workspaceId) {
220
228
  response.status === 409) {
221
229
  return;
222
230
  }
231
+ if (response.status === 404) {
232
+ // Retrying the other body shapes cannot conjure a route that is absent.
233
+ sawRouteMissing = true;
234
+ break;
235
+ }
223
236
  const responseBody = await response.text().catch(() => '');
224
237
  lastFailure = `HTTP ${response.status} ${responseBody}`.trim();
225
238
  if (response.status < 500 && response.status !== 409) {
@@ -230,8 +243,12 @@ export async function createWorkspaceIfNeeded(baseUrl, token, workspaceId) {
230
243
  lastFailure = String(error);
231
244
  }
232
245
  }
246
+ if (sawRouteMissing) {
247
+ // Implicit-workspace deployment: nothing to create, so seeding can proceed.
248
+ return;
249
+ }
233
250
  if (lastFailure) {
234
- throw new Error(`Failed to create workspace ${workspace}: ${lastFailure}`);
251
+ throw new Error(`Failed to create workspace ${workspace} at ${endpoint}: ${lastFailure}`);
235
252
  }
236
253
  }
237
254
  export async function seedAclRules(baseUrl, token, workspaceId, aclRules) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/sdk",
3
- "version": "0.10.43",
3
+ "version": "0.10.45",
4
4
  "description": "TypeScript SDK for relayfile — real-time filesystem for humans and agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -59,15 +59,15 @@
59
59
  "prepublishOnly": "npm run build"
60
60
  },
61
61
  "dependencies": {
62
- "@relayfile/core": "0.10.43",
62
+ "@relayfile/core": "0.10.45",
63
63
  "ignore": "^7.0.5",
64
64
  "tar": "^7.5.10"
65
65
  },
66
66
  "optionalDependencies": {
67
- "@relayfile/mount-darwin-arm64": "0.10.43",
68
- "@relayfile/mount-darwin-x64": "0.10.43",
69
- "@relayfile/mount-linux-arm64": "0.10.43",
70
- "@relayfile/mount-linux-x64": "0.10.43"
67
+ "@relayfile/mount-darwin-arm64": "0.10.45",
68
+ "@relayfile/mount-darwin-x64": "0.10.45",
69
+ "@relayfile/mount-linux-arm64": "0.10.45",
70
+ "@relayfile/mount-linux-x64": "0.10.45"
71
71
  },
72
72
  "devDependencies": {
73
73
  "typescript": "^5.7.3",