@runappsai/sdk 0.3.1 → 0.5.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/README.md +225 -95
- package/dist/activity-tracker.js +1 -1
- package/dist/browser-auth.d.ts +2 -1
- package/dist/browser-auth.d.ts.map +1 -1
- package/dist/browser-auth.js +61 -32
- package/dist/browser-auth.js.map +1 -1
- package/dist/client.d.ts +8 -8
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +10 -4
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/media.d.ts +2 -2
- package/dist/media.js +2 -2
- package/dist/sdk.umd.js +2 -2
- package/dist/sdk.umd.js.map +1 -1
- package/dist/transport.d.ts +2 -2
- package/package.json +1 -1
- package/src/activity-tracker.ts +1 -1
- package/src/browser-auth.ts +62 -31
- package/src/client.ts +19 -12
- package/src/index.ts +2 -0
- package/src/media.ts +2 -2
- package/src/transport.ts +2 -2
package/dist/transport.d.ts
CHANGED
|
@@ -12,8 +12,8 @@ export interface TransportOptions {
|
|
|
12
12
|
apiKey?: string;
|
|
13
13
|
/** Dynamic resolver — called immediately before each request. Use this
|
|
14
14
|
* when the token is short-lived and refreshed externally (e.g. running
|
|
15
|
-
* inside
|
|
16
|
-
* `
|
|
15
|
+
* inside an app bundle that exposes
|
|
16
|
+
* its own `getToken()`). The result is awaited per request, so
|
|
17
17
|
* the caller can return a Promise that hits a token endpoint. Wins
|
|
18
18
|
* over `apiKey` when both are supplied. */
|
|
19
19
|
apiKeyResolver?: () => string | Promise<string>;
|
package/package.json
CHANGED
package/src/activity-tracker.ts
CHANGED
|
@@ -153,7 +153,7 @@ export class ActivityTracker {
|
|
|
153
153
|
h();
|
|
154
154
|
} catch (err) {
|
|
155
155
|
// eslint-disable-next-line no-console
|
|
156
|
-
console.error("[
|
|
156
|
+
console.error("[runapps sdk] ActivityTracker onChange listener threw:", err);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|
package/src/browser-auth.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
// browser-auth.ts — opt-in runapps.ai auth flow for browser bundles.
|
|
2
2
|
//
|
|
3
|
-
// Activated by `new RunApps({ authProvider: "
|
|
3
|
+
// Activated by `new RunApps({ authProvider: "runapps", baseURL: "..." })`.
|
|
4
4
|
// In Node and other non-window environments this module's runtime code
|
|
5
5
|
// short-circuits to no-ops; it ships with the IIFE bundle for resource
|
|
6
6
|
// bundles loaded via <script> tag.
|
|
7
7
|
//
|
|
8
8
|
// Responsibilities:
|
|
9
|
-
// - Detect & consume `#
|
|
9
|
+
// - Detect & consume the `#runapps_token=…` URL fragment planted by the
|
|
10
10
|
// grant page after a successful sign-in.
|
|
11
11
|
// - Trigger a redirect-based grant flow when the bundle calls a
|
|
12
12
|
// gateway endpoint without a fresh token.
|
|
13
|
-
// - In iframe contexts (
|
|
13
|
+
// - In iframe contexts (a RunApps page embedding the app), handshake
|
|
14
14
|
// with the parent via postMessage to silently obtain a token.
|
|
15
15
|
// - Render an unobtrusive identity badge in the bottom-right corner
|
|
16
|
-
// so the end user can see WHICH
|
|
16
|
+
// so the end user can see WHICH RunApps account is paying for the
|
|
17
17
|
// calls being made on their behalf.
|
|
18
18
|
//
|
|
19
19
|
// Why redirect (not popup): under COOP=same-origin (required so the
|
|
@@ -103,7 +103,10 @@ const TOKEN_REFRESH_MARGIN_S = 60;
|
|
|
103
103
|
// project (iframe / parent-handshake mode) fall back to the legacy
|
|
104
104
|
// unsuffixed key, which preserves back-compat for already-persisted
|
|
105
105
|
// tokens after upgrade.
|
|
106
|
-
const STORAGE_KEY_BASE = "
|
|
106
|
+
const STORAGE_KEY_BASE = "__runapps_auth_v1__";
|
|
107
|
+
// Written by SDK 0.3 and earlier; read once and migrated, so an upgrade
|
|
108
|
+
// keeps the user signed in.
|
|
109
|
+
const LEGACY_STORAGE_KEY_BASE = "__runjobs_auth_v1__";
|
|
107
110
|
// Set when the user clicks "Sign out". While present, getToken() must
|
|
108
111
|
// not silently redirect to the grant page even though the user still
|
|
109
112
|
// has a runapps.ai cookie — otherwise the backend's auto-grant turns
|
|
@@ -111,7 +114,8 @@ const STORAGE_KEY_BASE = "__runjobs_auth_v1__";
|
|
|
111
114
|
// signIn() so the user can come back. Same per-project namespacing
|
|
112
115
|
// rationale as STORAGE_KEY_BASE — signing out of bundle A shouldn't
|
|
113
116
|
// also sign out bundle B that happens to share the origin.
|
|
114
|
-
const SIGNED_OUT_KEY_BASE = "
|
|
117
|
+
const SIGNED_OUT_KEY_BASE = "__runapps_signed_out_v1__";
|
|
118
|
+
const LEGACY_SIGNED_OUT_KEY_BASE = "__runjobs_signed_out_v1__";
|
|
115
119
|
|
|
116
120
|
/** Compose the localStorage key for an auth slot. `null` project
|
|
117
121
|
* yields the base key (iframe-mode and pre-v1.x bundles), which
|
|
@@ -125,6 +129,14 @@ function signedOutKey(project: string | null): string {
|
|
|
125
129
|
return project ? `${SIGNED_OUT_KEY_BASE}:${project}` : SIGNED_OUT_KEY_BASE;
|
|
126
130
|
}
|
|
127
131
|
|
|
132
|
+
function legacyStorageKey(project: string | null): string {
|
|
133
|
+
return project ? `${LEGACY_STORAGE_KEY_BASE}:${project}` : LEGACY_STORAGE_KEY_BASE;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function legacySignedOutKey(project: string | null): string {
|
|
137
|
+
return project ? `${LEGACY_SIGNED_OUT_KEY_BASE}:${project}` : LEGACY_SIGNED_OUT_KEY_BASE;
|
|
138
|
+
}
|
|
139
|
+
|
|
128
140
|
interface PersistedAuth {
|
|
129
141
|
token: string;
|
|
130
142
|
expiresAt: number;
|
|
@@ -398,6 +410,9 @@ export class BrowserAuth {
|
|
|
398
410
|
params.set("redirect_to", args.redirectTo);
|
|
399
411
|
params.set("scheme", args.scheme);
|
|
400
412
|
if (this.project) params.set("project_id", this.project);
|
|
413
|
+
// Ask for #runapps_token=…; a platform that predates it answers with
|
|
414
|
+
// #runjobs_token=…, which consumeFragment also accepts.
|
|
415
|
+
params.set("token_name", "runapps_token");
|
|
401
416
|
return this.origin + "/api/sdk/grant?" + params.toString();
|
|
402
417
|
}
|
|
403
418
|
|
|
@@ -454,8 +469,14 @@ export class BrowserAuth {
|
|
|
454
469
|
private loadPersisted() {
|
|
455
470
|
if (typeof localStorage === "undefined") return;
|
|
456
471
|
try {
|
|
457
|
-
|
|
458
|
-
if (!raw)
|
|
472
|
+
let raw = localStorage.getItem(storageKey(this.project));
|
|
473
|
+
if (!raw) {
|
|
474
|
+
// Upgrade from SDK 0.3 or earlier: move the token to the new key.
|
|
475
|
+
raw = localStorage.getItem(legacyStorageKey(this.project));
|
|
476
|
+
if (!raw) return;
|
|
477
|
+
localStorage.setItem(storageKey(this.project), raw);
|
|
478
|
+
localStorage.removeItem(legacyStorageKey(this.project));
|
|
479
|
+
}
|
|
459
480
|
const data = JSON.parse(raw) as Partial<PersistedAuth>;
|
|
460
481
|
if (!data.token || !data.origin) return;
|
|
461
482
|
// Pin to the gateway origin we were constructed with — a bundle
|
|
@@ -480,13 +501,15 @@ export class BrowserAuth {
|
|
|
480
501
|
if (typeof localStorage === "undefined") return;
|
|
481
502
|
try {
|
|
482
503
|
localStorage.removeItem(storageKey(this.project));
|
|
504
|
+
localStorage.removeItem(legacyStorageKey(this.project));
|
|
483
505
|
} catch { /* ignore */ }
|
|
484
506
|
}
|
|
485
507
|
|
|
486
508
|
private isSignedOut(): boolean {
|
|
487
509
|
if (typeof localStorage === "undefined") return false;
|
|
488
510
|
try {
|
|
489
|
-
return localStorage.getItem(signedOutKey(this.project)) === "1"
|
|
511
|
+
return localStorage.getItem(signedOutKey(this.project)) === "1" ||
|
|
512
|
+
localStorage.getItem(legacySignedOutKey(this.project)) === "1";
|
|
490
513
|
} catch { return false; }
|
|
491
514
|
}
|
|
492
515
|
|
|
@@ -501,17 +524,19 @@ export class BrowserAuth {
|
|
|
501
524
|
if (typeof localStorage === "undefined") return;
|
|
502
525
|
try {
|
|
503
526
|
localStorage.removeItem(signedOutKey(this.project));
|
|
527
|
+
localStorage.removeItem(legacySignedOutKey(this.project));
|
|
504
528
|
} catch { /* ignore */ }
|
|
505
529
|
}
|
|
506
530
|
|
|
507
531
|
private removeBadge() {
|
|
508
532
|
if (typeof document === "undefined") return;
|
|
509
|
-
document.getElementById("
|
|
533
|
+
document.getElementById("__runapps_identity__")?.remove();
|
|
510
534
|
}
|
|
511
535
|
|
|
512
|
-
/** Parse the #
|
|
536
|
+
/** Parse the #runapps_token=… fragment (or the older #runjobs_token=…),
|
|
537
|
+
* install, then strip it. */
|
|
513
538
|
private consumeFragment(): boolean {
|
|
514
|
-
if (!location.hash || location.hash
|
|
539
|
+
if (!location.hash || !/(^#|&)run(apps|jobs)_token=/.test(location.hash))
|
|
515
540
|
return false;
|
|
516
541
|
const params: Record<string, string> = {};
|
|
517
542
|
location.hash
|
|
@@ -521,7 +546,8 @@ export class BrowserAuth {
|
|
|
521
546
|
const i = kv.indexOf("=");
|
|
522
547
|
if (i >= 0) params[decodeURIComponent(kv.slice(0, i))] = decodeURIComponent(kv.slice(i + 1));
|
|
523
548
|
});
|
|
524
|
-
|
|
549
|
+
const token = params.runapps_token || params.runjobs_token;
|
|
550
|
+
if (!token) return false;
|
|
525
551
|
let user: BrowserUser | undefined;
|
|
526
552
|
if (params.user) {
|
|
527
553
|
try {
|
|
@@ -531,7 +557,7 @@ export class BrowserAuth {
|
|
|
531
557
|
}
|
|
532
558
|
}
|
|
533
559
|
this.setToken(
|
|
534
|
-
|
|
560
|
+
token,
|
|
535
561
|
parseInt(params.expires_at ?? "", 10) || 0,
|
|
536
562
|
user,
|
|
537
563
|
);
|
|
@@ -559,7 +585,7 @@ export class BrowserAuth {
|
|
|
559
585
|
const data = e.data as
|
|
560
586
|
| { type: string; token?: string; expires_at?: number; user?: BrowserUser }
|
|
561
587
|
| null;
|
|
562
|
-
if (data && data.type === "runjobs:token" && data.token) {
|
|
588
|
+
if (data && (data.type === "runapps:token" || data.type === "runjobs:token") && data.token) {
|
|
563
589
|
this.setToken(data.token, data.expires_at ?? 0, data.user);
|
|
564
590
|
cleanup();
|
|
565
591
|
resolve();
|
|
@@ -576,7 +602,8 @@ export class BrowserAuth {
|
|
|
576
602
|
const post = () => {
|
|
577
603
|
if (done) return;
|
|
578
604
|
try {
|
|
579
|
-
window.parent.postMessage({ type: "
|
|
605
|
+
window.parent.postMessage({ type: "runapps:request-token" }, this.origin);
|
|
606
|
+
window.parent.postMessage({ type: "runjobs:request-token" }, this.origin); // older embedders
|
|
580
607
|
} catch (err) {
|
|
581
608
|
cleanup();
|
|
582
609
|
reject(err);
|
|
@@ -604,7 +631,7 @@ export class BrowserAuth {
|
|
|
604
631
|
* can't reach back into the bundle window via `window.opener`. */
|
|
605
632
|
private renderBadge() {
|
|
606
633
|
if (typeof document === "undefined" || !this.userInfo) return;
|
|
607
|
-
const ID = "
|
|
634
|
+
const ID = "__runapps_identity__";
|
|
608
635
|
const dashboardUrl = `${this.origin}/dashboard`;
|
|
609
636
|
const ready = (cb: () => void) =>
|
|
610
637
|
document.body ? cb() : document.addEventListener("DOMContentLoaded", cb);
|
|
@@ -689,7 +716,7 @@ interface MountOpts {
|
|
|
689
716
|
* downward); `right` vs `left` flips horizontal anchor on both.
|
|
690
717
|
*/
|
|
691
718
|
/**
|
|
692
|
-
* Inject the `@keyframes
|
|
719
|
+
* Inject the `@keyframes __runapps_led_pulse__` rule into the document
|
|
693
720
|
* head ONCE (idempotent — re-mounts and multiple SDK instances on the
|
|
694
721
|
* same page share the same rule). Must run at badge mount time so
|
|
695
722
|
* the LED's `animation` CSS resolves the keyframe reference the
|
|
@@ -699,11 +726,11 @@ interface MountOpts {
|
|
|
699
726
|
*/
|
|
700
727
|
function ensurePulseKeyframes(): void {
|
|
701
728
|
if (typeof document === "undefined") return;
|
|
702
|
-
if (document.getElementById("
|
|
729
|
+
if (document.getElementById("__runapps_kf__")) return;
|
|
703
730
|
const style = document.createElement("style");
|
|
704
|
-
style.id = "
|
|
731
|
+
style.id = "__runapps_kf__";
|
|
705
732
|
style.textContent =
|
|
706
|
-
"@keyframes
|
|
733
|
+
"@keyframes __runapps_led_pulse__ {" +
|
|
707
734
|
" 0% { box-shadow: 0 0 0 0 rgba(59,130,246,0.7); }" +
|
|
708
735
|
" 70% { box-shadow: 0 0 0 6px rgba(59,130,246,0); }" +
|
|
709
736
|
" 100% { box-shadow: 0 0 0 0 rgba(59,130,246,0); }" +
|
|
@@ -740,7 +767,8 @@ function badgeCornerStyles(position: BadgePosition): {
|
|
|
740
767
|
|
|
741
768
|
/** Cookie key the saved badge position lives under. URI-safe, prefixed
|
|
742
769
|
* so other libraries / consumers don't accidentally collide. */
|
|
743
|
-
const BADGE_POS_COOKIE = "
|
|
770
|
+
const BADGE_POS_COOKIE = "__runapps_badge_pos__";
|
|
771
|
+
const LEGACY_BADGE_POS_COOKIE = "__runjobs_badge_pos__";
|
|
744
772
|
|
|
745
773
|
/** Pixel threshold a pointer must travel before we treat the gesture
|
|
746
774
|
* as a drag instead of a click. Below this, it's a normal badge tap
|
|
@@ -754,12 +782,15 @@ const BADGE_EDGE_INSET_PX = 8;
|
|
|
754
782
|
|
|
755
783
|
function readBadgePosCookie(): { x: number; y: number } | null {
|
|
756
784
|
if (typeof document === "undefined") return null;
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
785
|
+
const cookies = document.cookie.split(";").map((s) => s.trim());
|
|
786
|
+
let name = BADGE_POS_COOKIE;
|
|
787
|
+
let raw = cookies.find((s) => s.startsWith(name + "="));
|
|
788
|
+
if (!raw) {
|
|
789
|
+
name = LEGACY_BADGE_POS_COOKIE;
|
|
790
|
+
raw = cookies.find((s) => s.startsWith(name + "="));
|
|
791
|
+
}
|
|
761
792
|
if (!raw) return null;
|
|
762
|
-
const value = decodeURIComponent(raw.slice(
|
|
793
|
+
const value = decodeURIComponent(raw.slice(name.length + 1));
|
|
763
794
|
const parts = value.split(",");
|
|
764
795
|
const rawX = parts[0];
|
|
765
796
|
const rawY = parts[1];
|
|
@@ -1322,7 +1353,7 @@ function updateLED(led: HTMLSpanElement, snap: ActivitySnapshot): void {
|
|
|
1322
1353
|
// CSS-driven pulse via box-shadow ring expanding outward —
|
|
1323
1354
|
// single keyframe loop, cheaper than animating opacity.
|
|
1324
1355
|
led.style.boxShadow = "0 0 0 0 rgba(59,130,246,0.7)";
|
|
1325
|
-
led.style.animation = "
|
|
1356
|
+
led.style.animation = "__runapps_led_pulse__ 1.2s ease-out infinite";
|
|
1326
1357
|
break;
|
|
1327
1358
|
case "error":
|
|
1328
1359
|
led.style.background = "#ef4444";
|
|
@@ -1353,14 +1384,14 @@ function createPopover(dashboardUrl: string, anchorCss: string, onSignOut: () =>
|
|
|
1353
1384
|
"cursor:default",
|
|
1354
1385
|
"text-align:left",
|
|
1355
1386
|
].join(";");
|
|
1356
|
-
pop.setAttribute("data-
|
|
1387
|
+
pop.setAttribute("data-runapps-popover", "1");
|
|
1357
1388
|
pop.addEventListener("click", (e) => e.stopPropagation());
|
|
1358
1389
|
|
|
1359
1390
|
// The popover's content is rebuilt on every redraw to keep DOM
|
|
1360
1391
|
// diffing simple. ~3 sections × ~6 children = ~20 nodes, no
|
|
1361
1392
|
// measurable cost at the 6 Hz redraw rate.
|
|
1362
1393
|
const inner = document.createElement("div");
|
|
1363
|
-
inner.setAttribute("data-
|
|
1394
|
+
inner.setAttribute("data-runapps-popover-content", "1");
|
|
1364
1395
|
pop.appendChild(inner);
|
|
1365
1396
|
|
|
1366
1397
|
const footer = document.createElement("div");
|
|
@@ -1411,7 +1442,7 @@ function createPopover(dashboardUrl: string, anchorCss: string, onSignOut: () =>
|
|
|
1411
1442
|
}
|
|
1412
1443
|
|
|
1413
1444
|
function updatePopover(pop: HTMLDivElement, snap: ActivitySnapshot): void {
|
|
1414
|
-
const inner = pop.querySelector('[data-
|
|
1445
|
+
const inner = pop.querySelector('[data-runapps-popover-content]') as HTMLDivElement | null;
|
|
1415
1446
|
if (!inner) return;
|
|
1416
1447
|
inner.innerHTML = "";
|
|
1417
1448
|
const now = Date.now();
|
package/src/client.ts
CHANGED
|
@@ -27,13 +27,13 @@ const DEFAULT_BASE_URL = "https://www.runapps.ai";
|
|
|
27
27
|
* in browsers — in Node this falls back to throwing the same
|
|
28
28
|
* "missing apiKey" error you'd get with no auth config.
|
|
29
29
|
*/
|
|
30
|
-
// "runapps"
|
|
31
|
-
//
|
|
30
|
+
// "runapps" turns on the platform sign-in. "runjobs" is a deprecated
|
|
31
|
+
// alias for it, kept so code written before the rename keeps working.
|
|
32
32
|
export type AuthProvider = "static" | "runapps" | "runjobs";
|
|
33
33
|
|
|
34
34
|
export interface ClientOptions {
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
35
|
+
/** A personal API key (`rk_…`) or another static key. Leave it out in an
|
|
36
|
+
* app published on RunApps: the browser client then signs the user in. */
|
|
37
37
|
apiKey?: string;
|
|
38
38
|
/**
|
|
39
39
|
* Dynamic API key resolver. See `AuthProvider` for the typical
|
|
@@ -43,13 +43,13 @@ export interface ClientOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
apiKeyResolver?: () => string | Promise<string>;
|
|
45
45
|
/**
|
|
46
|
-
* Auth strategy
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* Auth strategy. Rarely needed: in a browser with no `apiKey` /
|
|
47
|
+
* `apiKeyResolver` the client uses `"runapps"` (the platform sign-in),
|
|
48
|
+
* otherwise `"static"` (the key you pass).
|
|
49
49
|
*/
|
|
50
50
|
authProvider?: AuthProvider;
|
|
51
51
|
/**
|
|
52
|
-
* Show the floating identity badge in `
|
|
52
|
+
* Show the floating identity badge in `runapps` auth mode.
|
|
53
53
|
* **Default `true`** — the badge is now a desktop-ball-style
|
|
54
54
|
* real-time activity indicator (LED dot + progress ring around
|
|
55
55
|
* the avatar + click-through popover with active calls / recent
|
|
@@ -104,7 +104,7 @@ export interface ClientOptions {
|
|
|
104
104
|
* ```html
|
|
105
105
|
* <script src="https://cdn.jsdelivr.net/npm/@runappsai/sdk/dist/sdk.umd.js"></script>
|
|
106
106
|
* <script>
|
|
107
|
-
* const client = new RunApps
|
|
107
|
+
* const client = new RunApps();
|
|
108
108
|
* const res = await client.chat.create({
|
|
109
109
|
* model: "gpt-4o-mini",
|
|
110
110
|
* messages: [{ role: "user", content: "hello" }],
|
|
@@ -116,7 +116,7 @@ export interface ClientOptions {
|
|
|
116
116
|
*
|
|
117
117
|
* ```ts
|
|
118
118
|
* import { RunApps } from "@runappsai/sdk";
|
|
119
|
-
* const client = new RunApps({ apiKey: process.env.
|
|
119
|
+
* const client = new RunApps({ apiKey: process.env.RUNAPPS_API_KEY! });
|
|
120
120
|
* ```
|
|
121
121
|
*/
|
|
122
122
|
export class RunApps {
|
|
@@ -152,7 +152,14 @@ export class RunApps {
|
|
|
152
152
|
readonly events: SDKEvents = new SDKEvents();
|
|
153
153
|
|
|
154
154
|
constructor(options: ClientOptions = {}) {
|
|
155
|
-
|
|
155
|
+
// With no key and no explicit authProvider, a browser client uses the
|
|
156
|
+
// platform sign-in: `new RunApps()` is all an app needs. Elsewhere
|
|
157
|
+
// (Node, workers without a window) there is no one to sign in.
|
|
158
|
+
const provider =
|
|
159
|
+
options.authProvider ??
|
|
160
|
+
(!options.apiKey && !options.apiKeyResolver && typeof window !== "undefined"
|
|
161
|
+
? "runapps"
|
|
162
|
+
: "static");
|
|
156
163
|
let apiKeyResolver = options.apiKeyResolver;
|
|
157
164
|
let baseURL = options.baseURL;
|
|
158
165
|
let onUnauthorized: (() => void) | undefined;
|
|
@@ -197,7 +204,7 @@ export class RunApps {
|
|
|
197
204
|
|
|
198
205
|
if (!options.apiKey && !apiKeyResolver) {
|
|
199
206
|
throw new Error(
|
|
200
|
-
"runapps: pass
|
|
207
|
+
"runapps: pass `apiKey` (or `apiKeyResolver`); outside a browser there is no sign-in to fall back to",
|
|
201
208
|
);
|
|
202
209
|
}
|
|
203
210
|
const transport = new Transport({
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* reaching into per-service modules.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
// `RunJobs` is a deprecated alias of `RunApps`, kept for code written
|
|
10
|
+
// before the rename.
|
|
9
11
|
export { RunApps, RunApps as Client, RunApps as RunJobs, type ClientOptions, type AuthProvider } from "./client.js";
|
|
10
12
|
|
|
11
13
|
// SDK telemetry — `client.events` fires these around every LLM-ish
|
package/src/media.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* ```ts
|
|
23
|
-
* import { encodeImageUrl } from "@
|
|
23
|
+
* import { encodeImageUrl } from "@runappsai/sdk";
|
|
24
24
|
* const png = await fs.readFile("frame.png");
|
|
25
25
|
* await client.video.generate("Veo 3.1", {
|
|
26
26
|
* prompt: "...",
|
|
@@ -75,7 +75,7 @@ export function encodeImageUrl(
|
|
|
75
75
|
*
|
|
76
76
|
* @example
|
|
77
77
|
* ```ts
|
|
78
|
-
* import { decodeMediaUrl } from "@
|
|
78
|
+
* import { decodeMediaUrl } from "@runappsai/sdk";
|
|
79
79
|
* const job = await client.image.generateAsync("Seedream 5.0", {...});
|
|
80
80
|
* const { bytes, contentType } = await decodeMediaUrl(job.data[0].url);
|
|
81
81
|
* await fs.writeFile("out.png", bytes);
|
package/src/transport.ts
CHANGED
|
@@ -14,8 +14,8 @@ export interface TransportOptions {
|
|
|
14
14
|
apiKey?: string;
|
|
15
15
|
/** Dynamic resolver — called immediately before each request. Use this
|
|
16
16
|
* when the token is short-lived and refreshed externally (e.g. running
|
|
17
|
-
* inside
|
|
18
|
-
* `
|
|
17
|
+
* inside an app bundle that exposes
|
|
18
|
+
* its own `getToken()`). The result is awaited per request, so
|
|
19
19
|
* the caller can return a Promise that hits a token endpoint. Wins
|
|
20
20
|
* over `apiKey` when both are supplied. */
|
|
21
21
|
apiKeyResolver?: () => string | Promise<string>;
|