@topolo/sdk 0.9.1 → 0.9.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/dist/index.cjs +69 -13
- package/dist/index.d.cts +37 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +69 -13
- package/dist/node/credential-store.cjs +1 -0
- package/dist/node/credential-store.js +1 -0
- package/package.json +5 -8
package/dist/index.cjs
CHANGED
|
@@ -127,6 +127,7 @@ var APP_API_URLS = {
|
|
|
127
127
|
auth: "https://auth.topolo.app",
|
|
128
128
|
backup: "https://backup.topolo.app",
|
|
129
129
|
books: "https://books.topolo.app",
|
|
130
|
+
brand: "https://brand.topolo.app",
|
|
130
131
|
bugfix: "https://bugfix.topolo.app",
|
|
131
132
|
bytes: "https://bytes.topolo.app",
|
|
132
133
|
calendar: "https://calendar.topolo.app",
|
|
@@ -309,6 +310,38 @@ var APPLICATIONS = {
|
|
|
309
310
|
}
|
|
310
311
|
]
|
|
311
312
|
},
|
|
313
|
+
"brand": {
|
|
314
|
+
"id": "brand",
|
|
315
|
+
"appDir": "TopoloBrand",
|
|
316
|
+
"name": "topolo-brand",
|
|
317
|
+
"packageName": "@topolo/topolo-brand",
|
|
318
|
+
"productionUrl": "https://brand.topolo.app",
|
|
319
|
+
"services": [
|
|
320
|
+
"brand"
|
|
321
|
+
],
|
|
322
|
+
"deployTargets": [
|
|
323
|
+
{
|
|
324
|
+
"name": "topolo-brand",
|
|
325
|
+
"kind": "worker",
|
|
326
|
+
"apiUrl": "https://brand.topolo.app",
|
|
327
|
+
"domains": [
|
|
328
|
+
"brand.topolo.app"
|
|
329
|
+
],
|
|
330
|
+
"routes": [
|
|
331
|
+
"brand.topolo.app"
|
|
332
|
+
],
|
|
333
|
+
"appId": "brand"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"name": "topolo-brand-api",
|
|
337
|
+
"kind": "worker",
|
|
338
|
+
"apiUrl": null,
|
|
339
|
+
"domains": [],
|
|
340
|
+
"routes": [],
|
|
341
|
+
"appId": null
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
},
|
|
312
345
|
"bugfix": {
|
|
313
346
|
"id": "bugfix",
|
|
314
347
|
"appDir": "TopoloBugFix",
|
|
@@ -2431,6 +2464,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2431
2464
|
requireConfirmForWrites;
|
|
2432
2465
|
timeoutMs;
|
|
2433
2466
|
fetchImpl;
|
|
2467
|
+
credentialProvider;
|
|
2468
|
+
credentialLoadInFlight = null;
|
|
2434
2469
|
refreshCredential;
|
|
2435
2470
|
refreshInFlight = null;
|
|
2436
2471
|
debug;
|
|
@@ -2458,6 +2493,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2458
2493
|
this.requireConfirmForWrites = options.requireConfirmForWrites !== false;
|
|
2459
2494
|
this.timeoutMs = options.timeoutMs ?? 3e4;
|
|
2460
2495
|
this.fetchImpl = options.fetch ?? fetch;
|
|
2496
|
+
this.credentialProvider = options.credentialProvider;
|
|
2461
2497
|
this.refreshCredential = options.refreshCredential;
|
|
2462
2498
|
this.debug = options.debug;
|
|
2463
2499
|
}
|
|
@@ -2480,6 +2516,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2480
2516
|
`Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
|
|
2481
2517
|
);
|
|
2482
2518
|
}
|
|
2519
|
+
await this.loadCurrentCredential();
|
|
2483
2520
|
const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: requireHttpOrigin(opts.baseUrl) } : await this.resolveRequestService(opts.service);
|
|
2484
2521
|
const baseUrl = resolvedService.baseUrl;
|
|
2485
2522
|
const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
@@ -2591,6 +2628,19 @@ var TopoloClient = class _TopoloClient {
|
|
|
2591
2628
|
});
|
|
2592
2629
|
return parsed;
|
|
2593
2630
|
}
|
|
2631
|
+
async loadCurrentCredential() {
|
|
2632
|
+
if (!this.credentialProvider) return;
|
|
2633
|
+
this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
|
|
2634
|
+
if (!credential) {
|
|
2635
|
+
throw new TopoloAuthError("The configured Topolo credential is no longer available.");
|
|
2636
|
+
}
|
|
2637
|
+
this.credential = credential;
|
|
2638
|
+
return credential;
|
|
2639
|
+
}).finally(() => {
|
|
2640
|
+
this.credentialLoadInFlight = null;
|
|
2641
|
+
});
|
|
2642
|
+
await this.credentialLoadInFlight;
|
|
2643
|
+
}
|
|
2594
2644
|
async refreshRejectedAccessToken(attemptedAccessToken) {
|
|
2595
2645
|
if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
|
|
2596
2646
|
return this.credential;
|
|
@@ -3259,6 +3309,7 @@ function normalizeActionCatalogEntry(item) {
|
|
|
3259
3309
|
permissionName: pickActionString(a.permission_name) ?? pickActionString(a.permissionName) ?? "",
|
|
3260
3310
|
requiredPermission: pickActionString(a.required_permission) ?? pickActionString(a.requiredPermission) ?? "",
|
|
3261
3311
|
authorizationMode: pickAuthorizationMode(a.authorization_mode ?? a.authorizationMode),
|
|
3312
|
+
allowedServices: stringArray(a.allowed_services ?? a.allowedServices),
|
|
3262
3313
|
inputSchema: plainObject(a.input_schema ?? a.inputSchema),
|
|
3263
3314
|
outputSchema: plainObject(a.output_schema ?? a.outputSchema),
|
|
3264
3315
|
agentContract: plainObject(a.agent_contract ?? a.agentContract),
|
|
@@ -3280,7 +3331,7 @@ function pickAgentAccess(value) {
|
|
|
3280
3331
|
return value === "auto" || value === "confirm" || value === "off" ? value : null;
|
|
3281
3332
|
}
|
|
3282
3333
|
function pickAuthorizationMode(value) {
|
|
3283
|
-
return value === "runtime"
|
|
3334
|
+
return value === "runtime" || value === "public" || value === "service" ? value : "static";
|
|
3284
3335
|
}
|
|
3285
3336
|
function plainObject(value) {
|
|
3286
3337
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -3388,18 +3439,23 @@ function stableJson(value) {
|
|
|
3388
3439
|
return JSON.stringify(value);
|
|
3389
3440
|
}
|
|
3390
3441
|
async function digestTopoloActionCatalog(actions, appId) {
|
|
3391
|
-
const canonical = actions.filter((action) => action.agentAccess !== "off").map((action) =>
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3442
|
+
const canonical = actions.filter((action) => action.agentAccess !== "off").map((action) => {
|
|
3443
|
+
const authorizationMode = ["runtime", "public", "service"].includes(action.authorizationMode || "") ? action.authorizationMode : "static";
|
|
3444
|
+
const allowedServices = [...action.allowedServices || []].map((service) => service.trim()).filter(Boolean).sort();
|
|
3445
|
+
return {
|
|
3446
|
+
actionId: action.actionId || `${appId}.${action.name}`,
|
|
3447
|
+
authorizationMode,
|
|
3448
|
+
...authorizationMode === "service" ? { allowedServices } : {},
|
|
3449
|
+
inputSchema: action.inputSchema,
|
|
3450
|
+
method: action.method,
|
|
3451
|
+
outputSchema: action.outputSchema,
|
|
3452
|
+
path: action.path,
|
|
3453
|
+
permission: canonicalPermission(action.permission ?? action.permissionName ?? "", appId),
|
|
3454
|
+
readOnly: action.readOnly,
|
|
3455
|
+
requiresConfirmation: action.requiresConfirmation,
|
|
3456
|
+
target: action.target ?? ""
|
|
3457
|
+
};
|
|
3458
|
+
}).sort((left, right) => left.actionId.localeCompare(right.actionId));
|
|
3403
3459
|
const bytes = new TextEncoder().encode(canonical.map(stableJson).join("\n"));
|
|
3404
3460
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
3405
3461
|
return [...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join("");
|
package/dist/index.d.cts
CHANGED
|
@@ -58,6 +58,12 @@ interface TopoloClientOptions {
|
|
|
58
58
|
timeoutMs?: number;
|
|
59
59
|
/** Injected fetch, for testing. Defaults to global fetch. */
|
|
60
60
|
fetch?: typeof fetch;
|
|
61
|
+
/**
|
|
62
|
+
* Load the credential currently stored for this client before each request.
|
|
63
|
+
* Long-lived hosts use this to adopt context reauthentication and claim
|
|
64
|
+
* changes without waiting for the previous token to fail with a 401.
|
|
65
|
+
*/
|
|
66
|
+
credentialProvider?: () => Promise<TopoloCredential | null>;
|
|
61
67
|
/**
|
|
62
68
|
* Refresh a rejected access-token credential. When supplied, the client
|
|
63
69
|
* retries one 401 response with the returned credential. Concurrent 401s
|
|
@@ -182,8 +188,9 @@ interface TopoloActionCatalogEntry {
|
|
|
182
188
|
path: string;
|
|
183
189
|
permissionName: string;
|
|
184
190
|
requiredPermission: string;
|
|
185
|
-
/** Static
|
|
186
|
-
authorizationMode?: 'static' | 'runtime';
|
|
191
|
+
/** Static RBAC, contextual runtime policy, or an explicit public/service exception. */
|
|
192
|
+
authorizationMode?: 'static' | 'runtime' | 'public' | 'service';
|
|
193
|
+
allowedServices?: string[];
|
|
187
194
|
inputSchema: Record<string, unknown>;
|
|
188
195
|
outputSchema: Record<string, unknown>;
|
|
189
196
|
agentContract?: TopoloActionAgentContract;
|
|
@@ -270,6 +277,8 @@ declare class TopoloClient {
|
|
|
270
277
|
private readonly requireConfirmForWrites;
|
|
271
278
|
private readonly timeoutMs;
|
|
272
279
|
private readonly fetchImpl;
|
|
280
|
+
private readonly credentialProvider?;
|
|
281
|
+
private credentialLoadInFlight;
|
|
273
282
|
private readonly refreshCredential?;
|
|
274
283
|
private refreshInFlight;
|
|
275
284
|
private readonly debug?;
|
|
@@ -293,6 +302,7 @@ declare class TopoloClient {
|
|
|
293
302
|
* use and for the generic `topolo api` / MCP passthrough tool.
|
|
294
303
|
*/
|
|
295
304
|
request<T = unknown>(opts: RequestOptions): Promise<T>;
|
|
305
|
+
private loadCurrentCredential;
|
|
296
306
|
private refreshRejectedAccessToken;
|
|
297
307
|
private resolveRequestService;
|
|
298
308
|
private resolveLiveCallableService;
|
|
@@ -416,6 +426,7 @@ interface TopoloActionDigestInput {
|
|
|
416
426
|
permission?: string | null;
|
|
417
427
|
permissionName?: string | null;
|
|
418
428
|
authorizationMode?: string | null;
|
|
429
|
+
allowedServices?: string[] | null;
|
|
419
430
|
target?: string | null;
|
|
420
431
|
readOnly: boolean;
|
|
421
432
|
requiresConfirmation: boolean;
|
|
@@ -430,6 +441,7 @@ declare const APP_API_URLS: {
|
|
|
430
441
|
readonly auth: "https://auth.topolo.app";
|
|
431
442
|
readonly backup: "https://backup.topolo.app";
|
|
432
443
|
readonly books: "https://books.topolo.app";
|
|
444
|
+
readonly brand: "https://brand.topolo.app";
|
|
433
445
|
readonly bugfix: "https://bugfix.topolo.app";
|
|
434
446
|
readonly bytes: "https://bytes.topolo.app";
|
|
435
447
|
readonly calendar: "https://calendar.topolo.app";
|
|
@@ -579,6 +591,29 @@ declare const APPLICATIONS: {
|
|
|
579
591
|
readonly appId: null;
|
|
580
592
|
}];
|
|
581
593
|
};
|
|
594
|
+
readonly brand: {
|
|
595
|
+
readonly id: "brand";
|
|
596
|
+
readonly appDir: "TopoloBrand";
|
|
597
|
+
readonly name: "topolo-brand";
|
|
598
|
+
readonly packageName: "@topolo/topolo-brand";
|
|
599
|
+
readonly productionUrl: "https://brand.topolo.app";
|
|
600
|
+
readonly services: readonly ["brand"];
|
|
601
|
+
readonly deployTargets: readonly [{
|
|
602
|
+
readonly name: "topolo-brand";
|
|
603
|
+
readonly kind: "worker";
|
|
604
|
+
readonly apiUrl: "https://brand.topolo.app";
|
|
605
|
+
readonly domains: readonly ["brand.topolo.app"];
|
|
606
|
+
readonly routes: readonly ["brand.topolo.app"];
|
|
607
|
+
readonly appId: "brand";
|
|
608
|
+
}, {
|
|
609
|
+
readonly name: "topolo-brand-api";
|
|
610
|
+
readonly kind: "worker";
|
|
611
|
+
readonly apiUrl: null;
|
|
612
|
+
readonly domains: readonly [];
|
|
613
|
+
readonly routes: readonly [];
|
|
614
|
+
readonly appId: null;
|
|
615
|
+
}];
|
|
616
|
+
};
|
|
582
617
|
readonly bugfix: {
|
|
583
618
|
readonly id: "bugfix";
|
|
584
619
|
readonly appDir: "TopoloBugFix";
|
package/dist/index.d.ts
CHANGED
|
@@ -58,6 +58,12 @@ interface TopoloClientOptions {
|
|
|
58
58
|
timeoutMs?: number;
|
|
59
59
|
/** Injected fetch, for testing. Defaults to global fetch. */
|
|
60
60
|
fetch?: typeof fetch;
|
|
61
|
+
/**
|
|
62
|
+
* Load the credential currently stored for this client before each request.
|
|
63
|
+
* Long-lived hosts use this to adopt context reauthentication and claim
|
|
64
|
+
* changes without waiting for the previous token to fail with a 401.
|
|
65
|
+
*/
|
|
66
|
+
credentialProvider?: () => Promise<TopoloCredential | null>;
|
|
61
67
|
/**
|
|
62
68
|
* Refresh a rejected access-token credential. When supplied, the client
|
|
63
69
|
* retries one 401 response with the returned credential. Concurrent 401s
|
|
@@ -182,8 +188,9 @@ interface TopoloActionCatalogEntry {
|
|
|
182
188
|
path: string;
|
|
183
189
|
permissionName: string;
|
|
184
190
|
requiredPermission: string;
|
|
185
|
-
/** Static
|
|
186
|
-
authorizationMode?: 'static' | 'runtime';
|
|
191
|
+
/** Static RBAC, contextual runtime policy, or an explicit public/service exception. */
|
|
192
|
+
authorizationMode?: 'static' | 'runtime' | 'public' | 'service';
|
|
193
|
+
allowedServices?: string[];
|
|
187
194
|
inputSchema: Record<string, unknown>;
|
|
188
195
|
outputSchema: Record<string, unknown>;
|
|
189
196
|
agentContract?: TopoloActionAgentContract;
|
|
@@ -270,6 +277,8 @@ declare class TopoloClient {
|
|
|
270
277
|
private readonly requireConfirmForWrites;
|
|
271
278
|
private readonly timeoutMs;
|
|
272
279
|
private readonly fetchImpl;
|
|
280
|
+
private readonly credentialProvider?;
|
|
281
|
+
private credentialLoadInFlight;
|
|
273
282
|
private readonly refreshCredential?;
|
|
274
283
|
private refreshInFlight;
|
|
275
284
|
private readonly debug?;
|
|
@@ -293,6 +302,7 @@ declare class TopoloClient {
|
|
|
293
302
|
* use and for the generic `topolo api` / MCP passthrough tool.
|
|
294
303
|
*/
|
|
295
304
|
request<T = unknown>(opts: RequestOptions): Promise<T>;
|
|
305
|
+
private loadCurrentCredential;
|
|
296
306
|
private refreshRejectedAccessToken;
|
|
297
307
|
private resolveRequestService;
|
|
298
308
|
private resolveLiveCallableService;
|
|
@@ -416,6 +426,7 @@ interface TopoloActionDigestInput {
|
|
|
416
426
|
permission?: string | null;
|
|
417
427
|
permissionName?: string | null;
|
|
418
428
|
authorizationMode?: string | null;
|
|
429
|
+
allowedServices?: string[] | null;
|
|
419
430
|
target?: string | null;
|
|
420
431
|
readOnly: boolean;
|
|
421
432
|
requiresConfirmation: boolean;
|
|
@@ -430,6 +441,7 @@ declare const APP_API_URLS: {
|
|
|
430
441
|
readonly auth: "https://auth.topolo.app";
|
|
431
442
|
readonly backup: "https://backup.topolo.app";
|
|
432
443
|
readonly books: "https://books.topolo.app";
|
|
444
|
+
readonly brand: "https://brand.topolo.app";
|
|
433
445
|
readonly bugfix: "https://bugfix.topolo.app";
|
|
434
446
|
readonly bytes: "https://bytes.topolo.app";
|
|
435
447
|
readonly calendar: "https://calendar.topolo.app";
|
|
@@ -579,6 +591,29 @@ declare const APPLICATIONS: {
|
|
|
579
591
|
readonly appId: null;
|
|
580
592
|
}];
|
|
581
593
|
};
|
|
594
|
+
readonly brand: {
|
|
595
|
+
readonly id: "brand";
|
|
596
|
+
readonly appDir: "TopoloBrand";
|
|
597
|
+
readonly name: "topolo-brand";
|
|
598
|
+
readonly packageName: "@topolo/topolo-brand";
|
|
599
|
+
readonly productionUrl: "https://brand.topolo.app";
|
|
600
|
+
readonly services: readonly ["brand"];
|
|
601
|
+
readonly deployTargets: readonly [{
|
|
602
|
+
readonly name: "topolo-brand";
|
|
603
|
+
readonly kind: "worker";
|
|
604
|
+
readonly apiUrl: "https://brand.topolo.app";
|
|
605
|
+
readonly domains: readonly ["brand.topolo.app"];
|
|
606
|
+
readonly routes: readonly ["brand.topolo.app"];
|
|
607
|
+
readonly appId: "brand";
|
|
608
|
+
}, {
|
|
609
|
+
readonly name: "topolo-brand-api";
|
|
610
|
+
readonly kind: "worker";
|
|
611
|
+
readonly apiUrl: null;
|
|
612
|
+
readonly domains: readonly [];
|
|
613
|
+
readonly routes: readonly [];
|
|
614
|
+
readonly appId: null;
|
|
615
|
+
}];
|
|
616
|
+
};
|
|
582
617
|
readonly bugfix: {
|
|
583
618
|
readonly id: "bugfix";
|
|
584
619
|
readonly appDir: "TopoloBugFix";
|
package/dist/index.js
CHANGED
|
@@ -68,6 +68,7 @@ var APP_API_URLS = {
|
|
|
68
68
|
auth: "https://auth.topolo.app",
|
|
69
69
|
backup: "https://backup.topolo.app",
|
|
70
70
|
books: "https://books.topolo.app",
|
|
71
|
+
brand: "https://brand.topolo.app",
|
|
71
72
|
bugfix: "https://bugfix.topolo.app",
|
|
72
73
|
bytes: "https://bytes.topolo.app",
|
|
73
74
|
calendar: "https://calendar.topolo.app",
|
|
@@ -250,6 +251,38 @@ var APPLICATIONS = {
|
|
|
250
251
|
}
|
|
251
252
|
]
|
|
252
253
|
},
|
|
254
|
+
"brand": {
|
|
255
|
+
"id": "brand",
|
|
256
|
+
"appDir": "TopoloBrand",
|
|
257
|
+
"name": "topolo-brand",
|
|
258
|
+
"packageName": "@topolo/topolo-brand",
|
|
259
|
+
"productionUrl": "https://brand.topolo.app",
|
|
260
|
+
"services": [
|
|
261
|
+
"brand"
|
|
262
|
+
],
|
|
263
|
+
"deployTargets": [
|
|
264
|
+
{
|
|
265
|
+
"name": "topolo-brand",
|
|
266
|
+
"kind": "worker",
|
|
267
|
+
"apiUrl": "https://brand.topolo.app",
|
|
268
|
+
"domains": [
|
|
269
|
+
"brand.topolo.app"
|
|
270
|
+
],
|
|
271
|
+
"routes": [
|
|
272
|
+
"brand.topolo.app"
|
|
273
|
+
],
|
|
274
|
+
"appId": "brand"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"name": "topolo-brand-api",
|
|
278
|
+
"kind": "worker",
|
|
279
|
+
"apiUrl": null,
|
|
280
|
+
"domains": [],
|
|
281
|
+
"routes": [],
|
|
282
|
+
"appId": null
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
},
|
|
253
286
|
"bugfix": {
|
|
254
287
|
"id": "bugfix",
|
|
255
288
|
"appDir": "TopoloBugFix",
|
|
@@ -2372,6 +2405,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2372
2405
|
requireConfirmForWrites;
|
|
2373
2406
|
timeoutMs;
|
|
2374
2407
|
fetchImpl;
|
|
2408
|
+
credentialProvider;
|
|
2409
|
+
credentialLoadInFlight = null;
|
|
2375
2410
|
refreshCredential;
|
|
2376
2411
|
refreshInFlight = null;
|
|
2377
2412
|
debug;
|
|
@@ -2399,6 +2434,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2399
2434
|
this.requireConfirmForWrites = options.requireConfirmForWrites !== false;
|
|
2400
2435
|
this.timeoutMs = options.timeoutMs ?? 3e4;
|
|
2401
2436
|
this.fetchImpl = options.fetch ?? fetch;
|
|
2437
|
+
this.credentialProvider = options.credentialProvider;
|
|
2402
2438
|
this.refreshCredential = options.refreshCredential;
|
|
2403
2439
|
this.debug = options.debug;
|
|
2404
2440
|
}
|
|
@@ -2421,6 +2457,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2421
2457
|
`Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
|
|
2422
2458
|
);
|
|
2423
2459
|
}
|
|
2460
|
+
await this.loadCurrentCredential();
|
|
2424
2461
|
const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: requireHttpOrigin(opts.baseUrl) } : await this.resolveRequestService(opts.service);
|
|
2425
2462
|
const baseUrl = resolvedService.baseUrl;
|
|
2426
2463
|
const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
@@ -2532,6 +2569,19 @@ var TopoloClient = class _TopoloClient {
|
|
|
2532
2569
|
});
|
|
2533
2570
|
return parsed;
|
|
2534
2571
|
}
|
|
2572
|
+
async loadCurrentCredential() {
|
|
2573
|
+
if (!this.credentialProvider) return;
|
|
2574
|
+
this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
|
|
2575
|
+
if (!credential) {
|
|
2576
|
+
throw new TopoloAuthError("The configured Topolo credential is no longer available.");
|
|
2577
|
+
}
|
|
2578
|
+
this.credential = credential;
|
|
2579
|
+
return credential;
|
|
2580
|
+
}).finally(() => {
|
|
2581
|
+
this.credentialLoadInFlight = null;
|
|
2582
|
+
});
|
|
2583
|
+
await this.credentialLoadInFlight;
|
|
2584
|
+
}
|
|
2535
2585
|
async refreshRejectedAccessToken(attemptedAccessToken) {
|
|
2536
2586
|
if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
|
|
2537
2587
|
return this.credential;
|
|
@@ -3200,6 +3250,7 @@ function normalizeActionCatalogEntry(item) {
|
|
|
3200
3250
|
permissionName: pickActionString(a.permission_name) ?? pickActionString(a.permissionName) ?? "",
|
|
3201
3251
|
requiredPermission: pickActionString(a.required_permission) ?? pickActionString(a.requiredPermission) ?? "",
|
|
3202
3252
|
authorizationMode: pickAuthorizationMode(a.authorization_mode ?? a.authorizationMode),
|
|
3253
|
+
allowedServices: stringArray(a.allowed_services ?? a.allowedServices),
|
|
3203
3254
|
inputSchema: plainObject(a.input_schema ?? a.inputSchema),
|
|
3204
3255
|
outputSchema: plainObject(a.output_schema ?? a.outputSchema),
|
|
3205
3256
|
agentContract: plainObject(a.agent_contract ?? a.agentContract),
|
|
@@ -3221,7 +3272,7 @@ function pickAgentAccess(value) {
|
|
|
3221
3272
|
return value === "auto" || value === "confirm" || value === "off" ? value : null;
|
|
3222
3273
|
}
|
|
3223
3274
|
function pickAuthorizationMode(value) {
|
|
3224
|
-
return value === "runtime"
|
|
3275
|
+
return value === "runtime" || value === "public" || value === "service" ? value : "static";
|
|
3225
3276
|
}
|
|
3226
3277
|
function plainObject(value) {
|
|
3227
3278
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -3329,18 +3380,23 @@ function stableJson(value) {
|
|
|
3329
3380
|
return JSON.stringify(value);
|
|
3330
3381
|
}
|
|
3331
3382
|
async function digestTopoloActionCatalog(actions, appId) {
|
|
3332
|
-
const canonical = actions.filter((action) => action.agentAccess !== "off").map((action) =>
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3383
|
+
const canonical = actions.filter((action) => action.agentAccess !== "off").map((action) => {
|
|
3384
|
+
const authorizationMode = ["runtime", "public", "service"].includes(action.authorizationMode || "") ? action.authorizationMode : "static";
|
|
3385
|
+
const allowedServices = [...action.allowedServices || []].map((service) => service.trim()).filter(Boolean).sort();
|
|
3386
|
+
return {
|
|
3387
|
+
actionId: action.actionId || `${appId}.${action.name}`,
|
|
3388
|
+
authorizationMode,
|
|
3389
|
+
...authorizationMode === "service" ? { allowedServices } : {},
|
|
3390
|
+
inputSchema: action.inputSchema,
|
|
3391
|
+
method: action.method,
|
|
3392
|
+
outputSchema: action.outputSchema,
|
|
3393
|
+
path: action.path,
|
|
3394
|
+
permission: canonicalPermission(action.permission ?? action.permissionName ?? "", appId),
|
|
3395
|
+
readOnly: action.readOnly,
|
|
3396
|
+
requiresConfirmation: action.requiresConfirmation,
|
|
3397
|
+
target: action.target ?? ""
|
|
3398
|
+
};
|
|
3399
|
+
}).sort((left, right) => left.actionId.localeCompare(right.actionId));
|
|
3344
3400
|
const bytes = new TextEncoder().encode(canonical.map(stableJson).join("\n"));
|
|
3345
3401
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
3346
3402
|
return [...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
@@ -84,6 +84,7 @@ var APP_API_URLS = {
|
|
|
84
84
|
auth: "https://auth.topolo.app",
|
|
85
85
|
backup: "https://backup.topolo.app",
|
|
86
86
|
books: "https://books.topolo.app",
|
|
87
|
+
brand: "https://brand.topolo.app",
|
|
87
88
|
bugfix: "https://bugfix.topolo.app",
|
|
88
89
|
bytes: "https://bytes.topolo.app",
|
|
89
90
|
calendar: "https://calendar.topolo.app",
|
|
@@ -40,6 +40,7 @@ var APP_API_URLS = {
|
|
|
40
40
|
auth: "https://auth.topolo.app",
|
|
41
41
|
backup: "https://backup.topolo.app",
|
|
42
42
|
books: "https://books.topolo.app",
|
|
43
|
+
brand: "https://brand.topolo.app",
|
|
43
44
|
bugfix: "https://bugfix.topolo.app",
|
|
44
45
|
bytes: "https://bytes.topolo.app",
|
|
45
46
|
calendar: "https://calendar.topolo.app",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/sdk",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"topoloPublishedVersion": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
|
+
"topoloPublishedVersion": "0.9.3",
|
|
5
5
|
"description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -23,16 +23,13 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"
|
|
27
|
-
"check:generated": "node scripts/check-generated.mjs",
|
|
28
|
-
"prebuild": "node scripts/generate-services.mjs",
|
|
26
|
+
"check:generated": "git diff --exit-code -- src/services.generated.ts src/applications.generated.ts",
|
|
29
27
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean && tsup src/node/credential-store.ts --format esm,cjs --dts --out-dir dist/node",
|
|
30
28
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
31
|
-
"typecheck": "
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
32
30
|
"test": "vitest run",
|
|
33
31
|
"test:watch": "vitest",
|
|
34
|
-
"prepublishOnly": "npm run build
|
|
35
|
-
"verify:package": "node ../../tooling/verify-npm-package.mjs .",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
36
33
|
"coverage": "vitest run --coverage"
|
|
37
34
|
},
|
|
38
35
|
"devDependencies": {
|