@nodaro/sdk 2.5.0 → 2.6.0

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/index.js CHANGED
@@ -146,6 +146,20 @@ var JobAbortedError = class extends NodaroError {
146
146
  }
147
147
  jobId;
148
148
  };
149
+ var StudioPreviewUnavailable = class extends NodaroError {
150
+ constructor(message = "This deployment does not preview operation batches; nothing was sent") {
151
+ super(message, "studio_preview_unavailable", 0);
152
+ this.name = "StudioPreviewUnavailable";
153
+ }
154
+ };
155
+ var StudioPreviewAppliedError = class extends NodaroError {
156
+ constructor(applied, message = applied ? "Asked for a preview and this deployment APPLIED the batch; the change is written \u2014 see `applied`" : "Asked for a preview and this deployment answered with neither one nor a body to read; the batch may have been applied \u2014 re-read the production before deciding anything") {
157
+ super(message, "studio_preview_applied", 0);
158
+ this.applied = applied;
159
+ this.name = "StudioPreviewAppliedError";
160
+ }
161
+ applied;
162
+ };
149
163
  var JobHeldError = class extends NodaroError {
150
164
  constructor(message, jobId) {
151
165
  super(message, "job_held", 0);
@@ -2037,6 +2051,47 @@ var LlmResource = class {
2037
2051
  }
2038
2052
  };
2039
2053
 
2054
+ // src/sse.ts
2055
+ async function* readSseStream(res, opts = {}) {
2056
+ if (!res.ok) {
2057
+ let errBody = {};
2058
+ try {
2059
+ errBody = await res.json();
2060
+ } catch {
2061
+ }
2062
+ throwFromResponse(res.status, errBody);
2063
+ }
2064
+ if (!res.body) {
2065
+ throw new NodaroError(`${opts.label ?? "event stream"} has no response body`, "empty_stream", res.status);
2066
+ }
2067
+ const reader = res.body.getReader();
2068
+ const decoder = new TextDecoder();
2069
+ let buffer = "";
2070
+ try {
2071
+ for (; ; ) {
2072
+ const { done, value } = await reader.read();
2073
+ if (done) break;
2074
+ buffer += decoder.decode(value, { stream: true });
2075
+ let sep;
2076
+ while ((sep = buffer.indexOf("\n\n")) >= 0) {
2077
+ const frame = buffer.slice(0, sep);
2078
+ buffer = buffer.slice(sep + 2);
2079
+ for (const line of frame.split("\n")) {
2080
+ if (!line.startsWith("data:")) continue;
2081
+ try {
2082
+ yield JSON.parse(line.slice(5).trim());
2083
+ } catch {
2084
+ }
2085
+ }
2086
+ }
2087
+ }
2088
+ } finally {
2089
+ reader.releaseLock();
2090
+ await res.body.cancel().catch(() => {
2091
+ });
2092
+ }
2093
+ }
2094
+
2040
2095
  // src/resources/media.ts
2041
2096
  var MediaResource = class {
2042
2097
  constructor(client) {
@@ -2073,43 +2128,7 @@ var MediaResource = class {
2073
2128
  headers: token ? { Authorization: `Bearer ${token}` } : {},
2074
2129
  signal: opts.signal
2075
2130
  });
2076
- if (!res.ok) {
2077
- let errBody = {};
2078
- try {
2079
- errBody = await res.json();
2080
- } catch {
2081
- }
2082
- throwFromResponse(res.status, errBody);
2083
- }
2084
- if (!res.body) {
2085
- throw new NodaroError("progress stream has no response body", "empty_stream", res.status);
2086
- }
2087
- const reader = res.body.getReader();
2088
- const decoder = new TextDecoder();
2089
- let buffer = "";
2090
- try {
2091
- for (; ; ) {
2092
- const { done, value } = await reader.read();
2093
- if (done) break;
2094
- buffer += decoder.decode(value, { stream: true });
2095
- let sep;
2096
- while ((sep = buffer.indexOf("\n\n")) >= 0) {
2097
- const frame = buffer.slice(0, sep);
2098
- buffer = buffer.slice(sep + 2);
2099
- for (const line of frame.split("\n")) {
2100
- if (!line.startsWith("data:")) continue;
2101
- try {
2102
- yield JSON.parse(line.slice(5).trim());
2103
- } catch {
2104
- }
2105
- }
2106
- }
2107
- }
2108
- } finally {
2109
- reader.releaseLock();
2110
- await res.body.cancel().catch(() => {
2111
- });
2112
- }
2131
+ yield* readSseStream(res, { label: "progress stream" });
2113
2132
  }
2114
2133
  /**
2115
2134
  * Copy an external media URL into your Nodaro storage (`POST /v1/save-to-storage`)
@@ -2647,19 +2666,27 @@ var StudioProductionsResource = class {
2647
2666
  );
2648
2667
  return res.data;
2649
2668
  }
2650
- /**
2651
- * Apply a batch of operations. Atomic: one bad operation refuses the whole
2652
- * batch with a `StudioOpError` naming its index, and nothing is written. On
2653
- * success adopt `production` wholesale and carry `version` forward as the
2654
- * next `baseVersion`.
2655
- */
2656
2669
  async ops(productionId, input) {
2657
- const res = await this.client.request(
2670
+ if (input.dryRun !== true) {
2671
+ const res2 = await this.client.request(
2672
+ "POST",
2673
+ this.path(productionId, "/ops"),
2674
+ { body: input }
2675
+ );
2676
+ return res2.data;
2677
+ }
2678
+ const ping = await this.client.request(
2658
2679
  "POST",
2659
2680
  this.path(productionId, "/ops"),
2660
- { body: input }
2681
+ { body: { ops: [], dryRun: true } }
2661
2682
  );
2662
- return res.data;
2683
+ if (ping?.data?.dryRun !== true) throw new StudioPreviewUnavailable();
2684
+ const res = await this.client.request("POST", this.path(productionId, "/ops"), { body: input });
2685
+ const data = res?.data;
2686
+ if (data?.dryRun !== true) {
2687
+ throw new StudioPreviewAppliedError(data);
2688
+ }
2689
+ return data;
2663
2690
  }
2664
2691
  /**
2665
2692
  * Land every generation that has finished since you last looked, and report
@@ -2867,6 +2894,103 @@ var StudioResource = class {
2867
2894
  }
2868
2895
  };
2869
2896
 
2897
+ // src/resources/copilot.ts
2898
+ var COPILOT_FRAME_TYPES = /* @__PURE__ */ new Set([
2899
+ "metadata",
2900
+ "token",
2901
+ "tool_call",
2902
+ "workflow_updated",
2903
+ "workflow_created",
2904
+ "run_proposed",
2905
+ "memory_saved",
2906
+ "usage",
2907
+ "done",
2908
+ "error"
2909
+ ]);
2910
+ function isCopilotFrame(value) {
2911
+ if (typeof value !== "object" || value === null) return false;
2912
+ const type = value.type;
2913
+ return typeof type === "string" && COPILOT_FRAME_TYPES.has(type);
2914
+ }
2915
+ var CopilotResource = class {
2916
+ constructor(client) {
2917
+ this.client = client;
2918
+ }
2919
+ client;
2920
+ /**
2921
+ * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on
2922
+ * a workflow the server creates from `prompt`. Re-opening a workflow that
2923
+ * already has an active thread answers THAT thread rather than a second one.
2924
+ */
2925
+ create(input) {
2926
+ return this.client.request("POST", "/v1/copilot/threads", { body: input });
2927
+ }
2928
+ /**
2929
+ * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),
2930
+ * or `null` when the user has none open on it.
2931
+ */
2932
+ list(params) {
2933
+ return this.client.request("GET", "/v1/copilot/threads", { query: { workflowId: params.workflowId } });
2934
+ }
2935
+ /**
2936
+ * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads
2937
+ * only what followed that sequence number (the panel's catch-up); `limit`
2938
+ * caps the page at the server's own ceiling.
2939
+ */
2940
+ get(id, opts = {}) {
2941
+ return this.client.request("GET", `/v1/copilot/threads/${encodeURIComponent(id)}`, {
2942
+ query: { ...opts.after !== void 0 ? { after: opts.after } : {}, ...opts.limit !== void 0 ? { limit: opts.limit } : {} }
2943
+ });
2944
+ }
2945
+ /**
2946
+ * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not
2947
+ * deletion — the messages stay readable. Refused while a turn is running.
2948
+ */
2949
+ archive(id) {
2950
+ return this.client.request("DELETE", `/v1/copilot/threads/${encodeURIComponent(id)}`);
2951
+ }
2952
+ /**
2953
+ * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the
2954
+ * turn it asked to stop; the turn's own stream ends with a `done` frame.
2955
+ */
2956
+ cancel(id) {
2957
+ return this.client.request("POST", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`);
2958
+ }
2959
+ /**
2960
+ * Send one message and iterate the turn's frames
2961
+ * (`POST /v1/copilot/threads/:id/messages`, server-sent events).
2962
+ *
2963
+ * Deliberately NOT routed through `client.request`: that path arms an abort
2964
+ * timer around the whole exchange, and a turn legitimately runs for minutes —
2965
+ * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller
2966
+ * owns the lifetime instead: pass `signal` to end the stream, or stop
2967
+ * iterating (the reader cancels the body, which ends the request).
2968
+ *
2969
+ * A frame kind this package does not model is skipped rather than thrown, so
2970
+ * a newer server cannot break an older caller.
2971
+ */
2972
+ async *stream(threadId, opts) {
2973
+ const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`;
2974
+ const token = await this.client.auth.getToken();
2975
+ const res = await this.client.fetch(url, {
2976
+ method: "POST",
2977
+ headers: {
2978
+ "Content-Type": "application/json",
2979
+ ...token ? { Authorization: `Bearer ${token}` } : {}
2980
+ },
2981
+ body: JSON.stringify({
2982
+ message: opts.message,
2983
+ ...opts.baseVersion !== void 0 ? { baseVersion: opts.baseVersion } : {},
2984
+ ...opts.tier ? { tier: opts.tier } : {}
2985
+ }),
2986
+ signal: opts.signal
2987
+ });
2988
+ for await (const value of readSseStream(res, { label: "copilot stream" })) {
2989
+ if (isCopilotFrame(value)) yield value;
2990
+ }
2991
+ }
2992
+ };
2993
+
2870
2994
  // src/resources/community.ts
2871
2995
  var CommunityResource = class {
2872
2996
  constructor(client) {
@@ -3248,7 +3372,7 @@ var WorkspacesResource = class {
3248
3372
  return this.client.requestText("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, format: "csv" } });
3249
3373
  }
3250
3374
  };
3251
- var SDK_VERSION = "2.5.0" ;
3375
+ var SDK_VERSION = "2.6.0" ;
3252
3376
  var CLIENT_HEADER = "X-Nodaro-Client";
3253
3377
  var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
3254
3378
  var NodaroClient = class _NodaroClient {
@@ -3300,6 +3424,7 @@ var NodaroClient = class _NodaroClient {
3300
3424
  shots;
3301
3425
  recast;
3302
3426
  studio;
3427
+ copilot;
3303
3428
  community;
3304
3429
  templates;
3305
3430
  tutorials;
@@ -3346,6 +3471,7 @@ var NodaroClient = class _NodaroClient {
3346
3471
  this.shots = new ShotsResource(this);
3347
3472
  this.recast = new RecastResource(this);
3348
3473
  this.studio = new StudioResource(this);
3474
+ this.copilot = new CopilotResource(this);
3349
3475
  this.community = new CommunityResource(this);
3350
3476
  this.templates = new TemplatesResource(this);
3351
3477
  this.tutorials = new TutorialsResource(this);
@@ -3507,6 +3633,6 @@ function supabaseAuth(supabase) {
3507
3633
  };
3508
3634
  }
3509
3635
 
3510
- export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CreaturesResource, CreditsResource, DeveloperAppsResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
3636
+ export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
3511
3637
  //# sourceMappingURL=index.js.map
3512
3638
  //# sourceMappingURL=index.js.map