@topolo/sdk 0.9.10 → 0.10.1
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 +21 -16
- package/dist/index.cjs +321 -74
- package/dist/index.d.cts +309 -194
- package/dist/index.d.ts +309 -194
- package/dist/index.js +310 -74
- package/dist/node/credential-store.cjs +2 -51
- package/dist/node/credential-store.js +2 -51
- package/package.json +3 -6
package/dist/index.js
CHANGED
|
@@ -101,62 +101,13 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
// src/services.
|
|
104
|
+
// src/bootstrap-services.ts
|
|
105
105
|
var APP_API_URLS = {
|
|
106
|
-
agent: "https://agent.topolo.app",
|
|
107
106
|
auth: "https://auth.topolo.app",
|
|
108
|
-
|
|
109
|
-
blog: "https://blog.topolo.app",
|
|
110
|
-
books: "https://books.topolo.app",
|
|
111
|
-
brand: "https://brand.topolo.app",
|
|
112
|
-
bugfix: "https://bugfix.topolo.app",
|
|
113
|
-
bytes: "https://bytes.topolo.app",
|
|
114
|
-
calendar: "https://calendar.topolo.app",
|
|
115
|
-
campaigns: "https://campaigns.topolo.app",
|
|
116
|
-
capacity: "https://capacity.topolo.app",
|
|
117
|
-
chat: "https://chat.topolo.app",
|
|
118
|
-
commerce: "https://commerce.topolo.app",
|
|
119
|
-
compose: "https://compose.topolo.app",
|
|
120
|
-
consent: "https://consent.topolo.app",
|
|
121
|
-
crm: "https://crm.topolo.app",
|
|
122
|
-
design: "https://design.topolo.app",
|
|
123
|
-
developers: "https://developers.topolo.app",
|
|
124
|
-
director: "https://director.topolo.app",
|
|
125
|
-
feed: "https://feed.topolo.app",
|
|
126
|
-
flow: "https://flow.topolo.app",
|
|
127
|
-
forecast: "https://forecast.topolo.app",
|
|
128
|
-
forms: "https://forms.topolo.app",
|
|
129
|
-
home: "https://home.topolo.app",
|
|
130
|
-
insights: "https://insights.topolo.app",
|
|
131
|
-
inventory: "https://inventory.topolo.app",
|
|
132
|
-
learn: "https://learn.topolo.app",
|
|
133
|
-
localize: "https://localize.topolo.app",
|
|
134
|
-
mail: "https://mail.topolo.app",
|
|
135
|
-
mdm: "https://mdm.topolo.app",
|
|
136
|
-
messages: "https://messages.topolo.app",
|
|
137
|
-
nexus: "https://nexus.topolo.app",
|
|
138
|
-
notify: "https://notify.topolo.app",
|
|
139
|
-
observability_watch: "https://observability-watch.topolo.app",
|
|
140
|
-
one: "https://www.topolo.app",
|
|
141
|
-
p2p: "https://p2p.topolo.app",
|
|
142
|
-
pay: "https://pay.topolo.app",
|
|
143
|
-
people: "https://people.topolo.app",
|
|
144
|
-
"quro.api": "https://api.ol0.me",
|
|
145
|
-
"quro.redirect": "https://ol0.me",
|
|
146
|
-
roadmapper: "https://roadmapper.topolo.app",
|
|
147
|
-
sign: "https://sign.topolo.app",
|
|
148
|
-
social_studio: "https://studio.topolo.app",
|
|
149
|
-
socialize: "https://socialize.topolo.app",
|
|
150
|
-
spaces: "https://spaces.topolo.app",
|
|
151
|
-
status: "https://status.topolo.app",
|
|
152
|
-
success: "https://success.topolo.app",
|
|
153
|
-
support: "https://support.topolo.app",
|
|
154
|
-
survey: "https://survey.topolo.app",
|
|
155
|
-
voice: "https://voice.topolo.app",
|
|
156
|
-
web: "https://web.topolo.app"
|
|
107
|
+
developers: "https://developers.topolo.app"
|
|
157
108
|
};
|
|
158
109
|
|
|
159
|
-
// src/applications.
|
|
110
|
+
// src/applications-fallback.ts
|
|
160
111
|
var APPLICATIONS = {
|
|
161
112
|
"admin": {
|
|
162
113
|
"id": "admin",
|
|
@@ -1882,8 +1833,148 @@ var APPLICATIONS = {
|
|
|
1882
1833
|
}
|
|
1883
1834
|
};
|
|
1884
1835
|
|
|
1836
|
+
// src/application-directory.ts
|
|
1837
|
+
function friendlyAppId(entry) {
|
|
1838
|
+
for (const value of [entry.slug, entry.name, entry.appId]) {
|
|
1839
|
+
if (typeof value !== "string" || !value.trim()) continue;
|
|
1840
|
+
const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
|
|
1841
|
+
const withoutPrefix = normalized.replace(/^(?:app[_-])?topolo[-_]+/, "");
|
|
1842
|
+
if (withoutPrefix) return withoutPrefix;
|
|
1843
|
+
}
|
|
1844
|
+
return entry.appId;
|
|
1845
|
+
}
|
|
1846
|
+
function idVariants(value) {
|
|
1847
|
+
const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
|
|
1848
|
+
return [.../* @__PURE__ */ new Set([
|
|
1849
|
+
normalized,
|
|
1850
|
+
normalized.replace(/-/g, "_"),
|
|
1851
|
+
normalized.replace(/_/g, "-")
|
|
1852
|
+
])].filter(Boolean);
|
|
1853
|
+
}
|
|
1854
|
+
var STATIC_APPLICATIONS = APPLICATIONS;
|
|
1855
|
+
function staticApplicationForId(id) {
|
|
1856
|
+
for (const variant of idVariants(id)) {
|
|
1857
|
+
const entry = STATIC_APPLICATIONS[variant];
|
|
1858
|
+
if (entry) return entry;
|
|
1859
|
+
}
|
|
1860
|
+
return null;
|
|
1861
|
+
}
|
|
1862
|
+
function applicationEntryFromCatalog(live) {
|
|
1863
|
+
const id = friendlyAppId(live);
|
|
1864
|
+
return {
|
|
1865
|
+
id,
|
|
1866
|
+
appDir: "-",
|
|
1867
|
+
name: live.name ?? live.slug ?? live.appId,
|
|
1868
|
+
packageName: null,
|
|
1869
|
+
productionUrl: live.launchUrl ?? live.apiBaseUrl ?? null,
|
|
1870
|
+
services: live.apiBaseUrl ? [id] : [],
|
|
1871
|
+
deployTargets: []
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
var DIRECTORY_PAGE_LIMIT = 100;
|
|
1875
|
+
var DIRECTORY_MAX_PAGES = 100;
|
|
1876
|
+
function staticApplicationDirectory() {
|
|
1877
|
+
const applications = Object.entries(STATIC_APPLICATIONS).map(([id, application]) => ({
|
|
1878
|
+
id,
|
|
1879
|
+
application,
|
|
1880
|
+
source: "static",
|
|
1881
|
+
live: null
|
|
1882
|
+
})).sort((left, right) => left.id.localeCompare(right.id));
|
|
1883
|
+
return { source: "static_fallback", applications };
|
|
1884
|
+
}
|
|
1885
|
+
function directoryApplicationFromLive(live) {
|
|
1886
|
+
const id = friendlyAppId(live);
|
|
1887
|
+
return {
|
|
1888
|
+
id,
|
|
1889
|
+
// Prefer the static snapshot's richer repo/deploy metadata when the live
|
|
1890
|
+
// registry confirms the app; synthesize from the live entry otherwise.
|
|
1891
|
+
application: staticApplicationForId(id) ?? applicationEntryFromCatalog(live),
|
|
1892
|
+
source: "live",
|
|
1893
|
+
live
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
async function listApplicationDirectory(client) {
|
|
1897
|
+
if (!client) return staticApplicationDirectory();
|
|
1898
|
+
let services;
|
|
1899
|
+
try {
|
|
1900
|
+
services = [];
|
|
1901
|
+
let cursor;
|
|
1902
|
+
for (let page = 0; page < DIRECTORY_MAX_PAGES; page += 1) {
|
|
1903
|
+
const result = await client.searchServices({
|
|
1904
|
+
...cursor ? { cursor } : {},
|
|
1905
|
+
limit: DIRECTORY_PAGE_LIMIT
|
|
1906
|
+
});
|
|
1907
|
+
services.push(...result.services);
|
|
1908
|
+
if (!result.page.nextCursor) break;
|
|
1909
|
+
cursor = result.page.nextCursor;
|
|
1910
|
+
}
|
|
1911
|
+
} catch {
|
|
1912
|
+
return staticApplicationDirectory();
|
|
1913
|
+
}
|
|
1914
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1915
|
+
for (const live of services) {
|
|
1916
|
+
const entry = directoryApplicationFromLive(live);
|
|
1917
|
+
if (!seen.has(entry.id)) seen.set(entry.id, entry);
|
|
1918
|
+
}
|
|
1919
|
+
return {
|
|
1920
|
+
source: "live",
|
|
1921
|
+
applications: [...seen.values()].sort((left, right) => left.id.localeCompare(right.id))
|
|
1922
|
+
};
|
|
1923
|
+
}
|
|
1924
|
+
function matchesDirectoryApplication(app, needle) {
|
|
1925
|
+
const candidates = new Set(idVariants(needle));
|
|
1926
|
+
const keys = [
|
|
1927
|
+
app.id,
|
|
1928
|
+
app.application.id,
|
|
1929
|
+
app.application.name,
|
|
1930
|
+
app.live?.appId,
|
|
1931
|
+
app.live?.slug,
|
|
1932
|
+
app.live?.name
|
|
1933
|
+
];
|
|
1934
|
+
for (const key of keys) {
|
|
1935
|
+
if (typeof key !== "string" || !key.trim()) continue;
|
|
1936
|
+
for (const variant of idVariants(key)) {
|
|
1937
|
+
if (candidates.has(variant)) return true;
|
|
1938
|
+
}
|
|
1939
|
+
for (const variant of idVariants(friendlyAppId({ appId: key }))) {
|
|
1940
|
+
if (candidates.has(variant)) return true;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
return false;
|
|
1944
|
+
}
|
|
1945
|
+
function formatDirectoryApplicationIds(directory) {
|
|
1946
|
+
const ids = directory.applications.map((app) => app.id).sort();
|
|
1947
|
+
const preview = ids.slice(0, 50).join(", ");
|
|
1948
|
+
const suffix = ids.length > 50 ? `, ... +${ids.length - 50} more` : "";
|
|
1949
|
+
const label = directory.source === "live" ? "Applications available to this credential" : "Applications in the bundled static snapshot (live registry unreachable)";
|
|
1950
|
+
return `${label}: ${preview}${suffix}`;
|
|
1951
|
+
}
|
|
1952
|
+
async function resolveApplicationDirectoryEntry(client, application) {
|
|
1953
|
+
const needle = typeof application === "string" ? application.trim() : "";
|
|
1954
|
+
if (!needle) {
|
|
1955
|
+
throw new TopoloSdkError("unknown_application", "application is required");
|
|
1956
|
+
}
|
|
1957
|
+
if (client) {
|
|
1958
|
+
let live = null;
|
|
1959
|
+
try {
|
|
1960
|
+
live = await client.getService(needle);
|
|
1961
|
+
} catch {
|
|
1962
|
+
live = null;
|
|
1963
|
+
}
|
|
1964
|
+
if (live) return directoryApplicationFromLive(live);
|
|
1965
|
+
}
|
|
1966
|
+
const directory = await listApplicationDirectory(client);
|
|
1967
|
+
const match = directory.applications.find((app) => matchesDirectoryApplication(app, needle));
|
|
1968
|
+
if (match) return match;
|
|
1969
|
+
throw new TopoloSdkError(
|
|
1970
|
+
"unknown_application",
|
|
1971
|
+
`Unknown application "${application}". ${formatDirectoryApplicationIds(directory)}`
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1885
1975
|
// src/application-requirements.ts
|
|
1886
|
-
var
|
|
1976
|
+
var STATIC_APPLICATIONS2 = APPLICATIONS;
|
|
1977
|
+
var APPLICATION_REQUIREMENTS_VERSION = "2026-08-11.1";
|
|
1887
1978
|
var APPLICATION_REQUIREMENTS = [
|
|
1888
1979
|
{
|
|
1889
1980
|
id: "platform-metadata",
|
|
@@ -1893,10 +1984,10 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1893
1984
|
evidence: [
|
|
1894
1985
|
"topolo.cloudcontrol.json exists for every deployed app surface",
|
|
1895
1986
|
"package.json names the package or app when the repo ships code",
|
|
1896
|
-
"The
|
|
1987
|
+
"The live platform registry exposes the app through topolo apps and MCP discovery"
|
|
1897
1988
|
],
|
|
1898
1989
|
implementation: [
|
|
1899
|
-
"
|
|
1990
|
+
"Register the app in the live platform registry (Auth service catalog) before exposing it to agents",
|
|
1900
1991
|
"Keep production URLs, Worker names, Pages projects, routes, domains, and bindings current in CloudControl metadata",
|
|
1901
1992
|
"Do not leave a new Topolo* app directory without an explicit application ID"
|
|
1902
1993
|
]
|
|
@@ -1971,7 +2062,7 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1971
2062
|
implementation: [
|
|
1972
2063
|
"Add production Worker api_url metadata and sdk_app_id for every agent-callable API target",
|
|
1973
2064
|
"Mark browser, documentation, and runtime-only Worker targets with agent_callable:false",
|
|
1974
|
-
"Expose stable app IDs through
|
|
2065
|
+
"Expose stable app IDs through live catalog discovery",
|
|
1975
2066
|
"Keep typed SDK/CLI/MCP surfaces in sync when an API contract stabilizes"
|
|
1976
2067
|
]
|
|
1977
2068
|
},
|
|
@@ -2091,15 +2182,24 @@ function applicationRequirementScopes(application) {
|
|
|
2091
2182
|
}
|
|
2092
2183
|
return Array.from(scopes);
|
|
2093
2184
|
}
|
|
2185
|
+
function fallbackApplication(id) {
|
|
2186
|
+
const entry = STATIC_APPLICATIONS2[id];
|
|
2187
|
+
if (!entry) {
|
|
2188
|
+
throw new Error(
|
|
2189
|
+
`Unknown application "${id}" in the static fallback snapshot. Resolve applications from the live registry (resolveApplicationDirectoryEntry) and pass the entry directly.`
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
return entry;
|
|
2193
|
+
}
|
|
2094
2194
|
function requirementsForApplication(applicationOrId) {
|
|
2095
|
-
const application = typeof applicationOrId === "string" ?
|
|
2195
|
+
const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
|
|
2096
2196
|
const scopes = new Set(applicationRequirementScopes(application));
|
|
2097
2197
|
return APPLICATION_REQUIREMENTS.filter(
|
|
2098
2198
|
(requirement) => requirement.appliesTo.some((scope) => scopes.has(scope))
|
|
2099
2199
|
);
|
|
2100
2200
|
}
|
|
2101
2201
|
function auditApplicationRequirements(applicationOrId) {
|
|
2102
|
-
const application = typeof applicationOrId === "string" ?
|
|
2202
|
+
const application = typeof applicationOrId === "string" ? fallbackApplication(applicationOrId) : applicationOrId;
|
|
2103
2203
|
const scopes = applicationRequirementScopes(application);
|
|
2104
2204
|
const findings = requirementsForApplication(application).map(
|
|
2105
2205
|
(requirement) => evaluateRequirement(application, requirement)
|
|
@@ -2112,10 +2212,17 @@ function auditApplicationRequirements(applicationOrId) {
|
|
|
2112
2212
|
findings
|
|
2113
2213
|
};
|
|
2114
2214
|
}
|
|
2215
|
+
function auditApplicationEntries(applications) {
|
|
2216
|
+
return buildAuditReport(
|
|
2217
|
+
applications.map((application) => auditApplicationRequirements(application))
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2115
2220
|
function auditAllApplicationRequirements(applicationIds = Object.keys(APPLICATIONS).sort()) {
|
|
2116
|
-
|
|
2117
|
-
(applicationId) => auditApplicationRequirements(applicationId)
|
|
2221
|
+
return buildAuditReport(
|
|
2222
|
+
applicationIds.map((applicationId) => auditApplicationRequirements(applicationId))
|
|
2118
2223
|
);
|
|
2224
|
+
}
|
|
2225
|
+
function buildAuditReport(applications) {
|
|
2119
2226
|
const migrationQueue = applications.flatMap(
|
|
2120
2227
|
(audit) => audit.findings.filter((finding2) => finding2.status !== "met").map((finding2) => ({
|
|
2121
2228
|
applicationId: audit.application.id,
|
|
@@ -3426,8 +3533,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
3426
3533
|
});
|
|
3427
3534
|
}
|
|
3428
3535
|
/**
|
|
3429
|
-
*
|
|
3430
|
-
*
|
|
3536
|
+
* @deprecated Static fallback snapshot only. Use `searchServices()` (the
|
|
3537
|
+
* live credential-scoped registry) for anything that decides behavior; this
|
|
3538
|
+
* exists for offline packaging audits when the registry is unreachable.
|
|
3431
3539
|
*/
|
|
3432
3540
|
listBundledServices() {
|
|
3433
3541
|
const apps = Object.values(APPLICATIONS);
|
|
@@ -3819,6 +3927,54 @@ function mergeSignals(a, b) {
|
|
|
3819
3927
|
return controller.signal;
|
|
3820
3928
|
}
|
|
3821
3929
|
|
|
3930
|
+
// src/agent-output.ts
|
|
3931
|
+
function compactActionCatalogEntry(action) {
|
|
3932
|
+
const required = Array.isArray(action.inputSchema["required"]) ? action.inputSchema["required"].filter((value) => typeof value === "string") : [];
|
|
3933
|
+
const examples = action.agentContract?.examples ?? [];
|
|
3934
|
+
return {
|
|
3935
|
+
actionId: action.actionId,
|
|
3936
|
+
title: action.title,
|
|
3937
|
+
description: action.description,
|
|
3938
|
+
method: action.method,
|
|
3939
|
+
readOnly: action.readOnly,
|
|
3940
|
+
requiresConfirmation: action.requiresConfirmation,
|
|
3941
|
+
agentAccess: action.agentAccess ?? (action.requiresConfirmation ? "confirm" : action.readOnly ? "auto" : "confirm"),
|
|
3942
|
+
requiredPermission: action.requiredPermission,
|
|
3943
|
+
requiredInput: required,
|
|
3944
|
+
resourceType: action.agentContract?.resource?.kind ?? null,
|
|
3945
|
+
exampleInput: examples[0]?.input ?? null,
|
|
3946
|
+
docsUrl: action.agentContract?.docsUrl ?? null
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3949
|
+
function compactActionValidation(actionId, validation) {
|
|
3950
|
+
return { actionId, valid: validation.valid, errors: validation.errors };
|
|
3951
|
+
}
|
|
3952
|
+
function compactActionPlan(plan) {
|
|
3953
|
+
return {
|
|
3954
|
+
actionId: plan.action.actionId,
|
|
3955
|
+
valid: plan.validation.valid,
|
|
3956
|
+
errors: plan.validation.errors,
|
|
3957
|
+
executable: plan.executable,
|
|
3958
|
+
confirmationRequired: plan.confirmationRequired,
|
|
3959
|
+
confirmationProvided: plan.confirmationProvided,
|
|
3960
|
+
request: plan.request,
|
|
3961
|
+
verification: plan.verification,
|
|
3962
|
+
rollbackActionId: plan.rollbackActionId,
|
|
3963
|
+
nextActionIds: plan.nextActionIds
|
|
3964
|
+
};
|
|
3965
|
+
}
|
|
3966
|
+
function compactApplicationAudit(report) {
|
|
3967
|
+
return {
|
|
3968
|
+
version: report.version,
|
|
3969
|
+
applications: report.applications.map((audit) => ({
|
|
3970
|
+
applicationId: audit.application.id,
|
|
3971
|
+
applicationName: audit.application.name,
|
|
3972
|
+
score: audit.score
|
|
3973
|
+
})),
|
|
3974
|
+
migrationQueueCount: report.migrationQueue.length
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3822
3978
|
// src/action-catalog-digest.ts
|
|
3823
3979
|
var ACTION_CATALOG_DIGEST_ALGORITHM = "sha256-v1";
|
|
3824
3980
|
function canonicalPermission(value, appId) {
|
|
@@ -4032,25 +4188,90 @@ function derivedOutputSchema(action) {
|
|
|
4032
4188
|
...provenance
|
|
4033
4189
|
};
|
|
4034
4190
|
}
|
|
4035
|
-
function
|
|
4036
|
-
|
|
4191
|
+
function patternedString(pattern, hint) {
|
|
4192
|
+
const candidates = [
|
|
4193
|
+
hint.toLowerCase().includes("email") ? "agent@topolo.app" : null,
|
|
4194
|
+
hint.toLowerCase().includes("url") || hint.toLowerCase().includes("uri") ? "https://topolo.app" : null,
|
|
4195
|
+
hint.toLowerCase().includes("app") && hint.toLowerCase().includes("id") ? "app_topolo_example" : null,
|
|
4196
|
+
hint.toLowerCase().includes("file") ? "sample.ply" : null,
|
|
4197
|
+
hint.toLowerCase().includes("slug") ? "/sample" : null,
|
|
4198
|
+
hint.toLowerCase().includes("year") ? "2026" : null,
|
|
4199
|
+
hint.toLowerCase().includes("date") || hint.toLowerCase().endsWith("at") ? "2026-01-15T12:00:00Z" : null,
|
|
4200
|
+
hint.toLowerCase().includes("period") || hint.toLowerCase().includes("month") ? "2026-01" : null,
|
|
4201
|
+
hint.toLowerCase().includes("event") || hint.toLowerCase().includes("type") ? "resource.created" : null,
|
|
4202
|
+
"app_topolo_example",
|
|
4203
|
+
"2026-01-15T12:00:00Z",
|
|
4204
|
+
"sample.ply",
|
|
4205
|
+
"/sample",
|
|
4206
|
+
"2026-01-15",
|
|
4207
|
+
"2026-01",
|
|
4208
|
+
"2026",
|
|
4209
|
+
"resource.created",
|
|
4210
|
+
"sample-value",
|
|
4211
|
+
"sample_value",
|
|
4212
|
+
"sample"
|
|
4213
|
+
].filter(Boolean);
|
|
4214
|
+
try {
|
|
4215
|
+
const expression = new RegExp(pattern);
|
|
4216
|
+
return candidates.find((candidate) => expression.test(candidate)) ?? "sample";
|
|
4217
|
+
} catch {
|
|
4218
|
+
return "sample";
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
function sampleString(schema, hint) {
|
|
4222
|
+
if (schema.format === "email") return "agent@topolo.app";
|
|
4223
|
+
if (schema.format === "uri" || schema.format === "url") return "https://topolo.app";
|
|
4224
|
+
if (schema.format === "date-time") return patternedString(schema.pattern || "", hint) || "2026-01-15T12:00:00Z";
|
|
4225
|
+
const words = String(hint || "value").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").toLowerCase();
|
|
4226
|
+
let value = typeof schema.pattern === "string" ? patternedString(schema.pattern, hint) : /(^|\s)id$/.test(words) ? `${slugify(words.replace(/\sid$/, "") || "resource")}_01` : words.includes("date") ? "2026-01-15" : words.includes("period") || words.includes("month") ? "2026-01" : words.includes("year") ? "2026" : `Sample ${words}`;
|
|
4227
|
+
const minimum = Number.isInteger(schema.minLength) ? schema.minLength : 0;
|
|
4228
|
+
const maximum = Number.isInteger(schema.maxLength) ? schema.maxLength : null;
|
|
4229
|
+
if (value.length < minimum) value = value.padEnd(minimum, "x");
|
|
4230
|
+
if (maximum !== null && value.length > maximum) value = value.slice(0, maximum);
|
|
4231
|
+
return value;
|
|
4232
|
+
}
|
|
4233
|
+
function localReference(rootSchema, reference) {
|
|
4234
|
+
if (!isRecord4(rootSchema) || typeof reference !== "string" || !reference.startsWith("#/")) return null;
|
|
4235
|
+
return reference.slice(2).split("/").reduce((value, segment) => {
|
|
4236
|
+
const key = segment.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
4237
|
+
return isRecord4(value) ? value[key] : void 0;
|
|
4238
|
+
}, rootSchema);
|
|
4239
|
+
}
|
|
4240
|
+
function sampleForSchema(schema, depth = 0, hint = "value", rootSchema = schema) {
|
|
4241
|
+
if (!isRecord4(schema) || depth > 20) return null;
|
|
4242
|
+
const referenced = localReference(rootSchema, schema.$ref);
|
|
4243
|
+
if (isRecord4(referenced)) return sampleForSchema(referenced, depth + 1, hint, rootSchema);
|
|
4037
4244
|
if (schema.const !== void 0) return schema.const;
|
|
4038
4245
|
if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
|
|
4039
|
-
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) return sampleForSchema(schema.oneOf[0], depth + 1);
|
|
4040
|
-
if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) return sampleForSchema(schema.anyOf[0], depth + 1);
|
|
4041
|
-
if (schema.type
|
|
4246
|
+
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) return sampleForSchema(schema.oneOf[0], depth + 1, hint, rootSchema);
|
|
4247
|
+
if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) return sampleForSchema(schema.anyOf[0], depth + 1, hint, rootSchema);
|
|
4248
|
+
if (Array.isArray(schema.type)) {
|
|
4249
|
+
return sampleForSchema({ ...schema, type: schema.type.find((type) => type !== "null") ?? schema.type[0] }, depth + 1, hint, rootSchema);
|
|
4250
|
+
}
|
|
4251
|
+
if (schema.type === "array") {
|
|
4252
|
+
const minimum = Number.isInteger(schema.minItems) ? schema.minItems : 0;
|
|
4253
|
+
const maximum = Number.isInteger(schema.maxItems) ? schema.maxItems : null;
|
|
4254
|
+
const count = maximum === 0 ? 0 : minimum > 0 ? minimum : depth >= 4 ? 0 : 1;
|
|
4255
|
+
return Array.from({ length: count }, () => sampleForSchema(schema.items, depth + 1, singularize(hint), rootSchema));
|
|
4256
|
+
}
|
|
4042
4257
|
if (schema.type === "boolean") return false;
|
|
4043
|
-
if (schema.type === "integer" || schema.type === "number")
|
|
4044
|
-
|
|
4045
|
-
if (schema.
|
|
4046
|
-
|
|
4047
|
-
|
|
4258
|
+
if (schema.type === "integer" || schema.type === "number") {
|
|
4259
|
+
let value = typeof schema.minimum === "number" ? schema.minimum : 0;
|
|
4260
|
+
if (typeof schema.exclusiveMinimum === "number" && value <= schema.exclusiveMinimum) {
|
|
4261
|
+
value = schema.type === "integer" ? Math.floor(schema.exclusiveMinimum) + 1 : schema.exclusiveMinimum + 0.1;
|
|
4262
|
+
}
|
|
4263
|
+
if (typeof schema.maximum === "number") value = Math.min(value, schema.maximum);
|
|
4264
|
+
if (typeof schema.exclusiveMaximum === "number" && value >= schema.exclusiveMaximum) {
|
|
4265
|
+
value = schema.type === "integer" ? Math.ceil(schema.exclusiveMaximum) - 1 : schema.exclusiveMaximum - 0.1;
|
|
4266
|
+
}
|
|
4267
|
+
return value;
|
|
4048
4268
|
}
|
|
4269
|
+
if (schema.type === "string") return sampleString(schema, hint);
|
|
4049
4270
|
if (schema.type === "null") return null;
|
|
4050
4271
|
if (schema.type === "object" || isRecord4(schema.properties)) {
|
|
4051
4272
|
const properties = isRecord4(schema.properties) ? schema.properties : {};
|
|
4052
4273
|
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
4053
|
-
const entries = Object.entries(properties).filter(([key]) => required.has(key)).map(([key, child]) => [key, sampleForSchema(child, depth + 1)]);
|
|
4274
|
+
const entries = Object.entries(properties).filter(([key]) => required.has(key)).map(([key, child]) => [key, sampleForSchema(child, depth + 1, key, rootSchema)]);
|
|
4054
4275
|
return Object.fromEntries(entries);
|
|
4055
4276
|
}
|
|
4056
4277
|
return null;
|
|
@@ -4126,7 +4347,11 @@ function enrichActionContract(manifest, action, allActions = manifest.actions ||
|
|
|
4126
4347
|
const recovery = isRecord4(existing.recovery) ? existing.recovery : recoveryFor(action, allActions, appId);
|
|
4127
4348
|
const rollbackActionId = typeof existing.rollbackActionId === "string" && existing.rollbackActionId.trim() ? existing.rollbackActionId.trim() : recovery.mode === "compensating_action" ? recovery.actionId : void 0;
|
|
4128
4349
|
const inputExample = sampleForSchema(action.inputSchema);
|
|
4129
|
-
const
|
|
4350
|
+
const expectedExample = readOnly ? `A successful response conforming to outputSchema; verify the returned ${resource.replaceAll("_", " ")} belongs to the selected resource context.` : `A successful response conforming to outputSchema; re-read the affected ${resource.replaceAll("_", " ")} to verify the intended change.`;
|
|
4351
|
+
const examples = Array.isArray(existing.examples) && existing.examples.length > 0 ? existing.examples.map((example) => isRecord4(example) && Object.hasOwn(example, "input") ? { ...example, expected: typeof example.expected === "string" && example.expected.trim() ? example.expected : expectedExample } : { input: example, expected: expectedExample }) : [{
|
|
4352
|
+
input: inputExample ?? {},
|
|
4353
|
+
expected: expectedExample
|
|
4354
|
+
}];
|
|
4130
4355
|
const docsUrl = `https://docs.topolo.app/reference/actions?service=${encodeURIComponent(service)}&action=${encodeURIComponent(action.name)}`;
|
|
4131
4356
|
const existingDocsUrl = typeof existing.docsUrl === "string" && existing.docsUrl.trim() ? existing.docsUrl.trim() : void 0;
|
|
4132
4357
|
return {
|
|
@@ -4766,9 +4991,15 @@ export {
|
|
|
4766
4991
|
TopoloSdkError,
|
|
4767
4992
|
WorkspacesModule,
|
|
4768
4993
|
actionContractCompleteness,
|
|
4994
|
+
applicationEntryFromCatalog,
|
|
4769
4995
|
applicationRequirementScopes,
|
|
4770
4996
|
auditAllApplicationRequirements,
|
|
4997
|
+
auditApplicationEntries,
|
|
4771
4998
|
auditApplicationRequirements,
|
|
4999
|
+
compactActionCatalogEntry,
|
|
5000
|
+
compactActionPlan,
|
|
5001
|
+
compactActionValidation,
|
|
5002
|
+
compactApplicationAudit,
|
|
4772
5003
|
createTopolo,
|
|
4773
5004
|
createTopoloWidgetError,
|
|
4774
5005
|
createTopoloWidgetResponse,
|
|
@@ -4779,12 +5010,17 @@ export {
|
|
|
4779
5010
|
defineTopoloStatsWidget,
|
|
4780
5011
|
digestTopoloActionCatalog,
|
|
4781
5012
|
enrichActionContract,
|
|
5013
|
+
formatDirectoryApplicationIds,
|
|
5014
|
+
friendlyAppId,
|
|
5015
|
+
listApplicationDirectory,
|
|
4782
5016
|
parseTopoloActionUploadContract,
|
|
4783
5017
|
prepareTopoloActionBase64UploadInput,
|
|
4784
5018
|
prepareTopoloActionUploadInput,
|
|
4785
5019
|
requirementsForApplication,
|
|
5020
|
+
resolveApplicationDirectoryEntry,
|
|
4786
5021
|
resolveCatalogServiceUrl,
|
|
4787
5022
|
resolveServiceUrl,
|
|
5023
|
+
staticApplicationDirectory,
|
|
4788
5024
|
validateTopoloActionInput,
|
|
4789
5025
|
validateTopoloWidgetResponse
|
|
4790
5026
|
};
|
|
@@ -105,59 +105,10 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
-
// src/services.
|
|
108
|
+
// src/bootstrap-services.ts
|
|
109
109
|
var APP_API_URLS = {
|
|
110
|
-
agent: "https://agent.topolo.app",
|
|
111
110
|
auth: "https://auth.topolo.app",
|
|
112
|
-
|
|
113
|
-
blog: "https://blog.topolo.app",
|
|
114
|
-
books: "https://books.topolo.app",
|
|
115
|
-
brand: "https://brand.topolo.app",
|
|
116
|
-
bugfix: "https://bugfix.topolo.app",
|
|
117
|
-
bytes: "https://bytes.topolo.app",
|
|
118
|
-
calendar: "https://calendar.topolo.app",
|
|
119
|
-
campaigns: "https://campaigns.topolo.app",
|
|
120
|
-
capacity: "https://capacity.topolo.app",
|
|
121
|
-
chat: "https://chat.topolo.app",
|
|
122
|
-
commerce: "https://commerce.topolo.app",
|
|
123
|
-
compose: "https://compose.topolo.app",
|
|
124
|
-
consent: "https://consent.topolo.app",
|
|
125
|
-
crm: "https://crm.topolo.app",
|
|
126
|
-
design: "https://design.topolo.app",
|
|
127
|
-
developers: "https://developers.topolo.app",
|
|
128
|
-
director: "https://director.topolo.app",
|
|
129
|
-
feed: "https://feed.topolo.app",
|
|
130
|
-
flow: "https://flow.topolo.app",
|
|
131
|
-
forecast: "https://forecast.topolo.app",
|
|
132
|
-
forms: "https://forms.topolo.app",
|
|
133
|
-
home: "https://home.topolo.app",
|
|
134
|
-
insights: "https://insights.topolo.app",
|
|
135
|
-
inventory: "https://inventory.topolo.app",
|
|
136
|
-
learn: "https://learn.topolo.app",
|
|
137
|
-
localize: "https://localize.topolo.app",
|
|
138
|
-
mail: "https://mail.topolo.app",
|
|
139
|
-
mdm: "https://mdm.topolo.app",
|
|
140
|
-
messages: "https://messages.topolo.app",
|
|
141
|
-
nexus: "https://nexus.topolo.app",
|
|
142
|
-
notify: "https://notify.topolo.app",
|
|
143
|
-
observability_watch: "https://observability-watch.topolo.app",
|
|
144
|
-
one: "https://www.topolo.app",
|
|
145
|
-
p2p: "https://p2p.topolo.app",
|
|
146
|
-
pay: "https://pay.topolo.app",
|
|
147
|
-
people: "https://people.topolo.app",
|
|
148
|
-
"quro.api": "https://api.ol0.me",
|
|
149
|
-
"quro.redirect": "https://ol0.me",
|
|
150
|
-
roadmapper: "https://roadmapper.topolo.app",
|
|
151
|
-
sign: "https://sign.topolo.app",
|
|
152
|
-
social_studio: "https://studio.topolo.app",
|
|
153
|
-
socialize: "https://socialize.topolo.app",
|
|
154
|
-
spaces: "https://spaces.topolo.app",
|
|
155
|
-
status: "https://status.topolo.app",
|
|
156
|
-
success: "https://success.topolo.app",
|
|
157
|
-
support: "https://support.topolo.app",
|
|
158
|
-
survey: "https://survey.topolo.app",
|
|
159
|
-
voice: "https://voice.topolo.app",
|
|
160
|
-
web: "https://web.topolo.app"
|
|
111
|
+
developers: "https://developers.topolo.app"
|
|
161
112
|
};
|
|
162
113
|
|
|
163
114
|
// src/services.ts
|
|
@@ -61,59 +61,10 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
// src/services.
|
|
64
|
+
// src/bootstrap-services.ts
|
|
65
65
|
var APP_API_URLS = {
|
|
66
|
-
agent: "https://agent.topolo.app",
|
|
67
66
|
auth: "https://auth.topolo.app",
|
|
68
|
-
|
|
69
|
-
blog: "https://blog.topolo.app",
|
|
70
|
-
books: "https://books.topolo.app",
|
|
71
|
-
brand: "https://brand.topolo.app",
|
|
72
|
-
bugfix: "https://bugfix.topolo.app",
|
|
73
|
-
bytes: "https://bytes.topolo.app",
|
|
74
|
-
calendar: "https://calendar.topolo.app",
|
|
75
|
-
campaigns: "https://campaigns.topolo.app",
|
|
76
|
-
capacity: "https://capacity.topolo.app",
|
|
77
|
-
chat: "https://chat.topolo.app",
|
|
78
|
-
commerce: "https://commerce.topolo.app",
|
|
79
|
-
compose: "https://compose.topolo.app",
|
|
80
|
-
consent: "https://consent.topolo.app",
|
|
81
|
-
crm: "https://crm.topolo.app",
|
|
82
|
-
design: "https://design.topolo.app",
|
|
83
|
-
developers: "https://developers.topolo.app",
|
|
84
|
-
director: "https://director.topolo.app",
|
|
85
|
-
feed: "https://feed.topolo.app",
|
|
86
|
-
flow: "https://flow.topolo.app",
|
|
87
|
-
forecast: "https://forecast.topolo.app",
|
|
88
|
-
forms: "https://forms.topolo.app",
|
|
89
|
-
home: "https://home.topolo.app",
|
|
90
|
-
insights: "https://insights.topolo.app",
|
|
91
|
-
inventory: "https://inventory.topolo.app",
|
|
92
|
-
learn: "https://learn.topolo.app",
|
|
93
|
-
localize: "https://localize.topolo.app",
|
|
94
|
-
mail: "https://mail.topolo.app",
|
|
95
|
-
mdm: "https://mdm.topolo.app",
|
|
96
|
-
messages: "https://messages.topolo.app",
|
|
97
|
-
nexus: "https://nexus.topolo.app",
|
|
98
|
-
notify: "https://notify.topolo.app",
|
|
99
|
-
observability_watch: "https://observability-watch.topolo.app",
|
|
100
|
-
one: "https://www.topolo.app",
|
|
101
|
-
p2p: "https://p2p.topolo.app",
|
|
102
|
-
pay: "https://pay.topolo.app",
|
|
103
|
-
people: "https://people.topolo.app",
|
|
104
|
-
"quro.api": "https://api.ol0.me",
|
|
105
|
-
"quro.redirect": "https://ol0.me",
|
|
106
|
-
roadmapper: "https://roadmapper.topolo.app",
|
|
107
|
-
sign: "https://sign.topolo.app",
|
|
108
|
-
social_studio: "https://studio.topolo.app",
|
|
109
|
-
socialize: "https://socialize.topolo.app",
|
|
110
|
-
spaces: "https://spaces.topolo.app",
|
|
111
|
-
status: "https://status.topolo.app",
|
|
112
|
-
success: "https://success.topolo.app",
|
|
113
|
-
support: "https://support.topolo.app",
|
|
114
|
-
survey: "https://survey.topolo.app",
|
|
115
|
-
voice: "https://voice.topolo.app",
|
|
116
|
-
web: "https://web.topolo.app"
|
|
67
|
+
developers: "https://developers.topolo.app"
|
|
117
68
|
};
|
|
118
69
|
|
|
119
70
|
// src/services.ts
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"topoloPublishedVersion": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
|
+
"topoloPublishedVersion": "0.10.1",
|
|
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,12 +23,9 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"generate:services": "node scripts/generate-services.mjs",
|
|
27
|
-
"check:generated": "node scripts/check-generated.mjs",
|
|
28
|
-
"prebuild": "node scripts/generate-services.mjs",
|
|
29
26
|
"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
27
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
31
|
-
"typecheck": "
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
32
29
|
"test": "vitest run",
|
|
33
30
|
"test:watch": "vitest",
|
|
34
31
|
"prepublishOnly": "npm run build && npm run verify:package",
|