@oddington/sdk 0.1.36 → 0.1.38

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/browser.js CHANGED
@@ -185,7 +185,11 @@ function parseAppRoutineContract(value) {
185
185
  };
186
186
  }
187
187
  case "array":
188
- return !fields(value2, ["type", "items", "maxItems"]) || !Number.isSafeInteger(value2.maxItems) || value2.maxItems < 1 || value2.maxItems > 64 ? invalidContract() : { type: "array", items: schema2(value2.items, depth + 1), maxItems: value2.maxItems };
188
+ return !fields(value2, ["type", "items"], ["maxItems"]) || owns(value2, "maxItems") && (!Number.isSafeInteger(value2.maxItems) || value2.maxItems < 1) ? invalidContract() : {
189
+ type: "array",
190
+ items: schema2(value2.items, depth + 1),
191
+ ...owns(value2, "maxItems") ? { maxItems: value2.maxItems } : {}
192
+ };
189
193
  case "boolean":
190
194
  return fields(value2, ["type"]) ? { type: value2.type } : invalidContract();
191
195
  case "file":
@@ -238,7 +242,8 @@ function validateRoutineSchemaValue(schema2, value, rejected) {
238
242
  return;
239
243
  case "array":
240
244
  if (!denseArray(value2)) return fail4("wrong_type");
241
- if (value2.length > schema3.maxItems) return fail4("out_of_bounds", { constraint: "maxItems", limit: schema3.maxItems });
245
+ if (schema3.maxItems !== void 0 && value2.length > schema3.maxItems)
246
+ return fail4("out_of_bounds", { constraint: "maxItems", limit: schema3.maxItems });
242
247
  value2.forEach((child, index) => check(schema3.items, child, `${path}[${index}]`));
243
248
  return;
244
249
  case "boolean":
@@ -887,8 +892,8 @@ var schema = {
887
892
  object(properties) {
888
893
  return declaration({ type: "object", properties: Object.fromEntries(Object.entries(properties).map(([key, value]) => [key, nestedSchema(value)])), required: Object.keys(properties), additionalProperties: !1 });
889
894
  },
890
- array(items, options) {
891
- return declaration({ type: "array", items: nestedSchema(items), maxItems: options.maxItems });
895
+ array(items, options = {}) {
896
+ return assertRoutineFields(options, ["maxItems"]), declaration({ type: "array", items: nestedSchema(items), ...options });
892
897
  },
893
898
  string(options = {}) {
894
899
  return declaration({ type: "string", ...options });
@@ -1665,7 +1670,7 @@ async function send(suffix, init2, descriptor, initial, parent) {
1665
1670
  parseFileErrorDetail(error?.detail)
1666
1671
  ) : unavailable2();
1667
1672
  }
1668
- if (response2.status !== (descriptor === 204 ? 204 : 200) || descriptor === 204 && response2.body !== null)
1673
+ if (response2.status !== 200)
1669
1674
  throw response2.body?.cancel().catch(() => {
1670
1675
  }), unavailable2();
1671
1676
  try {
@@ -1674,7 +1679,6 @@ async function send(suffix, init2, descriptor, initial, parent) {
1674
1679
  throw response2.body?.cancel().catch(() => {
1675
1680
  }), error;
1676
1681
  }
1677
- if (descriptor === 204) return;
1678
1682
  if (!descriptor) return response2;
1679
1683
  let value = await result(response2, descriptor === "control" ? CONTROL_RESULT_BYTES : RESULT_BYTES);
1680
1684
  if (descriptor === "control")
@@ -1773,10 +1777,15 @@ async function multipartCreate(input, metadata, exchange, release = () => {
1773
1777
  await upload?.beforeComplete();
1774
1778
  let completion = control({ parts: receipts });
1775
1779
  if (new TextEncoder().encode(completion.body).byteLength > 128 * 1024) throw unavailable2();
1776
- return parseFileDescriptor(await request2(
1780
+ let completed = parseFileDescriptor(await request2(
1777
1781
  (signal) => exchange(`${route}/complete`, completion, !0, signal),
1778
1782
  TIMEOUT_MS + Math.ceil(metadata.size / (1024 * 1024)) * 1e3
1779
1783
  ));
1784
+ if (!upload) {
1785
+ let acknowledged = await request2((signal) => exchange(`${route}/acknowledge`, control(completed), "control", signal));
1786
+ if (!acknowledged || typeof acknowledged != "object" || Object.keys(acknowledged).join(",") !== "acknowledged" || acknowledged.acknowledged !== !0) throw unavailable2();
1787
+ }
1788
+ return completed;
1780
1789
  } catch (error) {
1781
1790
  throw reader && await reader.cancel(error).catch(() => {
1782
1791
  }), ticket && await request2((signal) => exchange(`${route}/abort`, control({}), "control", signal)).catch(() => {
@@ -1839,9 +1848,6 @@ async function read(id3, names) {
1839
1848
  });
1840
1849
  }
1841
1850
  var files = {
1842
- delete(id3) {
1843
- return operation((context, signal) => send(idPath(id3), { method: "DELETE" }, 204, context, signal));
1844
- },
1845
1851
  async upload(id3) {
1846
1852
  return operation(async (context, signal) => {
1847
1853
  let file2 = await send(`${idPath(id3)}/upload`, { method: "POST" }, !0, context, signal);
@@ -1960,6 +1966,37 @@ var files = {
1960
1966
  function validDropboxRootPath(value) {
1961
1967
  return typeof value == "string" && value.length <= 2048 && value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value) && value.slice(1).split("/").every((segment) => segment.length > 0 && segment.trim() === segment && segment !== "." && segment !== "..");
1962
1968
  }
1969
+ function validMicrosoftId(value) {
1970
+ return typeof value == "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(value);
1971
+ }
1972
+ function validMicrosoftMailbox(value) {
1973
+ return typeof value == "string" && value.length <= 254 && /^[^\s@/?#\\\x00-\x1f\x7f]+@[^\s@/?#\\\x00-\x1f\x7f]+\.[^\s@/?#\\\x00-\x1f\x7f]+$/.test(value);
1974
+ }
1975
+ function sharePointHost(value) {
1976
+ return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.sharepoint\.com$/.test(value);
1977
+ }
1978
+ function canonicalSharePointSiteUrl(value) {
1979
+ if (!(typeof value != "string" || value.length > 2048 || /[\s\\?#\x00-\x1f\x7f]/.test(value) || !/^https:\/\/[^/:@]+(?:\/|$)/i.test(value)))
1980
+ try {
1981
+ let url = new URL(value);
1982
+ if (url.protocol !== "https:" || !sharePointHost(url.hostname) || url.username || url.password || url.port) return;
1983
+ let rawPath = value.replace(/^https:\/\/[^/]+/i, "") || "/", path = rawPath.endsWith("/") ? rawPath.slice(0, -1) : rawPath, segments = path.slice(1).split("/");
1984
+ if (path && segments.some((segment) => !segment)) return;
1985
+ let encoded = path ? segments.map((segment) => {
1986
+ let decoded = decodeURIComponent(segment);
1987
+ if (decoded === "." || decoded === ".." || /[/%\\?#\x00-\x1f\x7f]/.test(decoded)) throw new Error();
1988
+ return encodeURIComponent(decoded);
1989
+ }).join("/") : "", canonical = `https://${url.hostname}/${encoded}`;
1990
+ return canonical.length <= 2048 ? canonical : void 0;
1991
+ } catch {
1992
+ return;
1993
+ }
1994
+ }
1995
+ function validSharePointSiteId(value, siteUrl) {
1996
+ if (typeof value != "string" || value.length > 512) return !1;
1997
+ let [host, collection, site, extra] = value.split(",");
1998
+ return extra === void 0 && host === new URL(siteUrl).hostname && validMicrosoftId(collection) && validMicrosoftId(site);
1999
+ }
1963
2000
  function validGoogleScopes(value) {
1964
2001
  return Array.isArray(value) && value.length > 0 && value.length <= 32 && value.every((scope) => typeof scope == "string" && scope.length <= 256 && /^(https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._-]+|https:\/\/mail\.google\.com\/|openid|email|profile)$/.test(scope)) && new Set(value).size === value.length;
1965
2002
  }
@@ -1970,13 +2007,32 @@ function validDropboxFileScopes(value) {
1970
2007
 
1971
2008
  var ROUTINE_CONNECTION_CREDENTIALS_ENV = "OS_ROUTINE_CONNECTION_CREDENTIALS";
1972
2009
  function parseRoutineConnectionNames(value) {
1973
- if (!Array.isArray(value) || value.some((name2) => typeof name2 != "string" || !/^(gmail|airtable|dropbox)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name2)) || new Set(value).size !== value.length)
2010
+ if (!Array.isArray(value) || value.some((name2) => typeof name2 != "string" || !/^(gmail|airtable|dropbox|outlook|sharepoint)\/[a-z0-9][a-z0-9-]{0,62}$/.test(name2)) || new Set(value).size !== value.length)
1974
2011
  throw new Error("Invalid routine connections");
1975
2012
  return value;
1976
2013
  }
1977
2014
  var connectionUuid = (v) => typeof v == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(v);
1978
2015
  function runtimeConnection(lease) {
1979
2016
  switch (lease.provider) {
2017
+ case "outlook":
2018
+ return {
2019
+ id: `outlook/${lease.name}`,
2020
+ provider: lease.provider,
2021
+ name: lease.name,
2022
+ mailboxEmail: lease.mailboxEmail,
2023
+ accessToken: lease.accessToken,
2024
+ expiresAt: lease.expiresAt
2025
+ };
2026
+ case "sharepoint":
2027
+ return {
2028
+ id: `sharepoint/${lease.name}`,
2029
+ provider: lease.provider,
2030
+ name: lease.name,
2031
+ siteId: lease.siteId,
2032
+ siteUrl: lease.siteUrl,
2033
+ accessToken: lease.accessToken,
2034
+ expiresAt: lease.expiresAt
2035
+ };
1980
2036
  case "gmail":
1981
2037
  return {
1982
2038
  id: `gmail/${lease.name}`,
@@ -2014,6 +2070,11 @@ function parseConnectionLease(raw, now = Date.now()) {
2014
2070
  let v = raw;
2015
2071
  if (!v || typeof v != "object" || Array.isArray(v) || !connectionUuid(v.connectionId) || !connectionUuid(v.runId) || typeof v.name != "string" || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(v.name) || typeof v.accessToken != "string" || !/^[A-Za-z0-9._~+/-]{1,8192}={0,2}$/.test(v.accessToken))
2016
2072
  throw new Error("Invalid connection credential");
2073
+ if (v.provider === "outlook" || v.provider === "sharepoint") {
2074
+ if (!(v.provider === "outlook" ? Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,mailboxEmail,name,provider,runId" && validMicrosoftMailbox(v.mailboxEmail) : Object.keys(v).sort().join(",") === "accessToken,connectionId,expiresAt,name,provider,runId,siteId,siteUrl" && typeof v.siteUrl == "string" && canonicalSharePointSiteUrl(v.siteUrl) === v.siteUrl && validSharePointSiteId(v.siteId, v.siteUrl)) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now + 6e4 || Date.parse(v.expiresAt) > now + 36e5)
2075
+ throw new Error("Invalid connection credential");
2076
+ return v;
2077
+ }
2017
2078
  if (v.provider === "gmail") {
2018
2079
  if (Object.keys(v).sort().join(",") !== "accessToken,accountEmail,connectionId,expiresAt,name,provider,runId,scopes" || typeof v.accountEmail != "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.accountEmail) || !validGoogleScopes(v.scopes) || typeof v.expiresAt != "string" || !Number.isFinite(Date.parse(v.expiresAt)) || Date.parse(v.expiresAt) <= now + 6e4 || Date.parse(v.expiresAt) > now + 36e5)
2019
2080
  throw new Error("Invalid connection credential");
@@ -2281,7 +2342,17 @@ var connections = /* @__PURE__ */ runtimeConnections();
2281
2342
  var LOCAL_ROUTINE_VALUE_BYTES = 256 * 1024;
2282
2343
 
2283
2344
  function locationIdentity(location) {
2284
- let coordinates = location.provider === "os" ? [location.file] : location.provider === "gmail" ? [location.connection, location.message, location.attachment] : location.provider === "dropbox" ? [location.connection, location.file] : void 0;
2345
+ let coordinates = location.provider === "os" ? [location.file] : location.provider === "gmail" ? [location.connection, location.message, location.attachment] : location.provider === "dropbox" ? [location.connection, location.file] : location.provider === "outlook" ? [
2346
+ location.connection,
2347
+ location.message,
2348
+ ...location.attachment === void 0 ? [] : [location.attachment]
2349
+ ] : location.provider === "sharepoint" ? [
2350
+ location.connection,
2351
+ location.site,
2352
+ location.drive,
2353
+ location.item,
2354
+ ...location.version === void 0 ? [] : [location.version]
2355
+ ] : void 0;
2285
2356
  if (coordinates?.every((value) => typeof value == "string" && value.length > 0))
2286
2357
  return JSON.stringify([location.provider, ...coordinates]);
2287
2358
  }
@@ -2320,6 +2391,27 @@ var source = {
2320
2391
  ...input.path === void 0 ? {} : { path: input.path },
2321
2392
  ...input.url === void 0 ? {} : { url: input.url }
2322
2393
  };
2394
+ },
2395
+ outlook(input) {
2396
+ return {
2397
+ provider: "outlook",
2398
+ connection: input.connection,
2399
+ message: input.message,
2400
+ ...input.attachment === void 0 ? {} : { attachment: input.attachment },
2401
+ ...input.url === void 0 ? {} : { url: input.url }
2402
+ };
2403
+ },
2404
+ sharepoint(input) {
2405
+ return {
2406
+ provider: "sharepoint",
2407
+ connection: input.connection,
2408
+ site: input.site,
2409
+ drive: input.drive,
2410
+ item: input.item,
2411
+ ...input.version === void 0 ? {} : { version: input.version },
2412
+ ...input.path === void 0 ? {} : { path: input.path },
2413
+ ...input.url === void 0 ? {} : { url: input.url }
2414
+ };
2323
2415
  }
2324
2416
  },
2325
2417
  locations: {
@@ -2366,8 +2458,7 @@ var operations = {
2366
2458
  "items.listRecipientCandidates": ["itemId"],
2367
2459
  "items.addRecipient": ["itemId", "personId"],
2368
2460
  "questions.answer": ["itemId", "revision", "questionId", "response"],
2369
- "questions.searchRecords": ["itemId", "revision", "questionId", "query"],
2370
- "files.read": ["itemId", "fileId"]
2461
+ "questions.searchRecords": ["itemId", "revision", "questionId", "query"]
2371
2462
  };
2372
2463
  function assert(value) {
2373
2464
  if (!value) throw new Error("Invalid Inbox result");
@@ -3173,34 +3264,6 @@ async function send2(operation2, input, admitted) {
3173
3264
  if (response2.status !== 200)
3174
3265
  throw response2.body?.cancel().catch(() => {
3175
3266
  }), unavailable3();
3176
- if (operation2 === "files.read") {
3177
- if (!response2.body) throw unavailable3();
3178
- let source2 = response2.body, reader, size = 0, cancel = async (reason) => {
3179
- try {
3180
- await (reader ? reader.cancel(reason) : source2.cancel(reason));
3181
- } finally {
3182
- reader?.releaseLock();
3183
- }
3184
- }, body = new ReadableStream({
3185
- async pull(controller) {
3186
- try {
3187
- check(), reader ??= source2.getReader();
3188
- let next = await reader.read();
3189
- if (check(), next.done) {
3190
- reader.releaseLock(), controller.close();
3191
- return;
3192
- }
3193
- if (size += next.value.byteLength, size > 25 * 1024 * 1024) throw unavailable3();
3194
- controller.enqueue(next.value);
3195
- } catch (error) {
3196
- controller.error(error), await cancel(error).catch(() => {
3197
- });
3198
- }
3199
- },
3200
- cancel
3201
- }, { highWaterMark: 0 });
3202
- return new Response(body, { status: response2.status, headers: response2.headers });
3203
- }
3204
3267
  let bytes = await limitedBody(response2, INBOX_RESULT_BYTES);
3205
3268
  if (check(), !bytes) throw unavailable3();
3206
3269
  let value = JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(bytes)), parsed = parseInboxResult(operation2, value);
@@ -3279,8 +3342,7 @@ var inbox = {
3279
3342
  },
3280
3343
  answer: async (input) => await send2("questions.answer", input),
3281
3344
  searchRecords: async (input) => await send2("questions.searchRecords", input)
3282
- },
3283
- files: { read: async (input) => await send2("files.read", input) }
3345
+ }
3284
3346
  };
3285
3347
 
3286
3348
  var sources = /* @__PURE__ */ new WeakMap();
@@ -3796,7 +3858,6 @@ function routineRunHandle(operations2) {
3796
3858
  return Object.freeze({
3797
3859
  current: operations2.current,
3798
3860
  step: operations2.step,
3799
- ...operations2.publish ? { publish: operations2.publish } : {},
3800
3861
  async *watch() {
3801
3862
  let previous;
3802
3863
  for (; ; ) {
@@ -3927,7 +3988,7 @@ function summary(value, key, context, id3) {
3927
3988
  return fail3("execution_unavailable");
3928
3989
  }
3929
3990
  let run = value;
3930
- return (!only(run, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure,publication") || typeof run.id != "string" || !uuid2.test(run.id) || id3 !== void 0 && run.id !== id3 || run.routine !== key || run.placement !== "local" || !["queued", "running", "succeeded", "failed"].includes(run.status) || !timestamp(run.createdAt) || !optionalTimes(run) || !Array.isArray(run.steps) || run.steps.length > 64 || run.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,summary,detailAvailable") || typeof step.detailAvailable != "boolean" || !validStep(step)) || new Set(run.steps.map((step) => step.id)).size !== run.steps.length || Object.hasOwn(run, "result") && (run.status !== "succeeded" || !bounded2(run.result)) || run.failure !== void 0 && (run.status !== "failed" || !only(run.failure, "message") || !message(run.failure.message)) || run.publication !== void 0 && (run.status !== "succeeded" || !validPublication(run.publication))) && fail3("execution_unavailable"), run;
3991
+ return (!only(run, "id,routine,placement,status,createdAt,startedAt,finishedAt,steps,result,failure,local") || typeof run.id != "string" || !uuid2.test(run.id) || id3 !== void 0 && run.id !== id3 || run.routine !== key || run.placement !== "local" || !["queued", "running", "succeeded", "failed"].includes(run.status) || !timestamp(run.createdAt) || !optionalTimes(run) || !Array.isArray(run.steps) || run.steps.length > 64 || run.steps.some((step) => !only(step, "id,title,status,startedAt,finishedAt,summary,detailAvailable") || typeof step.detailAvailable != "boolean" || !validStep(step)) || new Set(run.steps.map((step) => step.id)).size !== run.steps.length || Object.hasOwn(run, "result") && (run.status !== "succeeded" || !bounded2(run.result)) || run.failure !== void 0 && (run.status !== "failed" || !only(run.failure, "message") || !message(run.failure.message)) || run.local !== void 0 && !validLocalActivity(run.local)) && fail3("execution_unavailable"), run;
3931
3992
  }
3932
3993
  function only(value, allowed) {
3933
3994
  return !!value && typeof value == "object" && !Array.isArray(value) && Object.keys(value).every((key) => allowed.split(",").includes(key));
@@ -3939,8 +4000,9 @@ function optionalTimes(value) {
3939
4000
  function validStep(step) {
3940
4001
  return typeof step.id == "string" && identifier.test(step.id) && typeof step.title == "string" && step.title.length > 0 && step.title.length <= 256 && ["pending", "running", "completed", "failed", "skipped"].includes(step.status) && optionalTimes(step) && (!Object.hasOwn(step, "summary") || bounded2(step.summary)) && (!Object.hasOwn(step, "data") || bounded2(step.data));
3941
4002
  }
3942
- function validPublication(value) {
3943
- return value && only(value, value.state === "failed" ? "state,message" : "state") && (["not_needed", "ready", "published"].includes(value.state) || value.state === "failed" && message(value.message));
4003
+ function validLocalActivity(value) {
4004
+ let paths = (value2) => Array.isArray(value2) && value2.every((path) => typeof path == "string" && path.length > 0 && path.length <= 4096 && !path.startsWith("/") && !path.includes("\\") && !path.split("/").some((part) => !part || part === "." || part === "..") && !/[\x00-\x1f\x7f]/.test(path));
4005
+ return value && only(value, "data,effects,git") && bounded2(value) && Array.isArray(value.data) && Array.isArray(value.effects) && value.data.every((item) => only(item, "repository,created,updated,deleted,failures") && typeof item.repository == "string" && identifier.test(item.repository) && paths(item.created) && paths(item.updated) && paths(item.deleted) && (item.failures === void 0 || Array.isArray(item.failures) && item.failures.every((code) => code === "unavailable"))) && value.effects.every((item) => only(item, "capability,operation,status,reference,summary") && ["files", "inbox", "ai"].includes(item.capability) && typeof item.operation == "string" && /^[a-zA-Z][a-zA-Z0-9-]{0,62}$/.test(item.operation) && ["completed", "failed"].includes(item.status) && (item.reference === void 0 || typeof item.reference == "string" && uuid2.test(item.reference)) && (!Object.hasOwn(item, "summary") || bounded2(item.summary))) && (value.git === void 0 || only(value.git, "branch,commit,dirty") && typeof value.git.dirty == "boolean" && (value.git.branch === void 0 || typeof value.git.branch == "string" && value.git.branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(value.git.branch)) && (value.git.commit === void 0 || typeof value.git.commit == "string" && /^[0-9a-f]{40}$/.test(value.git.commit)));
3944
4006
  }
3945
4007
  function jsonInput(value, ancestors = /* @__PURE__ */ new Set()) {
3946
4008
  if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return;
@@ -3976,9 +4038,6 @@ function handle(key, id3, context) {
3976
4038
  return fail3("execution_unavailable");
3977
4039
  }
3978
4040
  return (!only(value, "id,title,status,startedAt,finishedAt,summary,data") || value.id !== step || !validStep(value)) && fail3("execution_unavailable"), value;
3979
- },
3980
- async publish() {
3981
- return context.kind !== "local" && fail3("execution_unavailable"), summary(await request(key, `runs/${id3}/publish`, { method: "POST" }, SUMMARY_BYTES, context), key, context, id3);
3982
4041
  }
3983
4042
  });
3984
4043
  }
@@ -4058,21 +4117,31 @@ var app = /* @__PURE__ */ Object.freeze({
4058
4117
  })
4059
4118
  });
4060
4119
 
4061
- function validateFileAddOptions(value) {
4062
- let v = serializable(value);
4063
- if (!v || typeof v != "object" || Array.isArray(v) || Object.keys(v).some((k) => !["path", "name"].includes(k)) || typeof v.path != "string" || !v.path || v.path !== v.path.trim() || /[\\\x00-\x1f]/.test(v.path) || v.path.split("/").some((part) => !part || part === "." || part === "..") || /^[A-Za-z]:/.test(v.path))
4064
- throw new InboxContractError("File path must be relative to the configured working root");
4065
- if (v.name !== void 0 && (typeof v.name != "string" || !v.name || v.name !== v.name.trim() || v.name.length > 255 || /[\x00-\x1f\x7f/\\]/.test(v.name))) throw new InboxContractError("File name must be a safe filename");
4066
- return v;
4120
+ async function requestInboxPublication(operation2, request2, caller) {
4121
+ let attempt = () => {
4122
+ if (caller?.aborted) throw caller.reason;
4123
+ let timeout = AbortSignal.timeout(3e4);
4124
+ return request2(caller ? AbortSignal.any([caller, timeout]) : timeout);
4125
+ };
4126
+ if (operation2 !== "publish") return attempt();
4127
+ try {
4128
+ let response2 = await attempt();
4129
+ if (response2.status !== 408 && response2.status !== 429 && response2.status < 500) return response2;
4130
+ await response2.body?.cancel();
4131
+ } catch (error) {
4132
+ if (caller?.aborted) throw error;
4133
+ }
4134
+ if (caller?.aborted) throw caller.reason;
4135
+ return attempt();
4067
4136
  }
4068
4137
 
4069
4138
  function routinePublicationClient2(options = {}) {
4070
- let environment = {}, installed2 = routineTransport(), local2 = installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.OS_ROUTINE_WORKSPACE, capability = options.capability ?? environment.OS_ROUTINE_RUN;
4139
+ let environment = {}, installed2 = options.request ? void 0 : routineTransport(), local2 = options.request ? void 0 : installed2?.request ?? void 0, workspace = installed2 ? "installed" : options.workspace ?? environment.OS_ROUTINE_WORKSPACE, capability = options.capability ?? (options.request ? void 0 : environment.OS_ROUTINE_RUN);
4071
4140
  if (!workspace || !/^[a-z0-9][a-z0-9-]*$/.test(workspace) || capability !== void 0 && !/^[0-9a-f]{64}$/.test(capability))
4072
4141
  throw new Error("A workspace and valid optional routine capability are required");
4073
- let workingRoot = options.workingRoot ?? environment.OS_INBOX_WORKING_ROOT ?? void 0, headers = capability ? { "x-os-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
4142
+ let headers = capability ? { "x-os-run": capability } : {}, request2 = options.request ?? (capability ? async (path, init2) => {
4074
4143
  let origin = `https://${workspace}.oddington.ai`, target = new URL(path, `${origin}/`);
4075
- if (workspace.length > 63 || ["auth", "www", "api", "os"].includes(workspace) || target.origin !== origin || target.search || target.hash || target.username || target.password || !/^\/api\/inbox\/(check|publish|resolve|files)$/.test(path) || init2?.method !== "POST")
4144
+ if (workspace.length > 63 || ["auth", "www", "api", "os"].includes(workspace) || target.origin !== origin || target.search || target.hash || target.username || target.password || !/^\/api\/inbox\/(check|publish|resolve)$/.test(path) || init2?.method !== "POST")
4076
4145
  throw new Error("Invalid routine endpoint");
4077
4146
  return fetch(target, { ...init2, redirect: "error" });
4078
4147
  } : async () => {
@@ -4080,11 +4149,12 @@ function routinePublicationClient2(options = {}) {
4080
4149
  });
4081
4150
  async function send3(operation2, body) {
4082
4151
  if (local2) return await local2(operation2, body);
4083
- let response2 = await request2(`/api/inbox/${operation2}`, {
4152
+ let response2 = await requestInboxPublication(operation2, (signal) => request2(`/api/inbox/${operation2}`, {
4084
4153
  method: "POST",
4085
4154
  headers: { "content-type": "application/json", ...headers },
4086
- body: JSON.stringify(body)
4087
- }), result2 = await response2.json();
4155
+ body: JSON.stringify(body),
4156
+ signal
4157
+ })), result2 = await response2.json();
4088
4158
  if (!response2.ok) throw new Error(result2.error ?? "Could not confirm routine publication");
4089
4159
  return result2;
4090
4160
  }
@@ -4097,13 +4167,6 @@ function routinePublicationClient2(options = {}) {
4097
4167
  await send3("resolve", body);
4098
4168
  }
4099
4169
  }),
4100
- files: {
4101
- async add(value) {
4102
- let input = validateFileAddOptions(value);
4103
- if (local2) return validateInboxFile(await local2("files/add", input));
4104
- throw workingRoot ? new Error("Inbox file reads require a Node working root") : new Error("Inbox file reads require a working root");
4105
- }
4106
- },
4107
4170
  async check(body) {
4108
4171
  await send3("check", { requestKey: body.requestKey, item: validatePublication(body.item) });
4109
4172
  }